mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-06 07:38:24 +00:00
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:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user