diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 8cb9e208a488c..17e0da57558bc 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 1180c29119c1f..aba1aa38c7020 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 c36a9ede1825e..d1cd4d5daa358 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 9ca9da3027f30..1d08c70b4e16d 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 3b60fcd020232..d02db545a16e5 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]"