fixes #25464; gives a deprecated warning when =dup is not provided while there being a custom =copy (#25485)

Gives a deprecated warning to keep backwards compatibility

fixes #25464
This commit is contained in:
ringabout
2026-02-06 09:19:46 +08:00
committed by GitHub
parent 296b2789b5
commit 12a2333817
2 changed files with 52 additions and 0 deletions

View File

@@ -558,6 +558,15 @@ proc declareTempOf(c: var TLiftCtx; body: PNode; value: PNode): PNode =
v.addVar(result, value)
body.add v
proc errorDupCustomCopy(c: var TLiftCtx; t: PType) {.inline.} =
## Emit an error when generating `=dup` code and a custom `=copy` hook
## exists
if c.kind == attachedDup:
let op2 = getAttachedOp(c.g, t, attachedAsgn)
if op2 != nil and sfOverridden in op2.flags:
localError(c.g.config, c.info,
"'=dup' is not provided while a custom '=copy' is defined for type '" & typeToString(t) & "'")
proc addIncStmt(c: var TLiftCtx; body, i: PNode) =
let incCall = genBuiltin(c, mInc, "inc", i)
incCall.add lowerings.newIntLit(c.g, c.info, 1)
@@ -1056,6 +1065,9 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
if c.kind == attachedDup:
var op2 = getAttachedOp(c.g, t, attachedAsgn)
if op2 != nil and sfOverridden in op2.flags:
# warn if a custom '=copy' exists but no '=dup' is provided
message(c.g.config, c.info, warnDeprecated,
"'=dup' is not provided while a custom '=copy' is defined for type '" & typeToString(t) & "'; this will become a compile time error in the future")
#markUsed(c.g.config, c.info, op, c.g.usageSym)
onUse(c.info, op2)
body.add newHookCall(c, t.assignment, x, y)
@@ -1065,6 +1077,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
fillBodyObjT(c, t, body, x, y)
of tyDistinct:
if not considerUserDefinedOp(c, t, body, x, y):
errorDupCustomCopy(c, t)
fillBody(c, t.elementType, body, x, y)
of tyTuple:
fillBodyTup(c, t, body, x, y)

View File

@@ -0,0 +1,39 @@
discard """
errormsg: "'=dup' is not provided while a custom '=copy' is defined for type 'Foo'"
"""
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