summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorringabout <43030857+ringabout@users.noreply.github.com>2024-01-11 18:23:42 +0800
committerGitHub <noreply@github.com>2024-01-11 11:23:42 +0100
commit29ac3c9986de5731a32beaf015e81a18dd6bd498 (patch)
tree4bf31ac81104097e269658b3d5b132d157a93aa9
parent62c5b8b2873caac3e56d15738f503e953840e6ca (diff)
downloadNim-29ac3c9986de5731a32beaf015e81a18dd6bd498.tar.gz
fixes #22923; fixes `=dup` issues (#23182)
fixes #22923
-rw-r--r--compiler/ccgexprs.nim2
-rw-r--r--compiler/liftdestructors.nim10
-rw-r--r--compiler/semmagic.nim10
-rw-r--r--lib/system.nim3
-rw-r--r--tests/arc/tarcmisc.nim26
5 files changed, 49 insertions, 2 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 8cb9e208a..17e0da575 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -2587,6 +2587,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   of mTrace: discard "no code to generate"
   of mEnsureMove:
     expr(p, e[1], d)
+  of mDup:
+    expr(p, e[1], d)
   else:
     when defined(debugMagics):
       echo p.prc.name.s, " ", p.prc.id, " ", p.prc.flags, " ", p.prc.ast[genericParamsPos].kind
diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim
index 1180c2911..aba1aa38c 100644
--- a/compiler/liftdestructors.nim
+++ b/compiler/liftdestructors.nim
@@ -288,7 +288,7 @@ proc boolLit*(g: ModuleGraph; info: TLineInfo; value: bool): PNode =
 
 proc getCycleParam(c: TLiftCtx): PNode =
   assert c.kind in {attachedAsgn, attachedDup}
-  if c.fn.typ.signatureLen == 4:
+  if c.fn.typ.len == 3 + ord(c.kind == attachedAsgn):
     result = c.fn.typ.n.lastSon
     assert result.kind == nkSym
     assert result.sym.name.s == "cyclic"
@@ -323,6 +323,14 @@ proc newOpCall(c: var TLiftCtx; op: PSym; x: PNode): PNode =
   if sfNeverRaises notin op.flags:
     c.canRaise = true
 
+  if c.kind == attachedDup and op.typ.len == 3:
+    assert x != nil
+    if c.fn.typ.len == 3:
+      result.add getCycleParam(c)
+    else:
+      # assume the worst: A cycle is created:
+      result.add boolLit(c.g, x.info, true)
+
 proc newDeepCopyCall(c: var TLiftCtx; op: PSym; x, y: PNode): PNode =
   result = newAsgnStmt(x, newOpCall(c, op, y))
 
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index c36a9ede1..d1cd4d5da 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -635,6 +635,16 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
     let op = getAttachedOp(c.graph, t, attachedTrace)
     if op != nil:
       result[0] = newSymNode(op)
+  of mDup:
+    result = n
+    let t = n[1].typ.skipTypes(abstractVar)
+    let op = getAttachedOp(c.graph, t, attachedDup)
+    if op != nil:
+      result[0] = newSymNode(op)
+      if op.typ.len == 3:
+        let boolLit = newIntLit(c.graph, n.info, 1)
+        boolLit.typ = getSysType(c.graph, n.info, tyBool)
+        result.add boolLit
   of mWasMoved:
     result = n
     let t = n[1].typ.skipTypes(abstractVar)
diff --git a/lib/system.nim b/lib/system.nim
index 9ca9da302..1d08c70b4 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -2926,4 +2926,5 @@ proc arrayWith*[T](y: T, size: static int): array[size, T] {.raises: [].} =
     when nimvm:
       result[i] = y
     else:
-      result[i] = `=dup`(y)
+      {.cast(raises: []).}: # TODO: fixme bug #23129
+        result[i] = `=dup`(y)
diff --git a/tests/arc/tarcmisc.nim b/tests/arc/tarcmisc.nim
index 3b60fcd02..d02db545a 100644
--- a/tests/arc/tarcmisc.nim
+++ b/tests/arc/tarcmisc.nim
@@ -688,3 +688,29 @@ block: # bug #22259
     f(wrapper)
 
   main()
+
+block:
+  block: # bug #22923
+    block:
+      let
+        a: int = 100
+        b: int32 = 200'i32
+
+      let
+        x = arrayWith(a, 8) # compiles
+        y = arrayWith(b, 8) # internal error
+        z = arrayWith(14, 8) # integer literal also results in a crash
+
+      doAssert x == [100, 100, 100, 100, 100, 100, 100, 100]
+      doAssert $y == "[200, 200, 200, 200, 200, 200, 200, 200]"
+      doAssert z == [14, 14, 14, 14, 14, 14, 14, 14]
+
+    block:
+      let a: string = "nim"
+      doAssert arrayWith(a, 3) == ["nim", "nim", "nim"]
+
+      let b: char = 'c'
+      doAssert arrayWith(b, 3) == ['c', 'c', 'c']
+
+      let c: uint = 300'u
+      doAssert $arrayWith(c, 3) == "[300, 300, 300]"