summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/injectdestructors.nim15
-rw-r--r--compiler/lowerings.nim5
-rw-r--r--tests/arc/tmovebug.nim11
3 files changed, 22 insertions, 9 deletions
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim
index dc431ef38..bdd624281 100644
--- a/compiler/injectdestructors.nim
+++ b/compiler/injectdestructors.nim
@@ -251,7 +251,8 @@ proc canBeMoved(c: Con; t: PType): bool {.inline.} =
     result = t.attachedOps[attachedSink] != nil
 
 proc genSink(c: var Con; dest, ri: PNode): PNode =
-  if isFirstWrite(dest, c): # optimize sink call into a bitwise memcopy
+  if isUnpackedTuple(dest) or isFirstWrite(dest, c):
+    # optimize sink call into a bitwise memcopy
     result = newTree(nkFastAsgn, dest, ri)
   else:
     let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
@@ -592,6 +593,9 @@ proc p(n: PNode; c: var Con; mode: ProcessMode): PNode =
               # make sure it's destroyed at the end of the proc:
               if not isUnpackedTuple(v):
                 c.destroys.add genDestroy(c, v)
+              elif c.inLoop > 0:
+                # unpacked tuple needs reset at every loop iteration
+                result.add newTree(nkFastAsgn, v, genDefaultCall(v.typ, c, v.info))
             if ri.kind == nkEmpty and c.inLoop > 0:
               ri = genDefaultCall(v.typ, c, v.info)
             if ri.kind != nkEmpty:
@@ -660,14 +664,11 @@ proc p(n: PNode; c: var Con; mode: ProcessMode): PNode =
 proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
   case ri.kind
   of nkCallKinds:
-    if isUnpackedTuple(dest):
-      result = newTree(nkFastAsgn, dest, p(ri, c, consumed))
-    else:
-      result = genSink(c, dest, p(ri, c, consumed))
+    result = genSink(c, dest, p(ri, c, consumed))
   of nkBracketExpr:
     if isUnpackedTuple(ri[0]):
-      # unpacking of tuple: take over elements
-      result = newTree(nkFastAsgn, dest, p(ri, c, consumed))
+      # unpacking of tuple: take over the elements
+      result = genSink(c, dest, p(ri, c, consumed))
     elif isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c) and
         not aliases(dest, ri):
       # Rule 3: `=sink`(x, z); wasMoved(z)
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index b3b6cbb5c..d569c4dc9 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -74,8 +74,9 @@ proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
   result.add(v)
 
   for i in 0..<n.len-2:
-    if n[i].kind == nkSym: v.addVar(n[i])
-    result.add newAsgnStmt(n[i], newTupleAccess(g, tempAsNode, i))
+    let val = newTupleAccess(g, tempAsNode, i)
+    if n[i].kind == nkSym: v.addVar(n[i], val)
+    else: result.add newAsgnStmt(n[i], val)
 
 proc evalOnce*(g: ModuleGraph; value: PNode; owner: PSym): PNode =
   ## Turns (value) into (let tmp = value; tmp) so that 'value' can be re-used
diff --git a/tests/arc/tmovebug.nim b/tests/arc/tmovebug.nim
index 883543877..95bfb8202 100644
--- a/tests/arc/tmovebug.nim
+++ b/tests/arc/tmovebug.nim
@@ -86,3 +86,14 @@ proc tbug13314 =
   execute()
 
 tbug13314()
+
+#-------------------------------------------------------------------------
+# bug #13368
+
+import strutils
+proc procStat() =
+  for line in @["a b", "c d", "e f"]:
+    let cols = line.splitWhitespace(maxSplit=1)
+    let x = cols[0]
+    let (nm, rest) = (cols[0], cols[1])
+procStat()
\ No newline at end of file