fix compiler crash with uncheckedAssign and range/distinct discrims [backport] (#25585)

On simple code like:

```nim
type Foo = object
  case x: range[0..7]
  of 0..2:
    a: string
  else:
    b: string

var foo = Foo()
{.cast(uncheckedAssign).}:
  foo.x = 5
```

The compiler tries to generate a destructor for the variant fields by
checking if the discrim is equal to the old one, but the type is not
skipped when looking for an `==` operator in system, so any
discriminator with type `range`/`distinct`/etc crashes with:

```
(10, 9) Error: can't find magic equals operator for type kind tyRange
```

This is fixed by just skipping abstract types.

(cherry picked from commit 7a87e7d199)
This commit is contained in:
metagn
2026-03-07 09:39:57 +03:00
committed by narimiran
parent 29b0e8342b
commit f201c4e225
2 changed files with 27 additions and 2 deletions

View File

@@ -11,7 +11,7 @@
import
ast, astalgo, msgs, platform, idents,
modulegraphs, lineinfos
modulegraphs, lineinfos, types
export createMagic
@@ -134,7 +134,7 @@ proc getNimScriptSymbol*(g: ModuleGraph; name: string): PSym =
proc resetNimScriptSymbols*(g: ModuleGraph) = g.exposed = initStrTable()
proc getMagicEqSymForType*(g: ModuleGraph; t: PType; info: TLineInfo): PSym =
case t.kind
case t.skipTypes(abstractRange).kind
of tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64:
result = getSysMagic(g, info, "==", mEqI)

View File

@@ -365,3 +365,28 @@ proc do2(x: int, e: ItemExt): seq[(string, ItemExt)] =
do1(x).map(proc(v: (string, Item)): auto = (v[0], ItemExt(a: v[1], b: e.b)))
doAssert $do2(0, ItemExt(a: Item(kind: 1, c: "second"), b: "third")) == """@[("zero", (a: (kind: 1, c: "first"), b: "third"))]"""
block:
type RangeCrash = object
case x: range[0..7]
of 0..2:
a: string
else:
b: string
var rangeCrash = RangeCrash()
{.cast(uncheckedAssign).}:
rangeCrash.x = 5
block:
type Discrim = distinct uint8
type DistinctCrash = object
case x: Discrim
of Discrim(0)..Discrim(2):
a: string
else:
b: string
var distinctCrash = DistinctCrash()
{.cast(uncheckedAssign).}:
distinctCrash.x = Discrim(5)