Nim
Nim copied to clipboard
`converter` from uint32 to `enum` produces `RangeDefect`.
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.