fixes #15038 [backport:1.2]
This commit is contained in:
parent
624762cfb7
commit
aae998feff
3 changed files with 29 additions and 46 deletions
|
|
@ -62,52 +62,6 @@ proc getTemp(c: var Con; s: var Scope; typ: PType; info: TLineInfo): PNode =
|
||||||
proc nestedScope(parent: var Scope): Scope =
|
proc nestedScope(parent: var Scope): Scope =
|
||||||
Scope(vars: @[], wasMoved: @[], final: @[], needsTry: false, parent: addr(parent))
|
Scope(vars: @[], wasMoved: @[], final: @[], needsTry: false, parent: addr(parent))
|
||||||
|
|
||||||
proc optimize(s: var Scope) =
|
|
||||||
# optimize away simple 'wasMoved(x); destroy(x)' pairs.
|
|
||||||
#[ Unfortunately this optimization is only really safe when no exceptions
|
|
||||||
are possible, see for example:
|
|
||||||
|
|
||||||
proc main(inp: string; cond: bool) =
|
|
||||||
if cond:
|
|
||||||
try:
|
|
||||||
var s = ["hi", inp & "more"]
|
|
||||||
for i in 0..4:
|
|
||||||
use s
|
|
||||||
consume(s)
|
|
||||||
wasMoved(s)
|
|
||||||
finally:
|
|
||||||
destroy(x)
|
|
||||||
|
|
||||||
Now assume 'use' raises, then we shouldn't do the 'wasMoved(s)'
|
|
||||||
]#
|
|
||||||
proc findCorrespondingDestroy(final: seq[PNode]; moved: PNode): int =
|
|
||||||
# remember that it's destroy(addr(x))
|
|
||||||
for i in 0 ..< final.len:
|
|
||||||
if final[i] != nil and exprStructuralEquivalent(final[i][1].skipAddr, moved, strictSymEquality = true):
|
|
||||||
return i
|
|
||||||
return -1
|
|
||||||
|
|
||||||
var removed = 0
|
|
||||||
for i in 0 ..< s.wasMoved.len:
|
|
||||||
let j = findCorrespondingDestroy(s.final, s.wasMoved[i][1])
|
|
||||||
if j >= 0:
|
|
||||||
s.wasMoved[i] = nil
|
|
||||||
s.final[j] = nil
|
|
||||||
inc removed
|
|
||||||
if removed > 0:
|
|
||||||
template filterNil(field) =
|
|
||||||
var m = newSeq[PNode](s.field.len - removed)
|
|
||||||
var mi = 0
|
|
||||||
for i in 0 ..< s.field.len:
|
|
||||||
if s.field[i] != nil:
|
|
||||||
m[mi] = s.field[i]
|
|
||||||
inc mi
|
|
||||||
assert mi == m.len
|
|
||||||
s.field = m
|
|
||||||
|
|
||||||
filterNil(wasMoved)
|
|
||||||
filterNil(final)
|
|
||||||
|
|
||||||
proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode
|
proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode
|
||||||
proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope; isDecl = false): PNode
|
proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope; isDecl = false): PNode
|
||||||
|
|
||||||
|
|
@ -411,6 +365,7 @@ proc genDefaultCall(t: PType; c: Con; info: TLineInfo): PNode =
|
||||||
proc destructiveMoveVar(n: PNode; c: var Con; s: var Scope): PNode =
|
proc destructiveMoveVar(n: PNode; c: var Con; s: var Scope): PNode =
|
||||||
# generate: (let tmp = v; reset(v); tmp)
|
# generate: (let tmp = v; reset(v); tmp)
|
||||||
if not hasDestructor(n.typ):
|
if not hasDestructor(n.typ):
|
||||||
|
assert n.kind != nkSym or not hasDestructor(n.sym.typ)
|
||||||
result = copyTree(n)
|
result = copyTree(n)
|
||||||
else:
|
else:
|
||||||
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
|
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
|
||||||
|
|
|
||||||
|
|
@ -840,6 +840,8 @@ proc track(tracked: PEffects, n: PNode) =
|
||||||
useVar(tracked, n)
|
useVar(tracked, n)
|
||||||
if n.sym.typ != nil and tfHasAsgn in n.sym.typ.flags:
|
if n.sym.typ != nil and tfHasAsgn in n.sym.typ.flags:
|
||||||
tracked.owner.flags.incl sfInjectDestructors
|
tracked.owner.flags.incl sfInjectDestructors
|
||||||
|
# bug #15038: ensure consistency
|
||||||
|
if not hasDestructor(n.typ): n.typ = n.sym.typ
|
||||||
of nkHiddenAddr, nkAddr:
|
of nkHiddenAddr, nkAddr:
|
||||||
if n[0].kind == nkSym and isLocalVar(tracked, n[0].sym):
|
if n[0].kind == nkSym and isLocalVar(tracked, n[0].sym):
|
||||||
useVarNoInitCheck(tracked, n[0], n[0].sym)
|
useVarNoInitCheck(tracked, n[0], n[0].sym)
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ new line before - @['a']
|
||||||
new line after - @['a']
|
new line after - @['a']
|
||||||
finalizer
|
finalizer
|
||||||
aaaaa
|
aaaaa
|
||||||
|
hello
|
||||||
closed
|
closed
|
||||||
destroying variable: 20
|
destroying variable: 20
|
||||||
destroying variable: 10
|
destroying variable: 10
|
||||||
|
|
@ -293,3 +294,28 @@ proc mutstrings =
|
||||||
echo data
|
echo data
|
||||||
|
|
||||||
mutstrings()
|
mutstrings()
|
||||||
|
|
||||||
|
# bug #15038
|
||||||
|
|
||||||
|
type
|
||||||
|
Machine = ref object
|
||||||
|
hello: string
|
||||||
|
|
||||||
|
var machineTypes: seq[tuple[factory: proc(): Machine]]
|
||||||
|
|
||||||
|
proc registerMachine(factory: proc(): Machine) =
|
||||||
|
var mCreator = proc(): Machine =
|
||||||
|
result = factory()
|
||||||
|
|
||||||
|
machineTypes.add((factory: mCreator))
|
||||||
|
|
||||||
|
proc facproc(): Machine =
|
||||||
|
result = Machine(hello: "hello")
|
||||||
|
|
||||||
|
registerMachine(facproc)
|
||||||
|
|
||||||
|
proc createMachine =
|
||||||
|
for machine in machineTypes:
|
||||||
|
echo machine.factory().hello
|
||||||
|
|
||||||
|
createMachine()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue