summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBung <crc32@qq.com>2023-08-06 15:46:43 +0800
committerGitHub <noreply@github.com>2023-08-06 15:46:43 +0800
commit95c751a9e4d42eb61917684339406d1ff07a4225 (patch)
tree53c01ddde433b1ba58fbd70beb76c7a9e0296015
parent137d608d7d68a91c99149aa1127dd675ee45f751 (diff)
downloadNim-95c751a9e4d42eb61917684339406d1ff07a4225.tar.gz
fix #15005; [ARC] Global variable declared in a block is destroyed too… (#22388)
* fix #15005 [ARC] Global variable declared in a block is destroyed too early
-rw-r--r--compiler/injectdestructors.nim3
-rw-r--r--tests/global/t15005.nim18
2 files changed, 20 insertions, 1 deletions
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim
index 590012806..15f375d28 100644
--- a/compiler/injectdestructors.nim
+++ b/compiler/injectdestructors.nim
@@ -1153,7 +1153,8 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, flags: set[MoveOrCopy
         let snk = c.genSink(s, dest, ri, flags)
         result = newTree(nkStmtList, snk, c.genWasMoved(ri))
       elif ri.sym.kind != skParam and ri.sym.owner == c.owner and
-          isLastRead(ri, c, s) and canBeMoved(c, dest.typ) and not isCursor(ri):
+          isLastRead(ri, c, s) and canBeMoved(c, dest.typ) and not isCursor(ri) and
+          {sfGlobal, sfPure} <= ri.sym.flags == false:
         # Rule 3: `=sink`(x, z); wasMoved(z)
         let snk = c.genSink(s, dest, ri, flags)
         result = newTree(nkStmtList, snk, c.genWasMoved(ri))
diff --git a/tests/global/t15005.nim b/tests/global/t15005.nim
new file mode 100644
index 000000000..6395b1dde
--- /dev/null
+++ b/tests/global/t15005.nim
@@ -0,0 +1,18 @@
+type
+  T = ref object
+    data: string
+
+template foo(): T =
+  var a15005 {.global.}: T
+  once:
+    a15005 = T(data: "hi")
+
+  a15005
+
+proc test() =
+  var b15005 = foo()
+
+  doAssert b15005.data == "hi"
+
+test()
+test()