diff options
-rw-r--r-- | compiler/injectdestructors.nim | 47 | ||||
-rw-r--r-- | compiler/sempass2.nim | 2 | ||||
-rw-r--r-- | tests/arc/tarcmisc.nim | 26 |
3 files changed, 29 insertions, 46 deletions
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 01f72744a..aaa3db7f9 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -62,52 +62,6 @@ proc getTemp(c: var Con; s: var Scope; typ: PType; info: TLineInfo): PNode = proc nestedScope(parent: var Scope): Scope = 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 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 = # generate: (let tmp = v; reset(v); tmp) if not hasDestructor(n.typ): + assert n.kind != nkSym or not hasDestructor(n.sym.typ) result = copyTree(n) else: result = newNodeIT(nkStmtListExpr, n.info, n.typ) diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index f6fce712a..e9dcc7d8a 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -840,6 +840,8 @@ proc track(tracked: PEffects, n: PNode) = useVar(tracked, n) if n.sym.typ != nil and tfHasAsgn in n.sym.typ.flags: tracked.owner.flags.incl sfInjectDestructors + # bug #15038: ensure consistency + if not hasDestructor(n.typ): n.typ = n.sym.typ of nkHiddenAddr, nkAddr: if n[0].kind == nkSym and isLocalVar(tracked, n[0].sym): useVarNoInitCheck(tracked, n[0], n[0].sym) diff --git a/tests/arc/tarcmisc.nim b/tests/arc/tarcmisc.nim index d60e932a8..a7f2dd98b 100644 --- a/tests/arc/tarcmisc.nim +++ b/tests/arc/tarcmisc.nim @@ -25,6 +25,7 @@ new line before - @['a'] new line after - @['a'] finalizer aaaaa +hello closed destroying variable: 20 destroying variable: 10 @@ -293,3 +294,28 @@ proc mutstrings = echo data 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() |