From b40da812f7aa590ed16df54a492684c228320549 Mon Sep 17 00:00:00 2001 From: Bung Date: Wed, 2 Aug 2023 20:08:51 +0800 Subject: [PATCH] fix #22173 `sink` paramers not moved into closure (refc) (#22359) * use genRefAssign when assign to sink string * add test case --- compiler/ccgexprs.nim | 15 +++++++++------ tests/gc/t22173.nim | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 tests/gc/t22173.nim diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 712b874d93..8874f54ae3 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 0000000000..3fa3cc5038 --- /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