-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Multiplication of Int64 and Int32 may result in Int32 (risking overflows at runtime) #14347
Comments
Yeah, this behaviour is expected and (currently) intended. I agree that it can be confusing, though. The underlying idea is that performing an operation on a variable should not change the type of the variable. This is particularly relevant for the assignment operators, such as Knowing this practical reason, I believe the behaviour is quite comprehensible. But it's not without alternatives. I think this could potentially be changed in the future. I would support that because it's an odd rule and confusing. |
Maybe |
Yeah, that could be an option. I'd like to look into requiring identical number types for math operations. Thus you would need to be explicit about type casting when the types don't match. Auto-casting should cover some basic use cases, so it wouldn't be too much noise. |
It goes further than just the assignment operators. See #8111 and #8872. IMO integers are broken in Crystal, or at least not as simple as they could have been; either you live with the default Int32 everywhere or you type everything when you need explicit sizes, down to each literal value 🤷 I wish this had been fixed before 1.0 but we instead kept the rule that the left-most type is the result type, so Int64 * Int32 returns an Int64 while Int32 * Int64 returns an Int32, which means that you should always write |
Discussion
I had been debugging a problem with OverflowError in my code. Maybe the behavior is expected, but to me it was at surprising.
When multiplying Int64 and Int32, my assumption was that either it should implicitly promote the Int32 to Int64 or fail with an compile error. It turns out that the actual behavior - both compiler and interpreter - is to do a Int32 multiplication:
My assumption would have been that here, especially because "1" is not typed, should not result in a Int32 multiplication.
Here is another example of two programs. In both cases, I would have expected that they print "5000000000", but it is not the case:
Example 1: outputs 5000000000
Example 2: fails with "Arithmetic overflow (OverflowError)"
Also, with variables instead of literals. For instance, this here will overflow:
But this program will print "5000000000":
As said before, I was under the assumption that multiplying incompatible types like Int32 and Int64 should be rejected by the compiler, or that it should do the safe conversion implicitly (here Int32 to Int64). Otherwise, I feel it leads to subtle runtime errors.
Also, the operation is not symmetrical:
Same with the compiler:
results in this output:
Here I would also expected to see either Int64 in both cases, or that the compiler rejects it.
The text was updated successfully, but these errors were encountered: