summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim3
-rw-r--r--compiler/commands.nim13
-rw-r--r--compiler/injectdestructors.nim18
-rw-r--r--compiler/liftdestructors.nim14
-rw-r--r--compiler/transf.nim2
-rw-r--r--lib/core/runtime_v2.nim8
-rw-r--r--lib/core/strs.nim20
-rw-r--r--lib/system.nim33
-rw-r--r--tests/destructor/tgcdestructors.nim5
9 files changed, 73 insertions, 43 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index a21d9f738..0aeb94bb5 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1808,3 +1808,6 @@ template getBody*(s: PSym): PNode = s.ast[bodyPos]
 
 template detailedInfo*(sym: PSym): string =
   sym.name.s
+
+proc isInlineIterator*(s: PSym): bool {.inline.} =
+  s.kind == skIterator and s.typ.callConv != ccClosure
diff --git a/compiler/commands.nim b/compiler/commands.nim
index 0c574a079..6935e7747 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -745,12 +745,13 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
       conf.cppDefine(arg)
   of "newruntime":
     expectNoArg(conf, switch, arg, pass, info)
-    doAssert(conf != nil)
-    incl(conf.features, destructor)
-    incl(conf.globalOptions, optNimV2)
-    defineSymbol(conf.symbols, "nimV2")
-    conf.selectedGC = gcDestructors
-    defineSymbol(conf.symbols, "gcdestructors")
+    if pass in {passCmd2, passPP}:
+      doAssert(conf != nil)
+      incl(conf.features, destructor)
+      incl(conf.globalOptions, optNimV2)
+      defineSymbol(conf.symbols, "nimV2")
+      conf.selectedGC = gcDestructors
+      defineSymbol(conf.symbols, "gcdestructors")
   of "stylecheck":
     case arg.normalize
     of "off": conf.globalOptions = conf.globalOptions - {optStyleHint, optStyleError}
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim
index f1bda866b..350fd9c8d 100644
--- a/compiler/injectdestructors.nim
+++ b/compiler/injectdestructors.nim
@@ -456,7 +456,7 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
       result.add arg[0]
       for i in 1..<arg.len:
         result.add pArg(arg[i], c, i < L and parameters[i].kind == tySink)
-    elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkBracket, nkCharLit..nkFloat128Lit}:
+    elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkBracket, nkCharLit..nkTripleStrLit}:
       discard "object construction to sink parameter: nothing to do"
       result = arg
     elif arg.kind == nkSym and isSinkParam(arg.sym):
@@ -616,7 +616,21 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
     else:
       result = genCopy(c, dest.typ, dest, ri)
       result.add p(ri, c)
+  of nkHiddenSubConv, nkHiddenStdConv:
+    let harmless = ri[1].kind in (nkCallKinds + {nkSym, nkTupleConstr, nkObjConstr,
+                                                 nkBracket, nkBracketExpr, nkNilLit})
+    if harmless:
+      result = moveOrCopy(dest, ri[1], c)
+      var b = newNodeIT(ri.kind, ri.info, ri.typ)
+      b.add ri[0] # add empty node
+      let L = result.len-1
+      b.add result[L]
+      result[L] = b
+    else:
+      result = genCopy(c, dest.typ, dest, ri)
+      result.add p(ri, c)
   else:
+    # XXX At least string literals can be moved?
     result = genCopy(c, dest.typ, dest, ri)
     result.add p(ri, c)
 
@@ -725,7 +739,7 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
   when defined(nimDebugDestroys):
     if owner.name.s == "main":
       echo "injecting into ", n
-  if sfGeneratedOp in owner.flags: return n
+  if sfGeneratedOp in owner.flags or isInlineIterator(owner): return n
   var c: Con
   c.owner = owner
   c.destroys = newNodeI(nkStmtList, n.info)
diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim
index dba09b4ef..cfab1e221 100644
--- a/compiler/liftdestructors.nim
+++ b/compiler/liftdestructors.nim
@@ -309,13 +309,14 @@ proc seqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
 proc strOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
   case c.kind
   of attachedAsgn, attachedDeepCopy:
+    body.add callCodegenProc(c.graph, "nimAsgnStrV2", c.info, genAddr(c.graph, x), y)
     # we generate:
     # setLen(dest, y.len)
     # var i = 0
     # while i < y.len: dest[i] = y[i]; inc(i)
     # This is usually more efficient than a destroy/create pair.
-    body.add setLenStrCall(c.graph, x, y)
-    forallElements(c, t, body, x, y)
+    #body.add setLenStrCall(c.graph, x, y)
+    #forallElements(c, t, body, x, y)
   of attachedSink:
     let moveCall = genBuiltin(c.graph, mMove, "move", x)
     moveCall.add y
@@ -473,8 +474,11 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
      tyTypeDesc, tyGenericInvocation, tyForward:
     #internalError(c.graph.config, c.info, "assignment requested for type: " & typeToString(t))
     discard
+  of tyVar, tyLent:
+    if c.kind != attachedDestructor:
+      liftBodyAux(c, lastSon(t), body, x, y)
   of tyOrdinal, tyRange, tyInferred,
-     tyGenericInst, tyStatic, tyVar, tyLent, tyAlias, tySink:
+     tyGenericInst, tyStatic, tyAlias, tySink:
     liftBodyAux(c, lastSon(t), body, x, y)
 
 proc newProcType(info: TLineInfo; owner: PSym): PType =
@@ -650,7 +654,7 @@ proc createTypeBoundOps*(c: PContext; orig: PType; info: TLineInfo) =
     orig.assignment = canon.assignment
     orig.sink = canon.sink
 
