summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/injectdestructors.nim8
-rw-r--r--compiler/lambdalifting.nim15
-rw-r--r--tests/destructor/tlists.nim9
3 files changed, 24 insertions, 8 deletions
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim
index 8d975e69e..0bb192036 100644
--- a/compiler/injectdestructors.nim
+++ b/compiler/injectdestructors.nim
@@ -32,7 +32,7 @@ type
     uninit: IntSet # set of uninit'ed vars
     uninitComputed: bool
 
-const toDebug = "" # "server" # "serverNimAsyncContinue"
+const toDebug {.strdefine.} = "" # "server" # "serverNimAsyncContinue"
 
 template dbg(body) =
   when toDebug.len > 0:
@@ -450,7 +450,11 @@ proc p(n: PNode; c: var Con): PNode =
     for i in 1..<n.len:
       n[i] = pArg(n[i], c, i < L and isSinkTypeForParam(parameters[i]))
     result = n
-  of nkDiscardStmt: #Small optimization
+    if result[0].kind == nkSym and result[0].sym.magic in {mNew, mNewFinalize}:
+      if c.graph.config.selectedGC in {gcHooks, gcDestructors}:
+        let destroyOld = genDestroy(c, result[1])
+        result = newTree(nkStmtList, destroyOld, result)
+  of nkDiscardStmt: # Small optimization
     if n[0].kind != nkEmpty:
       n[0] = pArg(n[0], c, false)
     result = n
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 15ab7ec0a..9a12fb192 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -233,9 +233,12 @@ proc liftingHarmful(conf: ConfigRef; owner: PSym): bool {.inline.} =
   let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro
   result = conf.cmd == cmdCompileToJS and not isCompileTime
 
-proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo) =
+proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo; owner: PSym) =
   createTypeBoundOps(g, nil, refType.lastSon, info)
   createTypeBoundOps(g, nil, refType, info)
+  if (tfHasAsgn in refType.flags) or
+      optSeqDestructors in g.config.globalOptions:
+    owner.flags.incl sfInjectDestructors
 
 proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
   # transforms  (iter)  to  (let env = newClosure[iter](); (iter, env))
@@ -261,7 +264,7 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
     result.add(v)
   # add 'new' statement:
   result.add newCall(getSysSym(g, n.info, "internalNew"), env)
-  createTypeBoundOpsLL(g, env.typ, n.info)
+  createTypeBoundOpsLL(g, env.typ, n.info, owner)
   result.add makeClosure(g, iter, env, n.info)
 
 proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode =
@@ -592,7 +595,7 @@ proc rawClosureCreation(owner: PSym;
       let env2 = copyTree(env)
       env2.typ = unowned.typ
       result.add newAsgnStmt(unowned, env2, env.info)
-      createTypeBoundOpsLL(d.graph, unowned.typ, env.info)
+      createTypeBoundOpsLL(d.graph, unowned.typ, env.info, owner)
 
     # add assignment statements for captured parameters:
     for i in 1..<owner.typ.n.len:
@@ -615,7 +618,7 @@ proc rawClosureCreation(owner: PSym;
       localError(d.graph.config, env.info, "internal error: cannot create up reference")
   # we are not in the sem'check phase anymore! so pass 'nil' for the PContext
   # and hope for the best:
-  createTypeBoundOpsLL(d.graph, env.typ, owner.info)
+  createTypeBoundOpsLL(d.graph, env.typ, owner.info, owner)
 
 proc finishClosureCreation(owner: PSym; d: DetectionPass; c: LiftingPass;
                            info: TLineInfo; res: PNode) =
@@ -643,7 +646,7 @@ proc closureCreationForIter(iter: PNode;
     addVar(vs, vnode)
     result.add(vs)
   result.add(newCall(getSysSym(d.graph, iter.info, "internalNew"), vnode))
-  createTypeBoundOpsLL(d.graph, vnode.typ, iter.info)
+  createTypeBoundOpsLL(d.graph, vnode.typ, iter.info, owner)
 
   let upField = lookupInRecord(v.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(d.graph.cache, upName))
   if upField != nil:
@@ -926,7 +929,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
     result.add(v)
     # add 'new' statement:
     result.add(newCall(getSysSym(g, env.info, "internalNew"), env.newSymNode))
-    createTypeBoundOpsLL(g, env.typ, body.info)
+    createTypeBoundOpsLL(g, env.typ, body.info, owner)
 
   elif op.kind == nkStmtListExpr:
     let closure = op.lastSon
diff --git a/tests/destructor/tlists.nim b/tests/destructor/tlists.nim
index a9c78ab75..78c09b105 100644
--- a/tests/destructor/tlists.nim
+++ b/tests/destructor/tlists.nim
@@ -43,9 +43,18 @@ proc tlazyList =
   var x = LazyList(c: proc () = echo(dep))
   x.c()
 
+type
+  Foo = ref object
+
+proc tleakingNewStmt =
+  var x: Foo
+  for i in 0..10:
+    new(x)
+
 let startMem = getOccupiedMem()
 tlazyList()
 
 mkManyLeaks()
 tsimpleClosureIterator()
+tleakingNewStmt()
 echo getOccupiedMem() - startMem