summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBung <crc32@qq.com>2023-08-02 20:08:51 +0800
committerGitHub <noreply@github.com>2023-08-02 14:08:51 +0200
commitb40da812f7aa590ed16df54a492684c228320549 (patch)
tree89ea643f18a46af8f0ed7e99aeda02d23cb4c6d1
parent825a0e7df40100d92e87fc421a135a84b94f818f (diff)
downloadNim-b40da812f7aa590ed16df54a492684c228320549.tar.gz
fix #22173 `sink` paramers not moved into closure (refc) (#22359)
* use genRefAssign when assign to sink string

* add test case
-rw-r--r--compiler/ccgexprs.nim15
-rw-r--r--tests/gc/t22173.nim20
2 files changed, 29 insertions, 6 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 712b874d9..8874f54ae 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -342,12 +342,15 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
       if (dest.storage == OnStack and p.config.selectedGC != gcGo) or not usesWriteBarrier(p.config):
         linefmt(p, cpsStmts, "$1 = #copyString($2);$n", [dest.rdLoc, src.rdLoc])
       elif dest.storage == OnHeap:
-        # we use a temporary to care for the dreaded self assignment:
-        var tmp: TLoc
-        getTemp(p, ty, tmp)
-        linefmt(p, cpsStmts, "$3 = $1; $1 = #copyStringRC1($2);$n",
-                [dest.rdLoc, src.rdLoc, tmp.rdLoc])
-        linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", [tmp.rdLoc])
+        if dest.lode.typ.kind == tySink:
+          genRefAssign(p, dest, src)
+        else:
+          # we use a temporary to care for the dreaded self assignment:
+          var tmp: TLoc
+          getTemp(p, ty, tmp)
+          linefmt(p, cpsStmts, "$3 = $1; $1 = #copyStringRC1($2);$n",
+                  [dest.rdLoc, src.rdLoc, tmp.rdLoc])
+          linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", [tmp.rdLoc])
       else:
         linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
                [addrLoc(p.config, dest), rdLoc(src)])
diff --git a/tests/gc/t22173.nim b/tests/gc/t22173.nim
new file mode 100644
index 000000000..3fa3cc503
--- /dev/null
+++ b/tests/gc/t22173.nim
@@ -0,0 +1,20 @@
+discard """
+  cmd: '''nim c --gc:refc -r $file'''
+"""
+const Memo = 100 * 1024
+
+proc fff(v: sink string): iterator(): char =
+  return iterator(): char =
+    for c in v:
+      yield c
+
+var tmp = newString(Memo)
+
+let iter = fff(move(tmp))
+
+while true:
+  let v = iter()
+  if finished(iter):
+    break
+
+doAssert getOccupiedMem() < Memo * 3