diff options
-rw-r--r-- | compiler/ast.nim | 6 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 10 | ||||
-rw-r--r-- | compiler/injectdestructors.nim | 18 | ||||
-rw-r--r-- | compiler/liftdestructors.nim | 132 | ||||
-rw-r--r-- | lib/system.nim | 4 | ||||
-rw-r--r-- | lib/system/arc.nim | 4 | ||||
-rw-r--r-- | testament/important_packages.nim | 2 | ||||
-rw-r--r-- | tests/arc/tdup.nim | 7 | ||||
-rw-r--r-- | tests/arc/topt_no_cursor.nim | 15 | ||||
-rw-r--r-- | tests/arc/topt_wasmoved_destroy_pairs.nim | 3 | ||||
-rw-r--r-- | tests/destructor/tatomicptrs.nim | 10 | ||||
-rw-r--r-- | tests/destructor/tmatrix.nim | 5 | ||||
-rw-r--r-- | tests/destructor/tprevent_assign2.nim | 7 | ||||
-rw-r--r-- | tests/destructor/tprevent_assign3.nim | 7 | ||||
-rw-r--r-- | tests/destructor/tv2_cast.nim | 14 |
15 files changed, 151 insertions, 93 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index b27b16fe2..2a5f18809 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -944,10 +944,10 @@ type attachedWasMoved, attachedDestructor, attachedAsgn, + attachedDup, attachedSink, attachedTrace, - attachedDeepCopy, - attachedDup + attachedDeepCopy TType* {.acyclic.} = object of TIdObj # \ # types are identical iff they have the @@ -1518,7 +1518,7 @@ proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode, const AttachedOpToStr*: array[TTypeAttachedOp, string] = [ - "=wasMoved", "=destroy", "=copy", "=sink", "=trace", "=deepcopy", "=dup"] + "=wasMoved", "=destroy", "=copy", "=dup", "=sink", "=trace", "=deepcopy"] proc `$`*(s: PSym): string = if s != nil: diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 6702c7537..a1c81599c 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2359,11 +2359,6 @@ proc genMove(p: BProc; n: PNode; d: var TLoc) = genAssignment(p, d, a, {}) resetLoc(p, a) -proc genDup(p: BProc; src: TLoc; d: var TLoc; n: PNode) = - if d.k == locNone: getTemp(p, n.typ, d) - linefmt(p, cpsStmts, "#nimDupRef((void**)$1, (void*)$2);$n", - [addrLoc(p.config, d), rdLoc(src)]) - proc genDestroy(p: BProc; n: PNode) = if optSeqDestructors in p.config.globalOptions: let arg = n[1].skipAddr @@ -2615,11 +2610,6 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mAccessTypeField: genAccessTypeField(p, e, d) of mSlice: genSlice(p, e, d) of mTrace: discard "no code to generate" - of mDup: - var a: TLoc - let x = if e[1].kind in {nkAddr, nkHiddenAddr}: e[1][0] else: e[1] - initLocExpr(p, x, a) - genDup(p, a, d, e) else: when defined(debugMagics): echo p.prc.name.s, " ", p.prc.id, " ", p.prc.flags, " ", p.prc.ast[genericParamsPos].kind diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 3275c1abc..a03f85d02 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -188,7 +188,7 @@ template isUnpackedTuple(n: PNode): bool = proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string) = var m = "'" & opname & "' is not available for type <" & typeToString(t) & ">" - if (opname == "=" or opname == "=copy") and ri != nil: + if (opname == "=" or opname == "=copy" or opname == "=dup") and ri != nil: m.add "; requires a copy because it's not the last read of '" m.add renderTree(ri) m.add '\'' @@ -427,21 +427,17 @@ proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode = if hasDestructor(c, n.typ): let typ = n.typ.skipTypes({tyGenericInst, tyAlias, tySink}) let op = getAttachedOp(c.graph, typ, attachedDup) - if op != nil: + if op != nil and tfHasOwned notin typ.flags: + if sfError in op.flags: + c.checkForErrorPragma(n.typ, n, "=dup") let src = p(n, c, s, normal) - result.add newTreeI(nkFastAsgn, - src.info, tmp, - newTreeIT(nkCall, src.info, src.typ, + var newCall = newTreeIT(nkCall, src.info, src.typ, newSymNode(op), src) - ) - elif typ.kind == tyRef: - let src = p(n, c, s, normal) + c.finishCopy(newCall, n, isFromSink = true) result.add newTreeI(nkFastAsgn, src.info, tmp, - newTreeIT(nkCall, src.info, src.typ, - newSymNode(createMagic(c.graph, c.idgen, "`=dup`", mDup)), - src) + newCall ) else: result.add c.genWasMoved(tmp) diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index e8db14569..e8f25f1a3 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -34,6 +34,7 @@ type template destructor*(t: PType): PSym = getAttachedOp(c.g, t, attachedDestructor) template assignment*(t: PType): PSym = getAttachedOp(c.g, t, attachedAsgn) +template dup*(t: PType): PSym = getAttachedOp(c.g, t, attachedDup) template asink*(t: PType): PSym = getAttachedOp(c.g, t, attachedSink) proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) @@ -82,7 +83,7 @@ proc genBuiltin(c: var TLiftCtx; magic: TMagic; name: string; i: PNode): PNode = result = genBuiltin(c.g, c.idgen, magic, name, i) proc defaultOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = - if c.kind in {attachedAsgn, attachedDeepCopy, attachedSink}: + if c.kind in {attachedAsgn, attachedDeepCopy, attachedSink, attachedDup}: body.add newAsgnStmt(x, y) elif c.kind == attachedDestructor and c.addMemReset: let call = genBuiltin(c, mDefault, "default", x) @@ -283,7 +284,7 @@ proc boolLit*(g: ModuleGraph; info: TLineInfo; value: bool): PNode = result.typ = getSysType(g, info, tyBool) proc getCycleParam(c: TLiftCtx): PNode = - assert c.kind == attachedAsgn + assert c.kind in {attachedAsgn, attachedDup} if c.fn.typ.len == 4: result = c.fn.typ.n.lastSon assert result.kind == nkSym @@ -322,6 +323,9 @@ proc newOpCall(c: var TLiftCtx; op: PSym; x: PNode): PNode = proc newDeepCopyCall(c: var TLiftCtx; op: PSym; x, y: PNode): PNode = result = newAsgnStmt(x, newOpCall(c, op, y)) +proc newDupCall(c: var TLiftCtx; op: PSym; x, y: PNode): PNode = + result = newAsgnStmt(x, newOpCall(c, op, y)) + proc usesBuiltinArc(t: PType): bool = proc wrap(t: PType): bool {.nimcall.} = ast.isGCedMem(t) result = types.searchTypeFor(t, wrap) @@ -464,7 +468,18 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool = result = true of attachedDup: - assert false, "cannot happen" + var op = getAttachedOp(c.g, t, attachedDup) + if op != nil and sfOverriden in op.flags: + + if op.ast.isGenericRoutine: + # patch generic destructor: + op = instantiateGeneric(c, op, t, t.typeInst) + setAttachedOp(c.g, c.idgen.module, t, attachedDup, op) + + #markUsed(c.g.config, c.info, op, c.g.usageSym) + onUse(c.info, op) + body.add newDupCall(c, op, x, y) + result = true proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode = var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.idgen, c.fn, c.info) @@ -526,6 +541,9 @@ proc forallElements(c: var TLiftCtx; t: PType; body, x, y: PNode) = proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = case c.kind + of attachedDup: + body.add setLenSeqCall(c, t, x, y) + forallElements(c, t, body, x, y) of attachedAsgn, attachedDeepCopy: # we generate: # setLen(dest, y.len) @@ -549,15 +567,13 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = # follow all elements: forallElements(c, t, body, x, y) of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x) - of attachedDup: - assert false, "cannot happen" proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = createTypeBoundOps(c.g, c.c, t, body.info, c.idgen) # recursions are tricky, so we might need to forward the generated # operation here: var t = t - if t.assignment == nil or t.destructor == nil: + if t.assignment == nil or t.destructor == nil or t.dup == nil: let h = sighashes.hashType(t,c.g.config, {CoType, CoConsiderOwned, CoDistinct}) let canon = c.g.canonTypes.getOrDefault(h) if canon != nil: t = canon @@ -590,11 +606,15 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = body.add newHookCall(c, op, x, y) of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x) of attachedDup: - assert false, "cannot happen" + # XXX: replace these with assertions. + let op = getAttachedOp(c.g, t, c.kind) + if op == nil: + return # protect from recursion + body.add newDupCall(c, op, x, y) proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = case c.kind - of attachedAsgn, attachedDeepCopy: + of attachedAsgn, attachedDeepCopy, attachedDup: body.add callCodegenProc(c.g, "nimAsgnStrV2", c.info, genAddr(c, x), y) of attachedSink: let moveCall = genBuiltin(c, mMove, "move", x) @@ -607,8 +627,6 @@ proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = of attachedTrace: discard "strings are atomic and have no inner elements that are to trace" of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x) - of attachedDup: - assert false, "cannot happen" proc cyclicType*(g: ModuleGraph, t: PType): bool = case t.kind @@ -648,7 +666,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = # dynamic Acyclic refs need to use dyn decRef let tmp = - if isCyclic and c.kind in {attachedAsgn, attachedSink}: + if isCyclic and c.kind in {attachedAsgn, attachedSink, attachedDup}: declareTempOf(c, body, x) else: x @@ -709,7 +727,14 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = #echo "can follow ", elemType, " static ", isFinal(elemType) of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x) of attachedDup: - assert false, "cannot happen" + if isCyclic: + body.add newAsgnStmt(x, y) + body.add genIf(c, y, callCodegenProc(c.g, + "nimIncRefCyclic", c.info, y, getCycleParam(c))) + else: + body.add newAsgnStmt(x, y) + body.add genIf(c, y, callCodegenProc(c.g, + "nimIncRef", c.info, y)) proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = ## Closures are really like refs except they always use a virtual destructor @@ -719,7 +744,7 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = let isCyclic = c.g.config.selectedGC == gcOrc let tmp = - if isCyclic and c.kind in {attachedAsgn, attachedSink}: + if isCyclic and c.kind in {attachedAsgn, attachedSink, attachedDup}: declareTempOf(c, body, xenv) else: xenv @@ -753,14 +778,21 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = body.add genIf(c, cond, actions) body.add newAsgnStmt(x, y) + of attachedDup: + let yenv = genBuiltin(c, mAccessEnv, "accessEnv", y) + yenv.typ = getSysType(c.g, c.info, tyPointer) + if isCyclic: + body.add newAsgnStmt(x, y) + body.add genIf(c, yenv, callCodegenProc(c.g, "nimIncRefCyclic", c.info, yenv, getCycleParam(c))) + else: + body.add newAsgnStmt(x, y) + body.add genIf(c, yenv, callCodegenProc(c.g, "nimIncRef", c.info, yenv)) of attachedDestructor: body.add genIf(c, cond, actions) of attachedDeepCopy: assert(false, "cannot happen") of attachedTrace: body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(xenv, c.idgen), y) of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x) - of attachedDup: - assert false, "cannot happen" proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = case c.kind @@ -773,6 +805,9 @@ proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = body.add genIf(c, y, callCodegenProc(c.g, "nimIncRef", c.info, y)) body.add genIf(c, x, callCodegenProc(c.g, "nimDecWeakRef", c.info, x)) body.add newAsgnStmt(x, y) + of attachedDup: + body.add newAsgnStmt(x, y) + body.add genIf(c, y, callCodegenProc(c.g, "nimIncRef", c.info, y)) of attachedDestructor: # it's better to prepend the destruction of weak refs in order to # prevent wrong "dangling refs exist" problems: @@ -786,8 +821,6 @@ proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = of attachedDeepCopy: assert(false, "cannot happen") of attachedTrace: discard of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x) - of attachedDup: - assert false, "cannot happen" proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = var actions = newNodeI(nkStmtList, c.info) @@ -809,13 +842,13 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = of attachedSink, attachedAsgn: body.add genIf(c, x, actions) body.add newAsgnStmt(x, y) + of attachedDup: + body.add newAsgnStmt(x, y) of attachedDestructor: body.add genIf(c, x, actions) of attachedDeepCopy: assert(false, "cannot happen") of attachedTrace: discard of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x) - of attachedDup: - assert false, "cannot happen" proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = if c.kind == attachedDeepCopy: @@ -842,6 +875,11 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = body.add genIf(c, yy, callCodegenProc(c.g, "nimIncRef", c.info, yy)) body.add genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx)) body.add newAsgnStmt(x, y) + of attachedDup: + let yy = genBuiltin(c, mAccessEnv, "accessEnv", y) + yy.typ = getSysType(c.g, c.info, tyPointer) + body.add newAsgnStmt(x, y) + body.add genIf(c, yy, callCodegenProc(c.g, "nimIncRef", c.info, yy)) of attachedDestructor: let des = genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx)) if body.len == 0: @@ -851,8 +889,6 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = of attachedDeepCopy: assert(false, "cannot happen") of attachedTrace: discard of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x) - of attachedDup: - assert false, "cannot happen" proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = let xx = genBuiltin(c, mAccessEnv, "accessEnv", x) @@ -864,13 +900,13 @@ proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = of attachedSink, attachedAsgn: body.add genIf(c, xx, actions) body.add newAsgnStmt(x, y) + of attachedDup: + body.add newAsgnStmt(x, y) of attachedDestructor: body.add genIf(c, xx, actions) of attachedDeepCopy: assert(false, "cannot happen") of attachedTrace: discard of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x) - of attachedDup: - assert false, "cannot happen" proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) = case t.kind @@ -936,7 +972,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) = if not considerUserDefinedOp(c, t, body, x, y): if t.sym != nil and sfImportc in t.sym.flags: case c.kind - of {attachedAsgn, attachedSink}: + of {attachedAsgn, attachedSink, attachedDup}: body.add newAsgnStmt(x, y) of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x) @@ -976,8 +1012,44 @@ proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType; result = getAttachedOp(g, baseType, kind) setAttachedOp(g, idgen.module, typ, kind, result) +proc symDupPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp; + info: TLineInfo; idgen: IdGenerator): PSym = + let procname = getIdent(g.cache, AttachedOpToStr[kind]) + result = newSym(skProc, procname, idgen, owner, info) + let res = newSym(skResult, getIdent(g.cache, "result"), idgen, result, info) + let src = newSym(skParam, getIdent(g.cache, "src"), + idgen, result, info) + res.typ = typ + src.typ = typ + + result.typ = newType(tyProc, nextTypeId idgen, owner) + result.typ.n = newNodeI(nkFormalParams, info) + rawAddSon(result.typ, res.typ) + result.typ.n.add newNodeI(nkEffectList, info) + + result.typ.addParam src + + if g.config.selectedGC == gcOrc and + cyclicType(g, typ.skipTypes(abstractInst)): + let cycleParam = newSym(skParam, getIdent(g.cache, "cyclic"), + idgen, result, info) + cycleParam.typ = getSysType(g, info, tyBool) + result.typ.addParam cycleParam + + var n = newNodeI(nkProcDef, info, bodyPos+2) + for i in 0..<n.len: n[i] = newNodeI(nkEmpty, info) + n[namePos] = newSymNode(result) + n[paramsPos] = result.typ.n + n[bodyPos] = newNodeI(nkStmtList, info) + n[resultPos] = newSymNode(res) + result.ast = n + incl result.flags, sfFromGeneric + incl result.flags, sfGeneratedOp + proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp; info: TLineInfo; idgen: IdGenerator): PSym = + if kind == attachedDup: + return symDupPrototype(g, typ, owner, kind, info, idgen) let procname = getIdent(g.cache, AttachedOpToStr[kind]) result = newSym(skProc, procname, idgen, owner, info) @@ -992,7 +1064,7 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp result.typ = newProcType(info, nextTypeId(idgen), owner) result.typ.addParam dest - if kind notin {attachedDestructor, attachedWasMoved, attachedDup}: + if kind notin {attachedDestructor, attachedWasMoved}: result.typ.addParam src if kind == attachedAsgn and g.config.selectedGC == gcOrc and @@ -1033,9 +1105,11 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp; var a = TLiftCtx(info: info, g: g, kind: kind, c: c, asgnForType: typ, idgen: idgen, fn: result) - let dest = result.typ.n[1].sym - let d = newDeref(newSymNode(dest)) - let src = if kind in {attachedDestructor, attachedWasMoved, attachedDup}: newNodeIT(nkSym, info, getSysType(g, info, tyPointer)) + let dest = if kind == attachedDup: result.ast[resultPos].sym else: result.typ.n[1].sym + let d = if kind == attachedDup: newSymNode(dest) else: newDeref(newSymNode(dest)) + let src = case kind + of {attachedDestructor, attachedWasMoved}: newNodeIT(nkSym, info, getSysType(g, info, tyPointer)) + of attachedDup: newSymNode(result.typ.n[1].sym) else: newSymNode(result.typ.n[2].sym) # register this operation already: @@ -1059,7 +1133,7 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp; fillStrOp(a, typ, result.ast[bodyPos], d, src) else: fillBody(a, typ, result.ast[bodyPos], d, src) - if tk == tyObject and a.kind in {attachedAsgn, attachedSink, attachedDeepCopy} and not lacksMTypeField(typ): + if tk == tyObject and a.kind in {attachedAsgn, attachedSink, attachedDeepCopy, attachedDup} and not lacksMTypeField(typ): # bug #19205: Do not forget to also copy the hidden type field: genTypeFieldCopy(a, typ, result.ast[bodyPos], d, src) diff --git a/lib/system.nim b/lib/system.nim index f8523b094..b0d900076 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -137,7 +137,7 @@ proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {. ## **Note**: The `finalizer` refers to the type `T`, not to the object! ## This means that for each object of type `T` the finalizer will be called! -proc `=wasMoved`[T](obj: var T) {.magic: "WasMoved", noSideEffect.} = +proc `=wasMoved`*[T](obj: var T) {.magic: "WasMoved", noSideEffect.} = ## Generic `wasMoved`:idx: implementation that can be overridden. proc wasMoved*[T](obj: var T) {.inline, noSideEffect.} = @@ -354,7 +354,7 @@ proc `=destroy`*[T](x: var T) {.inline, magic: "Destroy".} = discard when defined(nimHasDup): - proc `=dup`*[T](x: ref T): ref T {.inline, magic: "Dup".} = + proc `=dup`*[T](x: T): T {.inline, magic: "Dup".} = ## Generic `dup`:idx: implementation that can be overridden. discard diff --git a/lib/system/arc.nim b/lib/system/arc.nim index cc93eb9fc..2186806d6 100644 --- a/lib/system/arc.nim +++ b/lib/system/arc.nim @@ -200,10 +200,6 @@ proc nimDecRefIsLast(p: pointer): bool {.compilerRtl, inl.} = when traceCollector: cprintf("[DECREF] %p\n", cell) -proc nimDupRef(dest: ptr pointer, src: pointer) {.compilerRtl, inl.} = - dest[] = src - if src != nil: nimIncRef src - proc GC_unref*[T](x: ref T) = ## New runtime only supports this operation for 'ref T'. var y {.cursor.} = x diff --git a/testament/important_packages.nim b/testament/important_packages.nim index e2d1024b1..1ab6f3f04 100644 --- a/testament/important_packages.nim +++ b/testament/important_packages.nim @@ -87,7 +87,7 @@ pkg "kdtree", "nimble test -d:nimLegacyRandomInitRand", "https://github.com/jbli pkg "loopfusion" pkg "lockfreequeues" pkg "macroutils" -pkg "manu" +pkg "manu", url = "https://github.com/nim-lang/manu" pkg "markdown" pkg "measuremancer", "nimble testDeps; nimble -y test" pkg "memo" diff --git a/tests/arc/tdup.nim b/tests/arc/tdup.nim index b77f5c6eb..61f262a68 100644 --- a/tests/arc/tdup.nim +++ b/tests/arc/tdup.nim @@ -18,7 +18,7 @@ inc: var id_1 = 777 s = RefCustom(id_2: addr(id_1)) inc_1 : - :tmpD_1 = `=dup`(s) + :tmpD_1 = `=dup_1`(s) :tmpD_1 inc_1 : let blitTmp_1 = s @@ -34,14 +34,15 @@ type RefCustom = object id: ptr int +proc `=dup`(x: RefCustom): RefCustom = + result.id = x.id + proc inc(x: sink Ref) = inc x.id proc inc(x: sink RefCustom) = inc x.id[] -proc `=dup`(x: RefCustom): RefCustom = - result.id = x.id proc foo = var x = Ref(id: 8) diff --git a/tests/arc/topt_no_cursor.nim b/tests/arc/topt_no_cursor.nim index 32652b60a..39e5c8a9b 100644 --- a/tests/arc/topt_no_cursor.nim +++ b/tests/arc/topt_no_cursor.nim @@ -61,11 +61,9 @@ var try: it_cursor = x a = ( - `=wasMoved`(:tmpD) - `=copy`(:tmpD, it_cursor.key) + :tmpD = `=dup`(it_cursor.key) :tmpD, - `=wasMoved`(:tmpD_1) - `=copy`(:tmpD_1, it_cursor.val) + :tmpD_1 = `=dup`(it_cursor.val) :tmpD_1) echo [ :tmpD_2 = `$$`(a) @@ -125,19 +123,16 @@ this.isValid = fileExists(this.value) if dirExists(this.value): var :tmpD par = (dir: - `=wasMoved`(:tmpD) - `=copy`(:tmpD, this.value) + :tmpD = `=dup`(this.value) :tmpD, front: "") else: var :tmpD_1 :tmpD_2 :tmpD_3 par = (dir_1: parentDir(this.value), front_1: - `=wasMoved`(:tmpD_1) - `=copy`(:tmpD_1, + :tmpD_1 = `=dup`( :tmpD_3 = splitDrive do: - `=wasMoved`(:tmpD_2) - `=copy`(:tmpD_2, this.value) + :tmpD_2 = `=dup`(this.value) :tmpD_2 :tmpD_3.path) :tmpD_1) diff --git a/tests/arc/topt_wasmoved_destroy_pairs.nim b/tests/arc/topt_wasmoved_destroy_pairs.nim index 6577d6787..c96340a30 100644 --- a/tests/arc/topt_wasmoved_destroy_pairs.nim +++ b/tests/arc/topt_wasmoved_destroy_pairs.nim @@ -39,8 +39,7 @@ try: if i_cursor == 2: return add(a): - `=wasMoved`(:tmpD) - `=copy`(:tmpD, x) + :tmpD = `=dup`(x) :tmpD inc i_1, 1 if cond: diff --git a/tests/destructor/tatomicptrs.nim b/tests/destructor/tatomicptrs.nim index 88f84d67c..7bd5482b2 100644 --- a/tests/destructor/tatomicptrs.nim +++ b/tests/destructor/tatomicptrs.nim @@ -39,7 +39,7 @@ proc `=destroy`*[T](dest: var SharedPtr[T]) = echo "deallocating" dest.x = nil -proc `=`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) = +proc `=copy`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) = var s = src.x if s != nil: incRef(s) #atomicSwap(dest, s) @@ -50,6 +50,9 @@ proc `=`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) = deallocShared(s) echo "deallocating" +proc `=dup`*[T](src: SharedPtr[T]): SharedPtr[T] = + `=copy`(result, src) + proc `=sink`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) = ## XXX make this an atomic store: if dest.x != src.x: @@ -120,7 +123,7 @@ proc `=destroy`*[T](m: var MySeq[T]) {.inline.} = deallocShared(m.data) m.data = nil -proc `=`*[T](m: var MySeq[T], m2: MySeq[T]) = +proc `=copy`*[T](m: var MySeq[T], m2: MySeq[T]) = if m.data == m2.data: return if m.data != nil: `=destroy`(m) @@ -131,6 +134,9 @@ proc `=`*[T](m: var MySeq[T], m2: MySeq[T]) = m.data = cast[ptr UncheckedArray[T]](allocShared(bytes)) copyMem(m.data, m2.data, bytes) +proc `=dup`*[T](m: MySeq[T]): MySeq[T] = + `=copy`[T](result, m) + proc `=sink`*[T](m: var MySeq[T], m2: MySeq[T]) {.inline.} = if m.data != m2.data: if m.data != nil: diff --git a/tests/destructor/tmatrix.nim b/tests/destructor/tmatrix.nim index 98ca95c94..2fd5af789 100644 --- a/tests/destructor/tmatrix.nim +++ b/tests/destructor/tmatrix.nim @@ -31,7 +31,7 @@ proc `=sink`*(a: var Matrix; b: Matrix) = a.m = b.m a.n = b.n -proc `=`*(a: var Matrix; b: Matrix) = +proc `=copy`*(a: var Matrix; b: Matrix) = if a.data != nil and a.data != b.data: dealloc(a.data) deallocCount.inc @@ -43,6 +43,9 @@ proc `=`*(a: var Matrix; b: Matrix) = allocCount.inc copyMem(a.data, b.data, b.m * b.n * sizeof(float)) +proc `=dup`*(a: Matrix): Matrix = + `=copy`(result, a) + proc matrix*(m, n: int, s: float): Matrix = ## Construct an m-by-n constant matrix. result.m = m diff --git a/tests/destructor/tprevent_assign2.nim b/tests/destructor/tprevent_assign2.nim index fd1a711db..7d788fa5c 100644 --- a/tests/destructor/tprevent_assign2.nim +++ b/tests/destructor/tprevent_assign2.nim @@ -1,7 +1,7 @@ discard """ - errormsg: "'=copy' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'" + errormsg: "'=dup' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'" file: "tprevent_assign2.nim" - line: 48 + line: 49 """ type @@ -9,7 +9,8 @@ type x: int proc `=destroy`(f: var Foo) = f.x = 0 -proc `=`(a: var Foo; b: Foo) {.error.} # = a.x = b.x +proc `=copy`(a: var Foo; b: Foo) {.error.} # = a.x = b.x +proc `=dup`(a: Foo): Foo {.error.} proc `=sink`(a: var Foo; b: Foo) = a.x = b.x proc createTree(x: int): Foo = diff --git a/tests/destructor/tprevent_assign3.nim b/tests/destructor/tprevent_assign3.nim index b9bd40fa9..aa834a66c 100644 --- a/tests/destructor/tprevent_assign3.nim +++ b/tests/destructor/tprevent_assign3.nim @@ -1,7 +1,7 @@ discard """ - errormsg: "'=copy' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'" + errormsg: "'=dup' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'" file: "tprevent_assign3.nim" - line: 46 + line: 47 """ type @@ -9,7 +9,8 @@ type x: int proc `=destroy`(f: var Foo) = f.x = 0 -proc `=`(a: var Foo; b: Foo) {.error.} # = a.x = b.x +proc `=copy`(a: var Foo; b: Foo) {.error.} # = a.x = b.x +proc `=dup`(a: Foo): Foo {.error.} proc `=sink`(a: var Foo; b: Foo) = a.x = b.x proc createTree(x: int): Foo = diff --git a/tests/destructor/tv2_cast.nim b/tests/destructor/tv2_cast.nim index 6fa419996..4ff2dc9a0 100644 --- a/tests/destructor/tv2_cast.nim +++ b/tests/destructor/tv2_cast.nim @@ -3,7 +3,7 @@ discard """ @[116, 101, 115, 116] @[1953719668, 875770417] destroying O1''' - cmd: '''nim c --gc:arc --expandArc:main --expandArc:main1 --expandArc:main2 --expandArc:main3 --hints:off --assertions:off $file''' + cmd: '''nim c --mm:arc --expandArc:main --expandArc:main1 --expandArc:main2 --expandArc:main3 --hints:off --assertions:off $file''' nimout: ''' --expandArc: main @@ -13,8 +13,7 @@ var :tmpD_1 :tmpD_2 data = - `=wasMoved`(:tmpD) - `=copy`(:tmpD, cast[string]( + :tmpD = `=dup`(cast[string]( :tmpD_2 = encode(cast[seq[byte]]( :tmpD_1 = newString(100) :tmpD_1)) @@ -33,8 +32,7 @@ var :tmpD_1 s = newString(100) data = - `=wasMoved`(:tmpD) - `=copy`(:tmpD, cast[string]( + :tmpD = `=dup`(cast[string]( :tmpD_1 = encode(toOpenArrayByte(s, 0, len(s) - 1)) :tmpD_1)) :tmpD @@ -51,8 +49,7 @@ var :tmpD_1 s = newSeq(100) data = - `=wasMoved`(:tmpD) - `=copy`(:tmpD, cast[string]( + :tmpD = `=dup`(cast[string]( :tmpD_1 = encode(s) :tmpD_1)) :tmpD @@ -68,8 +65,7 @@ var :tmpD_1 :tmpD_2 data = - `=wasMoved`(:tmpD) - `=copy`(:tmpD, cast[string]( + :tmpD = `=dup`(cast[string]( :tmpD_2 = encode do: :tmpD_1 = newSeq(100) :tmpD_1 |