From 1edae67efd90a880bd537f27a3cfabbed722a7af Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Mon, 5 Jun 2023 14:06:14 +0800 Subject: [PATCH] infer error for `=dup` if there is a custom `=copy` error hook (#22004) --- compiler/injectdestructors.nim | 11 ++++++++++- tests/destructor/tprevent_assign2.nim | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index a03f85d025..c5056025b5 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -186,8 +186,11 @@ template isUnpackedTuple(n: PNode): bool = ## hence unpacked tuples themselves don't need to be destroyed (n.kind == nkSym and n.sym.kind == skTemp and n.sym.typ.kind == tyTuple) -proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string) = +proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string; inferredFromCopy = false) = var m = "'" & opname & "' is not available for type <" & typeToString(t) & ">" + if inferredFromCopy: + m.add ", which is inferred from unavailable '=copy'" + if (opname == "=" or opname == "=copy" or opname == "=dup") and ri != nil: m.add "; requires a copy because it's not the last read of '" m.add renderTree(ri) @@ -430,6 +433,12 @@ proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode = if op != nil and tfHasOwned notin typ.flags: if sfError in op.flags: c.checkForErrorPragma(n.typ, n, "=dup") + else: + let copyOp = getAttachedOp(c.graph, typ, attachedAsgn) + if copyOp != nil and sfError in copyOp.flags and + sfOverriden notin op.flags: + c.checkForErrorPragma(n.typ, n, "=dup", inferredFromCopy = true) + let src = p(n, c, s, normal) var newCall = newTreeIT(nkCall, src.info, src.typ, newSymNode(op), diff --git a/tests/destructor/tprevent_assign2.nim b/tests/destructor/tprevent_assign2.nim index 7d788fa5c1..eb5588b1a2 100644 --- a/tests/destructor/tprevent_assign2.nim +++ b/tests/destructor/tprevent_assign2.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "'=dup' is not available for type ; requires a copy because it's not the last read of 'otherTree'" + errormsg: "'=dup' is not available for type , which is inferred from unavailable '=copy'; requires a copy because it's not the last read of 'otherTree'; another read is done here: tprevent_assign2.nim(51, 31); routine: preventThis" file: "tprevent_assign2.nim" line: 49 """ @@ -10,7 +10,7 @@ type proc `=destroy`(f: var Foo) = f.x = 0 proc `=copy`(a: var Foo; b: Foo) {.error.} # = a.x = b.x -proc `=dup`(a: Foo): Foo {.error.} + proc `=sink`(a: var Foo; b: Foo) = a.x = b.x proc createTree(x: int): Foo =