Skip to content

fixes #24760; Noncopyable base type ignored #24777

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: devel
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions compiler/injectdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
8 changes: 4 additions & 4 deletions compiler/liftdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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!
4 changes: 2 additions & 2 deletions compiler/sempass2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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) =
Expand All @@ -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
Expand Down
20 changes: 20 additions & 0 deletions tests/arc/t24760.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
discard """
matrix: "--mm:refc; --mm:orc"
errormsg: "=dup' is not available for type <B>, 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()
Loading