summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/injectdestructors.nim47
-rw-r--r--compiler/sempass2.nim2
-rw-r--r--tests/arc/tarcmisc.nim26
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()