mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-21 06:10:56 +00:00
fixes #25464; infer =dup for distinct types
This commit is contained in:
@@ -558,6 +558,21 @@ proc declareTempOf(c: var TLiftCtx; body: PNode; value: PNode): PNode =
|
||||
v.addVar(result, value)
|
||||
body.add v
|
||||
|
||||
proc considerInferDupFromCopy(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
|
||||
## For `=dup`, if no explicit hook exists, try to infer from `=copy` hook
|
||||
## to maintain backward compatibility. Returns true if inference was applied.
|
||||
if c.kind == attachedDup:
|
||||
var op2 = getAttachedOp(c.g, t, attachedAsgn)
|
||||
if op2 != nil and sfOverridden in op2.flags:
|
||||
#markUsed(c.g.config, c.info, op, c.g.usageSym)
|
||||
onUse(c.info, op2)
|
||||
body.add newHookCall(c, t.assignment, x, y)
|
||||
result = true
|
||||
else:
|
||||
result = false
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc addIncStmt(c: var TLiftCtx; body, i: PNode) =
|
||||
let incCall = genBuiltin(c, mInc, "inc", i)
|
||||
incCall.add lowerings.newIntLit(c.g, c.info, 1)
|
||||
@@ -1053,19 +1068,12 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
elif tfUnion in t.flags: # bug #25236
|
||||
defaultOp(c, t, body, x, y)
|
||||
else:
|
||||
if c.kind == attachedDup:
|
||||
var op2 = getAttachedOp(c.g, t, attachedAsgn)
|
||||
if op2 != nil and sfOverridden in op2.flags:
|
||||
#markUsed(c.g.config, c.info, op, c.g.usageSym)
|
||||
onUse(c.info, op2)
|
||||
body.add newHookCall(c, t.assignment, x, y)
|
||||
else:
|
||||
fillBodyObjT(c, t, body, x, y)
|
||||
else:
|
||||
if not considerInferDupFromCopy(c, t, body, x, y):
|
||||
fillBodyObjT(c, t, body, x, y)
|
||||
of tyDistinct:
|
||||
if not considerUserDefinedOp(c, t, body, x, y):
|
||||
fillBody(c, t.elementType, body, x, y)
|
||||
if not considerInferDupFromCopy(c, t, body, x, y):
|
||||
fillBody(c, t.elementType, body, x, y)
|
||||
of tyTuple:
|
||||
fillBodyTup(c, t, body, x, y)
|
||||
of tyVarargs, tyOpenArray:
|
||||
|
||||
42
tests/destructor/tdup_from_copy.nim
Normal file
42
tests/destructor/tdup_from_copy.nim
Normal file
@@ -0,0 +1,42 @@
|
||||
discard """
|
||||
output: '''
|
||||
copy!
|
||||
2
|
||||
1'''
|
||||
"""
|
||||
|
||||
type Foo = distinct int
|
||||
|
||||
var counter = 0
|
||||
|
||||
proc `=destroy`(pkt: var Foo) =
|
||||
if cast[int](pkt) != 0:
|
||||
echo cast[int](pkt)
|
||||
|
||||
proc `=copy`(a: var Foo, b: Foo) =
|
||||
if cast[int](a) == cast[int](b):
|
||||
return
|
||||
|
||||
`=destroy`(a)
|
||||
if cast[int](b) == 0:
|
||||
zeroMem(addr a, sizeof(Foo))
|
||||
else:
|
||||
counter += 1
|
||||
copyMem(addr a, addr counter, sizeof(Foo))
|
||||
echo "copy!"
|
||||
|
||||
proc makeFoo(): Foo =
|
||||
counter += 1
|
||||
cast[Foo](counter)
|
||||
|
||||
|
||||
type Bar = object
|
||||
val: Foo
|
||||
|
||||
|
||||
proc consume(x: sink Bar) =
|
||||
discard
|
||||
|
||||
let x = Bar(val: makeFoo())
|
||||
consume(x)
|
||||
discard x
|
||||
Reference in New Issue
Block a user