diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index ce9164058a963..f25e1f2ee52e5 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -162,9 +162,12 @@ proc isLastReadImpl(n: PNode; c: var Con; scope: var Scope): bool = else: result = false +template hasDestructorOrAsgn(c: var Con, typ: PType): bool = + # bug #23354; an object type could have a non-trivial assignements when it is passed to a sink parameter + hasDestructor(c, typ) or (typ.kind == tyObject and not isTrivial(getAttachedOp(c.graph, typ, attachedAsgn))) + proc isLastRead(n: PNode; c: var Con; s: var Scope): bool = - # bug #23354; an object type could have a non-trival assignements when it is passed to a sink parameter - if not hasDestructor(c, n.typ) and (n.typ.kind != tyObject or isTrival(getAttachedOp(c.graph, n.typ, attachedAsgn))): return true + if not hasDestructorOrAsgn(c, n.typ): return true let m = skipConvDfa(n) result = (m.kind == nkSym and sfSingleUsedTemp in m.sym.flags) or @@ -449,7 +452,7 @@ proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode = result = newNodeIT(nkStmtListExpr, n.info, n.typ) let nTyp = n.typ.skipTypes(tyUserTypeClasses) let tmp = c.getTemp(s, nTyp, n.info) - if hasDestructor(c, nTyp): + if hasDestructorOrAsgn(c, nTyp): let typ = nTyp.skipTypes({tyGenericInst, tyAlias, tySink}) let op = getAttachedOp(c.graph, typ, attachedDup) if op != nil and tfHasOwned notin typ.flags: diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index c94891613234f..6d6d75377dfbb 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -1268,7 +1268,7 @@ proc inst(g: ModuleGraph; c: PContext; t: PType; kind: TTypeAttachedOp; idgen: I else: localError(g.config, info, "unresolved generic parameter") -proc isTrival*(s: PSym): bool {.inline.} = +proc isTrivial*(s: PSym): bool {.inline.} = s == nil or (s.ast != nil and s.ast[bodyPos].len == 0) proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo; @@ -1323,8 +1323,8 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf if canon != orig: setAttachedOp(g, idgen.module, orig, k, getAttachedOp(g, canon, k)) - if not isTrival(getAttachedOp(g, orig, attachedDestructor)): - #or not isTrival(orig.assignment) or - # not isTrival(orig.sink): + if not isTrivial(getAttachedOp(g, orig, attachedDestructor)): + #or not isTrivial(orig.assignment) or + # not isTrivial(orig.sink): orig.flags.incl tfHasAsgn # ^ XXX Breaks IC! diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 0aa96bd6ea94c..77b70028b70a7 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -705,7 +705,7 @@ proc isNoEffectList(n: PNode): bool {.inline.} = assert n.kind == nkEffectList n.len == 0 or (n[tagEffects] == nil and n[exceptionEffects] == nil and n[forbiddenEffects] == nil) -proc isTrival(caller: PNode): bool {.inline.} = +proc isTrivial(caller: PNode): bool {.inline.} = result = caller.kind == nkSym and caller.sym.magic in {mEqProc, mIsNil, mMove, mWasMoved, mSwap} proc trackOperandForIndirectCall(tracked: PEffects, n: PNode, formals: PType; argIndex: int; caller: PNode) = @@ -714,7 +714,7 @@ proc trackOperandForIndirectCall(tracked: PEffects, n: PNode, formals: PType; ar let param = if formals != nil and formals.n != nil and argIndex < formals.n.len: formals.n[argIndex].sym else: nil # assume indirect calls are taken here: if op != nil and op.kind == tyProc and n.skipConv.kind != nkNilLit and - not isTrival(caller) and + not isTrivial(caller) and ((param != nil and sfEffectsDelayed in param.flags) or laxEffects in tracked.c.config.legacyFeatures): internalAssert tracked.config, op.n[0].kind == nkEffectList diff --git a/tests/arc/t24760.nim b/tests/arc/t24760.nim new file mode 100644 index 0000000000000..4eb65a3774e2e --- /dev/null +++ b/tests/arc/t24760.nim @@ -0,0 +1,20 @@ +discard """ + matrix: "--mm:refc; --mm:orc" + errormsg: "=dup' is not available for type , which is inferred from unavailable '=copy'; requires a copy because it's not the last read of 'b'; another read is done here: t24760.nim(19, 8); routine: g" +""" + +type + A {.inheritable.} = object + B = object of A + +proc `=copy`(a: var A, x: A) {.error.} +#proc `=copy`(a: var B, x: B) {.error.} + +proc ffff(v: sink B) = + echo v + +proc g() = + var b: B + ffff(b) + ffff(b) +g() \ No newline at end of file