From cedcb7881dd310d9e7e47860348274bd01795fb0 Mon Sep 17 00:00:00 2001 From: metagn Date: Mon, 20 Jan 2025 12:12:38 +0300 Subject: [PATCH] generate destructor in nodestroy proc for explicit destructor call (#24627) fixes #24626 `createTypeboundOps` in sempass2 is called when generating destructors for types including for explicit destructor calls, however it blocks destructors from getting generated in a `nodestroy` proc. This causes issues when a destructor is explicitly called in a `nodestroy` proc. To fix this, allow destructors to get generated only for explicit destructor calls in nodestroy procs. (cherry picked from commit 793baf34ff72cb8c5485ce209af086e27f656853) --- compiler/sempass2.nim | 7 ++++--- tests/arc/tnodestroyexplicithook.nim | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 tests/arc/tnodestroyexplicithook.nim diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 94aa22ae40..cef1b444fa 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -89,10 +89,11 @@ const errXCannotBeAssignedTo = "'$1' cannot be assigned to" errLetNeedsInit = "'let' symbol requires an initialization" -proc createTypeBoundOps(tracked: PEffects, typ: PType; info: TLineInfo) = - if typ == nil or sfGeneratedOp in tracked.owner.flags: +proc createTypeBoundOps(tracked: PEffects, typ: PType; info: TLineInfo; explicit = false) = + if typ == nil or (sfGeneratedOp in tracked.owner.flags and not explicit): # don't create type bound ops for anything in a function with a `nodestroy` pragma # bug #21987 + # unless this is an explicit call, bug #24626 return when false: let realType = typ.skipTypes(abstractInst) @@ -926,7 +927,7 @@ proc trackCall(tracked: PEffects; n: PNode) = # rebind type bounds operations after createTypeBoundOps call let t = n[1].typ.skipTypes({tyAlias, tyVar}) if a.sym != getAttachedOp(tracked.graph, t, TTypeAttachedOp(opKind)): - createTypeBoundOps(tracked, t, n.info) + createTypeBoundOps(tracked, t, n.info, explicit = true) let op = getAttachedOp(tracked.graph, t, TTypeAttachedOp(opKind)) if op != nil: n[0].sym = op diff --git a/tests/arc/tnodestroyexplicithook.nim b/tests/arc/tnodestroyexplicithook.nim new file mode 100644 index 0000000000..3342a53f5d --- /dev/null +++ b/tests/arc/tnodestroyexplicithook.nim @@ -0,0 +1,20 @@ +# issue #24626 + +proc arrayWith2[T](y: T, size: static int): array[size, T] {.noinit, nodestroy, raises: [].} = + ## Creates a new array filled with `y`. + for i in 0..size-1: + when defined(nimHasDup): + result[i] = `=dup`(y) + else: + wasMoved(result[i]) + `=copy`(result[i], y) + +proc useArray(x: seq[int]) = + var a = arrayWith2(x, 2) + +proc main = + let x = newSeq[int](100) + for i in 0..5: + useArray(x) + +main()