summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2019-04-17 17:26:59 +0200
committerAraq <rumpf_a@web.de>2019-04-17 17:26:59 +0200
commit7640a230fc6166bb7fcc18bcab4251d7f6dc6caf (patch)
treef5ff43cfe6f85b46eb2f4a3eef3f3c4ecbb59295
parent850e90ac303cf791369e5fe4827fa1ab2269bdad (diff)
downloadNim-7640a230fc6166bb7fcc18bcab4251d7f6dc6caf.tar.gz
fixes #11050
-rw-r--r--compiler/sempass2.nim18
-rw-r--r--compiler/transf.nim2
-rw-r--r--tests/destructor/tgcdestructors.nim21
3 files changed, 34 insertions, 7 deletions
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index f2a6a7891..996735804 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -738,7 +738,7 @@ proc track(tracked: PEffects, n: PNode) =
         mergeTags(tracked, effectList.sons[tagEffects], n)
         gcsafeAndSideeffectCheck()
     if a.kind != nkSym or a.sym.magic != mNBindSym:
-      for i in 1 ..< len(n): trackOperand(tracked, n.sons[i], paramType(op, i), a)
+      for i in 1 ..< n.len: trackOperand(tracked, n.sons[i], paramType(op, i), a)
     if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}:
       # may not look like an assignment, but it is:
       let arg = n.sons[1]
@@ -754,7 +754,7 @@ proc track(tracked: PEffects, n: PNode) =
       track(tracked, n.sons[i])
   of nkDotExpr:
     guardDotAccess(tracked, n)
-    for i in 0 ..< len(n): track(tracked, n.sons[i])
+    for i in 0 ..< n.len: track(tracked, n.sons[i])
   of nkCheckedFieldExpr:
     track(tracked, n.sons[0])
     if warnProveField in tracked.config.notes:
@@ -821,7 +821,7 @@ proc track(tracked: PEffects, n: PNode) =
   of nkForStmt, nkParForStmt:
     # we are very conservative here and assume the loop is never executed:
     let oldState = tracked.init.len
-    for i in 0 .. len(n)-3:
+    for i in 0 .. n.len-3:
       let it = n[i]
       track(tracked, it)
       if tracked.owner.kind != skMacro:
@@ -830,13 +830,19 @@ proc track(tracked: PEffects, n: PNode) =
             createTypeBoundOps(tracked.c, x.typ, x.info)
         else:
           createTypeBoundOps(tracked.c, it.typ, it.info)
-    for i in len(n)-2..len(n)-1:
-      track(tracked, n.sons[i])
+    let iterCall = n[n.len-2]
+    let loopBody = n[n.len-1]
+    if tracked.owner.kind != skMacro and iterCall.len > 1:
+      # XXX this is a bit hacky:
+      if iterCall[1].typ.skipTypes(abstractVar).kind notin {tyVarargs, tyOpenArray}:
+        createTypeBoundOps(tracked.c, iterCall[1].typ, iterCall[1].info)
+    track(tracked, iterCall)
+    track(tracked, loopBody)
     setLen(tracked.init, oldState)
   of nkObjConstr:
     when false: track(tracked, n.sons[0])
     let oldFacts = tracked.guards.s.len
-    for i in 1 ..< len(n):
+    for i in 1 ..< n.len:
       let x = n.sons[i]
       track(tracked, x)
       if x.sons[0].kind == nkSym and sfDiscriminant in x.sons[0].sym.flags:
diff --git a/compiler/transf.nim b/compiler/transf.nim
index c455e3319..25a8bc5dd 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -651,6 +651,8 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
       var t = formal.typ
       if formal.ast != nil and formal.ast.typ.destructor != nil and t.destructor == nil:
         t = formal.ast.typ # better use the type that actually has a destructor.
+      elif t.destructor == nil and arg.typ.destructor != nil:
+        t = arg.typ
       # generate a temporary and produce an assignment statement:
       var temp = newTemp(c, t, formal.info)
       #temp.sym.flags.incl sfCursor
diff --git a/tests/destructor/tgcdestructors.nim b/tests/destructor/tgcdestructors.nim
index 620ba7d66..c0a88e650 100644
--- a/tests/destructor/tgcdestructors.nim
+++ b/tests/destructor/tgcdestructors.nim
@@ -4,7 +4,8 @@ discard """
 ho
 ha
 @["arg", "asdfklasdfkl", "asdkfj", "dfasj", "klfjl"]
-22 22'''
+@[1, 2, 3]
+25 25'''
 """
 
 import allocators
@@ -132,6 +133,24 @@ proc other =
 
 other()
 
+# bug #11050
+
+type
+  Obj* = object
+    f*: seq[int]
+
+method main(o: Obj) =
+  for newb in o.f:
+    discard
+
+# test that o.f was not moved!
+proc testforNoMove =
+  var o = Obj(f: @[1, 2, 3])
+  main(o)
+  echo o.f
+
+testforNoMove()
+
 #echo s
 let (a, d) = allocCounters()
 discard cprintf("%ld %ld\n", a, d)