mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-19 01:18:32 +00:00
* fixes #21540; deref block at transf phase to make injectdestructors function properly * add a test case * add one more test * fixes the type of block * transform block
This commit is contained in:
@@ -752,21 +752,8 @@ proc isCppRef(p: BProc; typ: PType): bool {.inline.} =
|
||||
skipTypes(typ, abstractInstOwned).kind in {tyVar} and
|
||||
tfVarIsPtr notin skipTypes(typ, abstractInstOwned).flags
|
||||
|
||||
proc derefBlock(p: BProc, e: PNode, d: var TLoc) =
|
||||
# We transform (block: x)[] to (block: x[])
|
||||
let e0 = e[0]
|
||||
var n = shallowCopy(e0)
|
||||
n.typ = e.typ
|
||||
for i in 0 ..< e0.len - 1:
|
||||
n[i] = e0[i]
|
||||
n[e0.len-1] = newTreeIT(nkHiddenDeref, e.info, e.typ, e0[e0.len-1])
|
||||
expr p, n, d
|
||||
|
||||
proc genDeref(p: BProc, e: PNode, d: var TLoc) =
|
||||
if e.kind == nkHiddenDeref and e[0].kind in {nkBlockExpr, nkBlockStmt}:
|
||||
# bug #20107. Watch out to not deref the pointer too late.
|
||||
derefBlock(p, e, d)
|
||||
return
|
||||
assert e[0].kind notin {nkBlockExpr, nkBlockStmt}, "it should have been transformed in transf"
|
||||
|
||||
let mt = mapType(p.config, e[0].typ, mapTypeChooser(e[0]))
|
||||
if mt in {ctArray, ctPtrToArray} and lfEnforceDeref notin d.flags:
|
||||
|
||||
@@ -941,6 +941,15 @@ proc commonOptimizations*(g: ModuleGraph; idgen: IdGenerator; c: PSym, n: PNode)
|
||||
else:
|
||||
result = n
|
||||
|
||||
proc transformDerefBlock(c: PTransf, n: PNode): PNode =
|
||||
# We transform (block: x)[] to (block: x[])
|
||||
let e0 = n[0]
|
||||
result = shallowCopy(e0)
|
||||
result.typ = n.typ
|
||||
for i in 0 ..< e0.len - 1:
|
||||
result[i] = e0[i]
|
||||
result[e0.len-1] = newTreeIT(nkHiddenDeref, n.info, n.typ, e0[e0.len-1])
|
||||
|
||||
proc transform(c: PTransf, n: PNode): PNode =
|
||||
when false:
|
||||
var oldDeferAnchor: PNode
|
||||
@@ -1012,7 +1021,12 @@ proc transform(c: PTransf, n: PNode): PNode =
|
||||
of nkAddr:
|
||||
result = transformAddrDeref(c, n, {nkDerefExpr, nkHiddenDeref})
|
||||
of nkDerefExpr, nkHiddenDeref:
|
||||
result = transformAddrDeref(c, n, {nkAddr, nkHiddenAddr})
|
||||
if n[0].kind in {nkBlockExpr, nkBlockStmt}:
|
||||
# bug #20107 bug #21540. Watch out to not deref the pointer too late.
|
||||
let e = transformDerefBlock(c, n)
|
||||
result = transformBlock(c, e)
|
||||
else:
|
||||
result = transformAddrDeref(c, n, {nkAddr, nkHiddenAddr})
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
result = transformConv(c, n)
|
||||
of nkDiscardStmt:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
discard """
|
||||
cmd: "nim c -d:release -d:danger $file"
|
||||
matrix: ";--gc:orc"
|
||||
matrix: "--mm:refc -d:release -d:danger;--mm:orc -d:useMalloc -d:release -d:danger"
|
||||
output: "42"
|
||||
"""
|
||||
|
||||
@@ -23,3 +22,55 @@ proc m() =
|
||||
echo $f.a
|
||||
|
||||
m()
|
||||
|
||||
block: # bug #21540
|
||||
type
|
||||
Option = object
|
||||
val: string
|
||||
has: bool
|
||||
|
||||
proc some(val: string): Option =
|
||||
result.has = true
|
||||
result.val = val
|
||||
|
||||
# Remove lent and it works
|
||||
proc get(self: Option): lent string =
|
||||
result = self.val
|
||||
|
||||
type
|
||||
StringStream = ref object
|
||||
data: string
|
||||
pos: int
|
||||
|
||||
proc readAll(s: StringStream): string =
|
||||
result = newString(s.data.len)
|
||||
copyMem(addr(result[0]), addr(s.data[0]), s.data.len)
|
||||
|
||||
proc newStringStream(s: string = ""): StringStream =
|
||||
new(result)
|
||||
result.data = s
|
||||
|
||||
proc parseJson(s: string): string =
|
||||
let stream = newStringStream(s)
|
||||
result = stream.readAll()
|
||||
|
||||
proc main =
|
||||
let initialFEN = block:
|
||||
let initialFEN = some parseJson("startpos")
|
||||
initialFEN.get
|
||||
|
||||
doAssert initialFEN == "startpos"
|
||||
|
||||
main()
|
||||
|
||||
import std/[
|
||||
json,
|
||||
options
|
||||
]
|
||||
|
||||
block: # bug #21540
|
||||
let cheek = block:
|
||||
let initialFEN = some("""{"initialFen": "startpos"}""".parseJson{"initialFen"}.getStr)
|
||||
initialFEN.get
|
||||
|
||||
doAssert cheek == "startpos"
|
||||
|
||||
Reference in New Issue
Block a user