Fix float64 to uint{8,16,32} conversion. #1305
Merged
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.
Before this change, GopherJS compiler emitted
(f >> 0)
expression to convert a float64f
to any non-64-bit unsigned integer type. This is incorrect, because>>
is a signed bitshift operator in JS, so the returned value remained signed. Moreover, it did not take into account to bit size of the target type.By removing the switch cause, we make the compiler fall through to the default clause where
fc.fixNumber()
actually does the right thing, taking the target into account.Fixes #733.
Amazingly, this is what was causing flakiness of the
hash/maphash.TestHashHighBytes
since Go 1.19. There, the 64-bit hash value was computed as(uint64(hi) << 32) | uint64(lo)
, wherehi
andlo
were randomly-generatedunit32
values. In turn, those values were generated by converting a random [0, 2^32) float64 value into uint32. As per explanation above, this used to be done with the following JS expression(f >> 0)
, which meant that for values in the range of [2^31, 2^32) it would return a negative JS number. This would also set all the high bits of that number to 1. So when we come back to(uint64(hi) << 32) | uint64(lo)
, there was the 50% chance that all higher bits of the right bitwise-or operand would be 1, meaning the result would also have the higher bits set to 1, regardless of whathi
was. That led to a high likelihood of failing said test 🕵️♂️