dotnet / fsharp

The F# compiler, F# core library, F# language service, and F# tooling integration for Visual Studio
https://dotnet.microsoft.com/languages/fsharp
MIT License
3.94k stars 788 forks source link

Hex integer literal has unexpected value #18041

Open inosik opened 1 week ago

inosik commented 1 week ago

Hex literals that would represent a negative number as a 32-bit value have an unexpected value when bound to a 64-bit value.

Repro steps

let a: int64 = 0xffff_ffff
let b: int64 = 0xffff_ffffL

Expected behavior

Not sure. It should either:

Actual behavior

a has a value of -1, as if it was first parsed as a 32-bit signed integer and then converted to a 64-bit integer.

Known workarounds

brianrourkeboll commented 1 week ago

a has a value of -1, as if it was first parsed as a 32-bit signed integer and then converted to a 64-bit integer.

I believe this is indeed more or less what happens.

inosik commented 1 week ago

I think you're right. I remember that I had to adapt the parsing code to support 64-bit numbers when I stole it from the F# compiler for my own purposes.

brianrourkeboll commented 1 week ago

You can see here that 0xffff_ffff is parsed as SynConst.Int32 -1, while 0xffff_ffffL is parsed as SynConst.Int64 4294967295L.

brianrourkeboll commented 1 week ago

I can't remember whether this widening conversion would always have compiled or was part of https://github.com/fsharp/fslang-design/blob/main/FSharp-6.0/FS-1093-additional-conversions.md.

abonie commented 1 week ago

Worth checking if this was introduced with implicit conversions

vzarytovskii commented 6 days ago

To add more context, as discussed before, it is likely that one scenario "goes" through literals "path", another through implicit (compile-time) conversion.