nim-works / nimskull

An in development statically typed systems programming language; with sustainability at its core. We, the community of users, maintain it.
https://nim-works.github.io/nimskull/index.html
Other
280 stars 39 forks source link

dereferencing `var|lent uint(8|16|32)` yields wrong value in VM #1407

Closed alaviss closed 3 months ago

alaviss commented 3 months ago

Example

proc foo(values: openArray[uint16]) =
  for value in values.items:
    doAssert value == 40000u16:
      "Got: " & $value

foo([40000u16])

Actual Output

$ nim r --backend:vm test.nim
stack trace: (most recent call last)
test.nim(1, 2) NimMain
test.nim(6, 4) test
test.nim(3, 14) foo
assertions.nim(38, 26) failedAssertImpl
assertions.nim(28, 11) raiseAssert
fatal.nim(50, 5) sysFatal
fatal.nim(50, 5) Error: unhandled exception: test.nim(3, 14) `value == 40000'u16` Got: 18446744073709526080 [AssertionDefect]

Additional Information

zerbina commented 3 months ago

Thanks for filing the issue!

The problem is not directly related to openArray and uint16, but instead affects all lent uint(8|16|32) and var uint(8|16|32) dereferences, with the reason being that vmgen doesn't emit the necessary narrowing instructions.

A more minimized reproducer:

proc f(x: (uint8,)): lent uint8 = x[0]

echo f((128'u8,)) # echoes 0xFFFFFFFF_FFFFFF80 (as a non-hex number)
saem commented 3 months ago

Fixed in https://github.com/nim-works/nimskull/pull/1409