-
Notifications
You must be signed in to change notification settings - Fork 693
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Right shift operator assert example fails on web #5020
Comments
Hi @iehrais, thanks for filing the issue. Does the assertion fail with a message that you can share? What platform did you run this on? |
Hello @danagbemava-nc . There is just a message |
Thanks for opening an issue! Trying on native compilers, it seems to work as expected, so it might be due to a difference on how Dart represents numbers on the web. However, writing equivalent code in JavaScript seems to match Dart native, so I'm not sure. JS: const value = 0x22;
console.log(-value >> 4); // Prints -3 (matching Dart native) Dart (web compilers): void main() {
final value = 0x22;
print((-value >> 4)); // Prints 4294967293 on web, -3 on native
} @sigmundch Is this difference in behavior expected? If so, we probably can just switch to another example that has the same behavior on all platforms. |
This is indeed caused by the JavaScript-like number semantics on the web, cf. https://dart.dev/guides/language/numbers#bitwise-operations. I think it would make sense to add a comment to that example about the special treatment of numbers on the web. Here's some background info. The following variant of the example succeeds in DartPad: void main() {
final value = 0x22;
final bitmask = 0x0f;
assert((value & bitmask) == 0x02); // AND
assert((value & ~bitmask) == 0x20); // AND NOT
assert((value | bitmask) == 0x2f); // OR
assert((value ^ bitmask) == 0x2d); // XOR
assert((value << 4) == 0x220); // Shift left
assert((value >> 4) == 0x02); // Shift right
assert((value >>> 4) == 0x02); // Unsigned shift right
assert((-value >> 4).toSigned(32) == -0x03); // Shift right
assert((-value >>> 4) > 0); // Unsigned shift right
} The point is that bitwise operators in Dart-on-the-web will consider their operands to be 32 bit unsigned values, perform the operation in the standard manner according to that interpretation of the bits, and return a value with the same interpretation. For example It is not very convenient to write completely portable code using bitwise operations, but one step is simple and useful: When using a Dart-on-the-web result returned by a bitwise operator, use The reason why it does not create any issues in all the other cases is that they yield a value that doesn't have a 1 in bit 31 (the sign bit for a 32 bit signed number), so they keep their value when reinterpreted from 32 bit unsigned to JavaScript numbers (where the 32 bit bitvector is considered as part of an IEEE 754 value). So if you know for certain that the result will be one of those bit patterns whose @sigmundch, I believe you gave some further background information about the reason why the Dart-on-the-web behavior isn't exactly the same as the JavaScript behavior with bit operations? I can't find it right now, but it would have been a very similar discussion, presumably in the SDK repo. As I remember it, you said that the experience during the early years of Dart was that the given semantics was the least surprising in practice. |
Thanks for the great explanation @eernstg! That makes a lot of sense! I completely missed the 32-bit unsigned treatment of the operands on web when checking the page. I think you’re right, it would be valuable to briefly mention the number semantics here, link to that section of the number semantics doc, and keep the mentioned example with a note. |
Thanks @eernstg for the great and detailed answer! I can't tell for sure, but I think the historical reference you are thinking of is the one that @lrhn wrote here: dart-lang/sdk#49019 (comment) |
I didn't want to repeat too much of what was covered on the number semantics page or focus too much on the platform differences, so I did my best to find a minimal balance. Let me know what you think. If we want to cover more of what @eernstg mentioned in #5020 (comment), such as potential workarounds, that would be best as a follow-up expansion on the number semantics page rather than here. **Staged:** https://dart-dev--pr5033-fix-5020-spu2i1id.web.app/language/operators#bitwise-and-shift-operators Closes #5020
I didn't want to repeat too much of what was covered on the number semantics page or focus too much on the platform differences, so I did my best to find a minimal balance. Let me know what you think. If we want to cover more of what @eernstg mentioned in dart-lang#5020 (comment), such as potential workarounds, that would be best as a follow-up expansion on the number semantics page rather than here. **Staged:** https://dart-dev--pr5033-fix-5020-spu2i1id.web.app/language/operators#bitwise-and-shift-operators Closes dart-lang#5020
Page URL
https://dart.dev/language/operators.html
Page source
https://github.com/dart-lang/site-www/tree/main/src/language/operators.md
Describe the problem
The assertion
assert((-value >> 4) == -0x03);
in the Bitwise and shift operators section of the page fails.Expected fix
No response
Additional context
No response
The text was updated successfully, but these errors were encountered: