nim-lang / Nim

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula. Its design focuses on efficiency, expressiveness, and elegance (in that order of priority).
https://nim-lang.org
Other
16.44k stars 1.47k forks source link

conversion to unsigned causes error in VM; works in RT #12700

Closed krux02 closed 1 month ago

krux02 commented 4 years ago

Example

proc foo1(arg: int): string =
  let x = uint32(arg)
  $x

proc foo2(arg: int): string {.compileTime.} =
  let x = uint32(arg)
  $x

echo foo1(-1)
echo foo2(-1)

Current Output

/tmp/scratch.nim(17, 17) Error: illegal conversion from '-1' to '[0..4294967295]'

But without the {.compileTime.} annotation foo1 works fine and returns "4294967295".

Expected Output

If conversation to unsigned integers should be unchecked as proposed in the RFC, then the conversation to unsigend should be unchecked at compile time as well.

4294967295
4294967295

Possible Solution

Additional Information

The example above is a stripped down version. A real world example would be more that there is some source code out there that you do not have full control over. You would want to use it, but at compile time. But you can't use it at compile time, because interally it uses the the conversion that is range checked at compile time and not range checked at runtime. And then you have to make a PR request to change the conversation into a cast. And maybe get into descussions about cast being ugly and compile time evaluation isn't that important etc. It is just friction that can be avoided.

This problem is also very annoying for me personally, because I spent a lot of time in the Nim compiler to ensure that both the VM and the runtime behavior of integers is exactly the same. I wrote many tests that ensure in many placed exact same behavior at runtime and compile time. And here the behavior was explicitly broken for reasons that I don't I can't see as important.

This is the commit that introduced that regression https://github.com/nim-lang/Nim/commit/c98e0e22ad7bf7772eb0ef3f50b7f67f33ec8905

Araq commented 4 years ago

It's exactly as the spec says and you know it.

And then you have to make a PR request to change the conversation into a cast. And maybe get into descussions about cast being ugly and compile time evaluation isn't that important etc. It is just friction that can be avoided.

All that happens: You add an explicit bitmask, no need to discuss things, no need for cast.

mratsim commented 4 years ago

The idiomatic way should be high(uint32) especially now that high(uint64) is working.

Also -1 is signed and conversion from signed to unsigned is checked. It's when you stay in the unsigned domain that it is unchecked.

Araq commented 4 years ago

Also -1 is signed and conversion from signed to unsigned is checked. It's when you stay in the unsigned domain that it is unchecked.

No, now it's not checked at runtime and only checked at compile time.

timotheecour commented 3 years ago
ringabout commented 2 years ago

ref https://github.com/nim-lang/Nim/pull/18900

static: # illegal conversion from   '-2147483648' to '[0..4294967295]' 
  let x = low(int32) 
  echo uint32(x) 
static: # pass 
  let x = low(int64) 
  echo uint64(x)

While

const x = uint64(-1) # Error: -1 can't
bung87 commented 1 year ago

when use nim check below case, I get messed errors.

static: 
  const x = low(int32) 
  echo uint32(x) 
static: # pass 
  const x = low(int64) 
  echo uint64(x)
t6549.nim(7, 14) Error: -2147483648 can't be converted to uint32
t6549.nim(7, 14) Error: conversion from int32 to uint32 is invalid
t6549.nim(7, 14) Error: conversion from int32 to uint32 is invalid
stack trace: (most recent call last)
t6549.nim(7, 14)         t6549
t6549.nim(7, 14) Error: illegal conversion from '-2147483648' to '[0..4294967295]'
t6549.nim(10, 14) Error: -9223372036854775808 can't be converted to uint64
t6549.nim(10, 14) Error: cannot convert -9223372036854775808 to uint64