diff options
author | ringabout <43030857+ringabout@users.noreply.github.com> | 2024-02-24 14:39:56 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-24 07:39:56 +0100 |
commit | 6ce6cd4bb8e59c9f5a2c4588d2d34b9306e03d63 (patch) | |
tree | c8bb90a3982475fe8ecdab094395d2396054e376 | |
parent | 248bdb276ac946ed8faa8fa4c1cbc32c2aff103b (diff) | |
download | Nim-6ce6cd4bb8e59c9f5a2c4588d2d34b9306e03d63.tar.gz |
fixes #22723; skips tyUserTypeClasses in injectdestructors (#23341)
fixes #22723
-rw-r--r-- | compiler/injectdestructors.nim | 19 | ||||
-rw-r--r-- | tests/concepts/tconcepts_issues.nim | 24 |
2 files changed, 34 insertions, 9 deletions
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index a61b1c317..ce84bc0dc 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -318,7 +318,7 @@ proc isCriticalLink(dest: PNode): bool {.inline.} = proc finishCopy(c: var Con; result, dest: PNode; isFromSink: bool) = if c.graph.config.selectedGC == gcOrc: - let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink, tyDistinct}) + let t = dest.typ.skipTypes(tyUserTypeClasses + {tyGenericInst, tyAlias, tySink, tyDistinct}) if cyclicType(c.graph, t): result.add boolLit(c.graph, result.info, isFromSink or isCriticalLink(dest)) @@ -442,18 +442,19 @@ proc isCapturedVar(n: PNode): bool = proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode = result = newNodeIT(nkStmtListExpr, n.info, n.typ) - let tmp = c.getTemp(s, n.typ, n.info) - if hasDestructor(c, n.typ): - let typ = n.typ.skipTypes({tyGenericInst, tyAlias, tySink}) + let nTyp = n.typ.skipTypes(tyUserTypeClasses) + let tmp = c.getTemp(s, nTyp, n.info) + if hasDestructor(c, nTyp): + let typ = nTyp.skipTypes({tyGenericInst, tyAlias, tySink}) let op = getAttachedOp(c.graph, typ, attachedDup) if op != nil and tfHasOwned notin typ.flags: if sfError in op.flags: - c.checkForErrorPragma(n.typ, n, "=dup") + c.checkForErrorPragma(nTyp, n, "=dup") else: let copyOp = getAttachedOp(c.graph, typ, attachedAsgn) if copyOp != nil and sfError in copyOp.flags and sfOverridden notin op.flags: - c.checkForErrorPragma(n.typ, n, "=dup", inferredFromCopy = true) + c.checkForErrorPragma(nTyp, n, "=dup", inferredFromCopy = true) let src = p(n, c, s, normal) var newCall = newTreeIT(nkCall, src.info, src.typ, @@ -470,7 +471,7 @@ proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode = m.add p(n, c, s, normal) c.finishCopy(m, n, isFromSink = true) result.add m - if isLValue(n) and not isCapturedVar(n) and n.typ.skipTypes(abstractInst).kind != tyRef and c.inSpawn == 0: + if isLValue(n) and not isCapturedVar(n) and nTyp.skipTypes(abstractInst).kind != tyRef and c.inSpawn == 0: message(c.graph.config, n.info, hintPerformance, ("passing '$1' to a sink parameter introduces an implicit copy; " & "if possible, rearrange your program's control flow to prevent it") % $n) @@ -479,8 +480,8 @@ proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode = ("cannot move '$1', passing '$1' to a sink parameter introduces an implicit copy") % $n) else: if c.graph.config.selectedGC in {gcArc, gcOrc, gcAtomicArc}: - assert(not containsManagedMemory(n.typ)) - if n.typ.skipTypes(abstractInst).kind in {tyOpenArray, tyVarargs}: + assert(not containsManagedMemory(nTyp)) + if nTyp.skipTypes(abstractInst).kind in {tyOpenArray, tyVarargs}: localError(c.graph.config, n.info, "cannot create an implicit openArray copy to be passed to a sink parameter") result.add newTree(nkAsgn, tmp, p(n, c, s, normal)) # Since we know somebody will take over the produced copy, there is diff --git a/tests/concepts/tconcepts_issues.nim b/tests/concepts/tconcepts_issues.nim index d6c8674fd..c6d0267c5 100644 --- a/tests/concepts/tconcepts_issues.nim +++ b/tests/concepts/tconcepts_issues.nim @@ -530,3 +530,27 @@ block: # bug #12852 var tree = CappedStringTree(symbols: "^v><", cap: 5) doAssert BreadthOrder.depthOf(tree, "", ">>>") == 3 + +block: #bug #22723 + type + Node = concept n, type T + for i in n.children: + i is T + n.parent is T + + Nd = ref object + parent: Nd + children: seq[Nd] + + proc addChild(parent, child: Node) = + parent.children.add(child) + child.parent = parent + + proc foo = + var + a = Nd() + b = Nd() + a.addChild(b) + doAssert a.children.len == 1 + + foo() |