Nim icon indicating copy to clipboard operation
Nim copied to clipboard

`converter` from uint32 to `enum` produces `RangeDefect`.

Open geekrelief opened this issue 3 years ago • 2 comments

Example

type Foo = enum
  A = 0u
  B = 0x8000_0000u

converter toFoo(a: uint32): Foo = Foo(a)

var f:Foo = 0u32

https://play.nim-lang.org/#ix=44jn

Current Output

/usercode/in.nim(7)      in
/usercode/in.nim(5)      toFoo
/playground/nim/lib/system/fatal.nim(53) sysFatal
Error: unhandled exception: value out of range: 0 notin 0 .. -2147483648 [RangeDefect]

Expected Output

No error.

Additional Information

The error occurs on devel in the C/C++ backends when rangeCheck is on.

In the cpp backend, generated code for the converter looks like this:

typedef NI32 tyEnum_Foo__e7ZYo29bCaSV5JytNytC9bZA;

if ((NI64)(a) < ((tyEnum_Foo__e7ZYo29bCaSV5JytNytC9bZA) 0) || (NI64)(a) > ((tyEnum_Foo__e7ZYo29bCaSV5JytNytC9bZA) IL64(2147483648))){ 
    raiseRangeErrorI(a, ((tyEnum_Foo__e7ZYo29bCaSV5JytNytC9bZA) 0), ((tyEnum_Foo__e7ZYo29bCaSV5JytNytC9bZA) IL64(2147483648))); 
}

The Foo enum is defined as an int32 even if we specify unsigned values. The value B is 0x8000_0000u, but is converted to signed with IL64 and becomes negative when cast to tyEnum_Foo. The value a is cast to int64 when it should be a uint32.

Instead of NI64(a), if the type was NU64(a) the comparison would convert all operands to unsigned and the test would be valid. This would also be the case if tyEnum_Foo was defined as NU32.

geekrelief avatar Jul 14 '22 05:07 geekrelief