From 0dc577a4dc11a51674722d0705d95a1f57cf4f12 Mon Sep 17 00:00:00 2001 From: metagn Date: Wed, 8 Apr 2026 01:51:47 +0300 Subject: [PATCH] fix compiler crash regression with explicit destructor calls [backport:2.2] (#25717) Unfortunately I do not have a test case for this (although I can link [this package test](https://github.com/metagn/froth/blob/60f1be9037feb8851810cdf45f11027e33e8c0bc/tests/test_simple_combined.nim) which broke), but this is a regression caused by #24841 (which was backported to 2.2.4) that causes the following compiler crash: ``` assertions.nim(34) raiseAssert Error: unhandled exception: ccgtypes.nim(230, 13) `false` mapType: tyGenericInvocation [AssertionDefect] ``` Codegen is traversing the type of the symbol of an explicit destructor call, but the symbol is the uninstantiated generic hook. This happens because #24841 changed the code which gives explicit destructor calls the proper attached destructor to use `replaceHookMagic`, which now skips `abstractVar` from the type to get the destructor whereas previously it was just `{tyAlias, tyVar}`. This skips `tyGenericInst` and also `tyDistinct`. I cannot explain why the skipped `tyGenericInst` does not have the right destructor but it's not really unexpected, and skipping `tyDistinct` is just wrong. To fix this, just `{tyAlias, tyVar, tySink}` are skipped. --- compiler/semdata.nim | 10 +++++----- compiler/sempass2.nim | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 0fc000051c..4710d7c0d6 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -741,7 +741,7 @@ proc replaceHookMagic*(c: PContext, n: PNode, kind: TTypeAttachedOp): PNode = case kind of attachedDestructor: result = n - let t = n[1].typ.skipTypes(abstractVar) + let t = n[1].typ.skipTypes({tyAlias, tyVar, tySink}) let op = getAttachedOp(c.graph, t, attachedDestructor) if op != nil: result[0] = newSymNode(op) @@ -753,13 +753,13 @@ proc replaceHookMagic*(c: PContext, n: PNode, kind: TTypeAttachedOp): PNode = result[1] = skipAddr(n[1]) of attachedTrace: result = n - let t = n[1].typ.skipTypes(abstractVar) + let t = n[1].typ.skipTypes({tyAlias, tyVar, tySink}) let op = getAttachedOp(c.graph, t, attachedTrace) if op != nil: result[0] = newSymNode(op) of attachedDup: result = n - let t = n[1].typ.skipTypes(abstractVar) + let t = n[1].typ.skipTypes({tyAlias, tyVar, tySink}) let op = getAttachedOp(c.graph, t, attachedDup) if op != nil: result[0] = newSymNode(op) @@ -769,7 +769,7 @@ proc replaceHookMagic*(c: PContext, n: PNode, kind: TTypeAttachedOp): PNode = result.add boolLit of attachedWasMoved: result = n - let t = n[1].typ.skipTypes(abstractVar) + let t = n[1].typ.skipTypes({tyAlias, tyVar, tySink}) let op = getAttachedOp(c.graph, t, attachedWasMoved) if op != nil: result[0] = newSymNode(op) @@ -780,7 +780,7 @@ proc replaceHookMagic*(c: PContext, n: PNode, kind: TTypeAttachedOp): PNode = result = c.semAsgnOpr(c, n, nkAsgn) of attachedDeepCopy: result = n - let t = n[1].typ.skipTypes(abstractVar) + let t = n[1].typ.skipTypes({tyAlias, tyVar, tySink}) let op = getAttachedOp(c.graph, t, kind) if op != nil: result[0] = newSymNode(op) diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 91ade858e9..35901ed960 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -1164,7 +1164,7 @@ proc trackCall(tracked: PEffects; n: PNode) = var (isHook, opKind) = findHookKind(a.sym.name.s) if isHook: # rebind type bounds operations after createTypeBoundOps call - let t = n[1].typ.skipTypes({tyAlias, tyVar}) + let t = n[1].typ.skipTypes({tyAlias, tyVar, tySink}) if a.sym != getAttachedOp(tracked.graph, t, opKind): createTypeBoundOps(tracked, t, n.info, explicit = true) # replace builtin hooks with lifted ones