summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/system/arc.nim6
-rw-r--r--tests/arc/tunref_cycle.nim26
2 files changed, 28 insertions, 4 deletions
diff --git a/lib/system/arc.nim b/lib/system/arc.nim
index ed5e9f5ca..d66f4b997 100644
--- a/lib/system/arc.nim
+++ b/lib/system/arc.nim
@@ -207,10 +207,8 @@ proc nimDecRefIsLast(p: pointer): bool {.compilerRtl, inl.} =
 
 proc GC_unref*[T](x: ref T) =
   ## New runtime only supports this operation for 'ref T'.
-  if nimDecRefIsLast(cast[pointer](x)):
-    # XXX this does NOT work for virtual destructors!
-    `=destroy`(x[])
-    nimRawDispose(cast[pointer](x), T.alignOf)
+  var y {.cursor.} = x
+  `=destroy`(y)
 
 proc GC_ref*[T](x: ref T) =
   ## New runtime only supports this operation for 'ref T'.
diff --git a/tests/arc/tunref_cycle.nim b/tests/arc/tunref_cycle.nim
new file mode 100644
index 000000000..82551b7f7
--- /dev/null
+++ b/tests/arc/tunref_cycle.nim
@@ -0,0 +1,26 @@
+discard """
+  outputsub: '''inside closure
+hello world'''
+  cmd: "nim c --gc:orc -d:useMalloc $file"
+  valgrind: true
+"""
+
+# bug #18579
+
+var fp: proc (env: pointer) {.cdecl.}
+var env: pointer
+
+proc store(f: proc (){.closure.}) =
+  proc closeOver() =
+    echo "inside closure"
+    f()
+  (fp,env) = (cast[proc(env: pointer){.cdecl.}](rawProc closeOver), rawEnv closeOver)
+  GC_ref(cast[RootRef](env))
+
+proc run() =
+  fp(env)
+  GC_unref(cast[RootRef](env))
+
+store(proc() = echo "hello world")
+run()
+GC_fullCollect()