From 397eb361e92204825db8176f851d31b60f84cc16 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Thu, 17 Apr 2025 04:51:12 +0800 Subject: [PATCH] fixes #24879; Data getting wiped on copy with iterators and =copy on refc (#24880) fixes #24879 (cherry picked from commit 9f359e8d6d51a9742c8e3a5816a2a8de8497f4c7) --- compiler/liftdestructors.nim | 6 +++++- tests/arc/t19457.nim | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index e6b2979dbd..a9eb0263e9 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -1003,9 +1003,13 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) = # 'selectedGC' here to determine if we have the new runtime. discard considerUserDefinedOp(c, t, body, x, y) elif tfHasAsgn in t.flags: + # seqs with elements using custom hooks in refc if c.kind in {attachedAsgn, attachedSink, attachedDeepCopy}: body.add newSeqCall(c, x, y) - forallElements(c, t, body, x, y) + if c.kind == attachedWasMoved: + body.add genBuiltin(c, mWasMoved, "wasMoved", x) + else: + forallElements(c, t, body, x, y) else: defaultOp(c, t, body, x, y) of tyString: diff --git a/tests/arc/t19457.nim b/tests/arc/t19457.nim index 78447ce82a..05e2ae732b 100644 --- a/tests/arc/t19457.nim +++ b/tests/arc/t19457.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--gc:refc; --gc:arc" + matrix: "--mm:refc; --mm:arc" """ # bug #19457 @@ -13,4 +13,36 @@ proc gcd(x, y: seq[int]): seq[int] = b = c return a -doAssert gcd(@[1], @[2]) == @[1] \ No newline at end of file +doAssert gcd(@[1], @[2]) == @[1] + + + +import std/sequtils + +type IrrelevantType* = object + +proc `=copy`*(dest: var IrrelevantType, src: IrrelevantType) = + discard + +type + Inner* = object + value*: string + someField*: IrrelevantType + + Outer* = object + inner*: Inner + +iterator valueIt(self: Outer): Inner = + yield self.inner + +proc getValues*(self: var Outer): seq[Inner] = + var peers = self.valueIt().toSeq + return peers + +var outer = Outer() + +outer.inner = Inner(value: "hello, world") + +doAssert (outer.valueIt().toSeq)[0].value == "hello, world" # Passes +doAssert outer.inner.value == "hello, world" # Passes too, original value is doing fine +doAssert outer.getValues()[0].value == "hello, world" # Fails, value is empty