-  #if not isTrival(orig.destructor):
+  if not isTrival(orig.destructor):
     #or not isTrival(orig.assignment) or
     # not isTrival(orig.sink):
-  #  orig.flags.incl tfHasAsgn
+    orig.flags.incl tfHasAsgn
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 640ed1136..a597123de 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -772,6 +772,8 @@ proc transformCall(c: PTransf, n: PNode): PTransNode =
   elif magic == mProcCall:
     # but do not change to its dispatcher:
     result = transformSons(c, n[1])
+  elif magic == mStrToStr:
+    result = transform(c, n[1])
   else:
     let s = transformSons(c, n).PNode
     # bugfix: check after 'transformSons' if it's still a method call:
diff --git a/lib/core/runtime_v2.nim b/lib/core/runtime_v2.nim
index 6463a5a27..f76fd2f3e 100644
--- a/lib/core/runtime_v2.nim
+++ b/lib/core/runtime_v2.nim
@@ -26,14 +26,6 @@ hash of ``package & "." & module & "." & name`` to save space.
 ]#
 
 type
-  TNimNode {.compilerProc.} = object # to keep the code generator simple
-  DestructorProc = proc (p: pointer) {.nimcall, benign.}
-  TNimType {.compilerProc.} = object
-    destructor: pointer
-    size: int
-    name: cstring
-  PNimType = ptr TNimType
-
   RefHeader = object
     rc: int # the object header is now a single RC field.
             # we could remove it in non-debug builds but this seems
diff --git a/lib/core/strs.nim b/lib/core/strs.nim
index 7dd65bdb3..ccc261d95 100644
--- a/lib/core/strs.nim
+++ b/lib/core/strs.nim
@@ -177,17 +177,15 @@ proc nimAsgnStrV2(a: var NimStringV2, b: NimStringV2) {.compilerRtl.} =
     frees(a)
     a.len = b.len
     a.p = b.p
-  elif isLiteral(a) or a.p.cap < b.len:
-    let allocator = if a.p != nil and a.p.allocator != nil: a.p.allocator else: getLocalAllocator()
-    # we have to allocate the 'cap' here, consider
-    # 'let y = newStringOfCap(); var x = y'
-    # on the other hand... These get turned into moves now.
-    a.p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(b.len)))
-    a.p.allocator = allocator
-    a.p.cap = b.len
-    a.len = b.len
-    copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1)
   else:
+    if isLiteral(a) or a.p.cap < b.len:
+      let allocator = if a.p != nil and a.p.allocator != nil: a.p.allocator else: getLocalAllocator()
+      # we have to allocate the 'cap' here, consider
+      # 'let y = newStringOfCap(); var x = y'
+      # on the other hand... These get turned into moves now.
+      frees(a)
+      a.p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(b.len)))
+      a.p.allocator = allocator
+      a.p.cap = b.len
     a.len = b.len
-    # reuse the storage we already have:
     copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1)
diff --git a/lib/system.nim b/lib/system.nim
index 9d0871490..f51767950 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -2971,6 +2971,30 @@ proc compiles*(x: untyped): bool {.magic: "Compiles", noSideEffect, compileTime.
 when not defined(js) and not defined(nimscript):
   include "system/ansi_c"
 
+when not defined(js):
+  {.push stackTrace:off.}
+
+  when hasThreadSupport and hostOS != "standalone":
+    const insideRLocksModule = false
+    include "system/syslocks"
+    include "system/threadlocalstorage"
+
+  when defined(nimV2):
+    type
+      TNimNode {.compilerProc.} = object # to keep the code generator simple
+      DestructorProc = proc (p: pointer) {.nimcall, benign.}
+      TNimType {.compilerProc.} = object
+        destructor: pointer
+        size: int
+        name: cstring
+      PNimType = ptr TNimType
+
+  when defined(gcDestructors) and not defined(nimscript):
+    include "core/strs"
+    include "core/seqs"
+
+  {.pop.}
+
 when not declared(sysFatal):
   include "system/fatal"
 
@@ -3481,15 +3505,6 @@ when not defined(JS): #and not defined(nimscript):
     when defined(endb):
       proc endbStep()
 
-  when hasThreadSupport and hostOS != "standalone":
-    const insideRLocksModule = false
-    include "system/syslocks"
-    include "system/threadlocalstorage"
-
-  when defined(gcDestructors) and not defined(nimscript):
-    include "core/strs"
-    include "core/seqs"
-
   when declared(newSeq):
     proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] =
       ## Converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be
diff --git a/tests/destructor/tgcdestructors.nim b/tests/destructor/tgcdestructors.nim
index 4b7f4ccb4..fa778f49d 100644
--- a/tests/destructor/tgcdestructors.nim
+++ b/tests/destructor/tgcdestructors.nim
@@ -3,7 +3,7 @@ discard """
   output: '''hi
 ho
 ha
-7 1'''
+7 7'''
 """
 
 import allocators
@@ -75,7 +75,7 @@ iterator interpolatedFragments*(s: string): tuple[kind: InterpolatedKind,
       break
     i = j
 
-when true:
+proc other =
   let input = "$test{}  $this is ${an{  example}}  "
   let expected = @[(ikVar, "test"), (ikStr, "{}  "), (ikVar, "this"),
                   (ikStr, " is "), (ikExpr, "an{  example}"), (ikStr, "  ")]
@@ -84,6 +84,7 @@ when true:
     doAssert s == expected[i]
     inc i
 
+other()
 
 #echo s
 let (a, d) = allocCounters()