modularml / mojo

The Mojo Programming Language
https://docs.modular.com/mojo/manual/
Other
23.25k stars 2.6k forks source link

[BUG]: Large values of types Int (and at least also Int64) are incorrect #1411

Open Harding-Stardust opened 11 months ago

Harding-Stardust commented 11 months ago

Bug description

I couldn't find and specifications on how large the type Int is (and if it's signed) so I fooled around in the Mojo Jupyter notebook with some large numbers like this:

let x: Int = 1
let y = x << 63
print(y) # prints: -9223372036854775808 (unknown to me if this is correct)

let x: Int = 1
let y: Int = x << 65
print(y) # prints: 94350063826592 (incorrect and seems to generate different numbers when I ran it multiple times)

let x: Int = 1
let y = x << 65
print(y) # prints: 94350059733488 (incorrect and seems to generate different numbers when I ran it multiple times)
# Expected: Overflow error

let x: UInt64 = 1
let y: UInt64 = x << 65
print(y) # prints: 1 (incorrect and also seems to return different numbers when I ran it multiple times)

# For reference, I tried it with the Python parser:
%%python
x = 1
y = x << 65
print(y) # prints: 36893488147419103232 (correct)

Steps to reproduce

Used a clean notebook in the playground. Can't think of anything else that is needed to reproduce the bug.

System information

``shell

theopomies commented 11 months ago

This is the correct behavior, because Int is signed and implemented with 64 bits of precision, what's happening here is a simple overflow, as it would happen in C++, not all languages error on overflow (although I agree this would be a desirable behavior) This doesn't happen in python because ints are using Arbitrary-precision arithmetic, see also

lattner commented 11 months ago

Agree. @willghatch the issue here is that the int constructor from IntegerLiteral is not producing an error or warning when it overflows. Was this on your todo list?

gryznar commented 11 months ago

@lattner I've made related feature request for overflow errors here: https://github.com/modularml/mojo/issues/992

soraros commented 11 months ago

@lattner Actually, compiler warns about this if you do the literal to int conversion manually:

fn main():
    alias x: IntLiteral = 1
    alias y: IntLiteral = x << 65
    print(Int(y))
# note: integer value 36893488147419103232 requires 67 bits to store, 
        but the destination bit width is only 64 bits wide

I agree with @theopomies that overflow at compile time should ideally trap. For instance, Rust lets people choose. Also, I'm surprised that it's nondeterministic, UB bad.

willghatch commented 11 months ago

Agree. @willghatch the issue here is that the int constructor from IntegerLiteral is not producing an error or warning when it overflows. Was this on your todo list?

Yes, this is on my list but was pre-empted by some other things.