-
-
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
Fix the return type of Enumerable#sum/product
for union elements
#15314
base: master
Are you sure you want to change the base?
Conversation
This PR expands on the (accidentally closed) PR 15308. Tagging @Blacksmoke16, @straight-shoota, and @BlobCodes to continue the discussion here. |
Using the first type of a union type as the type of the result of `Enumerable#sum/product()` call can cause runtime failures, e.g. `[1, 10000000000_u64].sum/product` will result in an ``OverflowError``. A safer alternative is to flag/disallow the use of union types with `Enumerable#sum/product()` and recommend the use of `Enumerable#sum/product(initial)` with an initial value of the expected type of the sum/product call.
The error message and documentation specifically refers to the variants of Enumerable#sum/product that do not support union types.
This change is rather ill-placed, given it modifies the internal |
@Sija can you please elaborate on "this change is rather ill-placed'? |
@rvprasad As I've already mentioned, this change modifies the internal |
@Sija I see what you mean. Here are a few thoughts and observations.
While I realize surfacing more issues is not ideal, I hope they can help clear up a small corner of the language. |
I don't think this change is ill-placed. The purpose of I believe the approach taken here to handle this case explicitly with a custom error message is better. The specific implementation such as the method name of the internal helper can be adjusted easily. Any issue with the yielding overloads |
With this PR, Reflect is not used to determine the first type of a union type. This commit aligns Reflect's method and related comments with the class' purpose.
I have pushed a revision that updates the implementation and comments in Regarding the yielding overloads, I did not realize that, during type coercion, Crystal uses the type of expression based on the type of the first sub-expression of the expression, i.e., typeof(1 * 1u64) is Int32 while typeof(1u64 * 1) is UInt64. On a related note, I believe Furthermore, when I tried to use
|
With regards to |
While Also, this observation is true of heterogeneous arrays, i.e., arrays whose element type is a union type. Edit1: I have captured this observation in issue #15317. |
Assuming we can pursue other issues in separate dedicated tickets, are there any objections to the proposed change to address the primary issue captured in this ticket? |
@straight-shoota thanks for the approval! Do I need to do anything more for these changes to be merged? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that + and * uses the type of the left operand one could argue that using the type of the first argument is consistent with that. Not allowing unions would be aligned to disable 1i32 + 1i64.
But still I think this change make sense, code that will break should be easy to fix, even if polymorphic since there is multiplicative_identity
and additive_identity
.
Co-authored-by: Sijawusz Pur Rahnama <sija@sija.pl>
Co-authored-by: Sijawusz Pur Rahnama <sija@sija.pl>
Seems like a gave bad advise to use While it generally seems like a good idea to test semantics by directly using the compiler, this also requires building a huge part of the compiler just to run If we want to build some code from stdlib specs we should instead run the compiler as an external program. |
Using the first type of a union type as the type of the result of
Enumerable#sum/product()
call can cause runtime failures, e.g.[1, 10000000000_u64].sum/product
will result in anOverflowError
. A safer alternative is to flag/disallow the use of union types withEnumerable#sum/product()
and recommend the use ofEnumerable#sum/product(initial)
with an initial value of the expected type of the sum/product call.