From 834dcab66cfcbd943a17b1fe24c634e3f24cbebd Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Wed, 12 Mar 2025 22:02:29 +0800 Subject: [PATCH 1/3] fixes #24760; Noncopyable base type ignored --- compiler/injectdestructors.nim | 9 ++++++--- tests/arc/t24760.nim | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 tests/arc/t24760.nim diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index ce9164058a963..e493cf0a64ae8 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 -proc isLastRead(n: PNode; c: var Con; s: var Scope): bool = +template hasDestructorOrAsgn(c: var Con, typ: PType): 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 + hasDestructor(c, typ) or (typ.kind == tyObject and not isTrival(getAttachedOp(c.graph, typ, attachedAsgn))) + +proc isLastRead(n: PNode; c: var Con; s: var Scope): bool = + 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/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 From 2993a9aa1af8b9dfaf5efff5aa58cb5f824dea0f Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Wed, 12 Mar 2025 22:05:45 +0800 Subject: [PATCH 2/3] fixes typos --- compiler/injectdestructors.nim | 2 +- compiler/liftdestructors.nim | 8 ++++---- compiler/sempass2.nim | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index e493cf0a64ae8..55146471eaa50 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -164,7 +164,7 @@ proc isLastReadImpl(n: PNode; c: var Con; scope: var Scope): bool = template hasDestructorOrAsgn(c: var Con, typ: PType): bool = # bug #23354; an object type could have a non-trival assignements when it is passed to a sink parameter - hasDestructor(c, typ) or (typ.kind == tyObject and not isTrival(getAttachedOp(c.graph, typ, attachedAsgn))) + 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 = if not hasDestructorOrAsgn(c, n.typ): return true 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 From 11eb802fed6417cf03e7e6c3508089d2156e4a8c Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Wed, 12 Mar 2025 22:07:43 +0800 Subject: [PATCH 3/3] oops --- compiler/injectdestructors.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 55146471eaa50..f25e1f2ee52e5 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -163,7 +163,7 @@ proc isLastReadImpl(n: PNode; c: var Con; scope: var Scope): bool = result = false template hasDestructorOrAsgn(c: var Con, typ: PType): bool = - # bug #23354; an object type could have a non-trival assignements when it is passed to a sink parameter + # 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 =