diff options
author | ringabout <43030857+ringabout@users.noreply.github.com> | 2023-06-05 14:06:14 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-05 08:06:14 +0200 |
commit | 1edae67efd90a880bd537f27a3cfabbed722a7af (patch) | |
tree | 826b5d7eadcee339a7f1791ce0deb3533525db8c | |
parent | 211ef26f2937ef218410231952a0680dfa1705ea (diff) | |
download | Nim-1edae67efd90a880bd537f27a3cfabbed722a7af.tar.gz |
infer error for `=dup` if there is a custom `=copy` error hook (#22004)
-rw-r--r-- | compiler/injectdestructors.nim | 11 | ||||
-rw-r--r-- | tests/destructor/tprevent_assign2.nim | 4 |
2 files changed, 12 insertions, 3 deletions
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index a03f85d02..c5056025b 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 7d788fa5c..eb5588b1a 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 <Foo>; requires a copy because it's not the last read of 'otherTree'" + errormsg: "'=dup' is not available for type <Foo>, 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 = |