Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
7 tests fails that should pass
Proof that the current implementation has major issues
Impact / Severity
i128.fromBits
32-Bit Shift forhi2
clz
with High Bit Set (i128)fromString
PerformancePatch-01 (fromBits)
1. How Sign Extension Works (i32 → i64)
Let’s say you have a 32-bit signed integer (
i32
) whose bits look like this:-2
(i32
).i32
toi64
, the language will sign-extend the value to 64 bits. That means it copies the leftmost bit (the sign bit,1
in this case) to the newly added high bits.As a result, the 64-bit (
i64
) pattern becomes:Thus, in decimal, this is still
-2
as ani64
, which might not be what you want if you needed the original bits as-is.2. How Zero Extension Works (i32 → u32 → i64)
If your goal is to preserve the exact 32 bits without interpreting them as signed, the usual trick is:
Cast
i32
→u32
: Sinceu32
is an unsigned 32-bit integer, no sign extension occurs. The bit pattern is treated as a non-negative number in 32 bits.Then cast
u32
→i64
(oru64
→i64
), which zero-extends to 64 bits. It fills the newly created high bits with0
instead of copying the sign bit.Following the same example (
-2
ini32
, which is11111111 11111111 11111111 11111110
):i32 (
-2
) → u32:The same bit pattern reinterpreted as unsigned yields
but this time it’s considered
u32
, noti32
. There’s no negative concept here—just bits.u32 → i64:
When you cast this
u32
to ani64
, the language zero-extends, producing:Now, numerically, this is
4294967294
as ani64
, which exactly preserves the original lower 32 bits without sign extension.In other words, you get a value that strictly matches the original 32 bits but in a 64-bit container.
3. Why This Matters
i32
tou32
first forces the language to treat those 32 bits as an unsigned quantity. Any further expansion to 64 bits will keep them exactly as they appear.i32 → i64
can lead to undesired negative values if the sign bit ofi32
was1
.4. Masking Alternative:
& 0xFFFFFFFF
Another common technique is using a bitmask:
This manually zeros out any higher bits when interpreted as signed, effectively doing the same job as
i32 → u32 → i64
. Under the hood:x & 0xFFFFFFFF
chopsx
down to 32 bits in an unsigned sense.i64
afterward prevents sign extension, because the upper 32 bits are now zero.But conceptually, doing
i32 → u32 → i64
orx & 0xFFFFFFFF
→i64
is the same idea: no sign extension—just the raw 32 bits in a bigger integer.