mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
fixes #24760
I tried `incl` `tfHasAsgn` to nontrivial assignment, but that solution
seems to break too many things. Instead, in this PR, `passCopyToSink`
now checks nontrivial assignment
(cherry picked from commit e958f4a3cd)
This commit is contained in:
@@ -163,9 +163,13 @@ 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 (c.graph.config.selectedGC in {gcArc, gcOrc, gcAtomicArc} and
|
||||
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 = isLastReadImpl(n, c, s)
|
||||
@@ -456,7 +460,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:
|
||||
|
||||
@@ -1286,7 +1286,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;
|
||||
@@ -1341,8 +1341,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!
|
||||
|
||||
@@ -706,7 +706,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) =
|
||||
@@ -715,7 +715,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
|
||||
|
||||
20
tests/arc/t24760.nim
Normal file
20
tests/arc/t24760.nim
Normal file
@@ -0,0 +1,20 @@
|
||||
discard """
|
||||
matrix: "--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()
|
||||
Reference in New Issue
Block a user