-
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
Dart infers "num" for result of generic function when only ints are involved #55315
Comments
This is all working as specified. Check out the signature of operator num operator +(num other); This operator should work with numbers, both of type We do have special rules about the typing of expressions of the form In this case the argument does indeed have the type
Exactly! The reason why this is so is that Dart type inference gives a high priority to the context type, and this causes Of course, You can force the choice of type argument by specifying it explicitly, as you mention: T first<T>(List<T> list) {
return list[0];
}
int getInt() {
final ints = [1, 2, 3]; // List<int>.
final n = 1 + first<int>(ints);
return n; // OK.
} The main reason why Dart type inference gives a high priority to the context type is that mutable state plus dynamically checked covariance works best when the chosen type argument is what the context specifies (because this implies that we avoid introducing covariance in many situations). Here is an illustration why this matters: void main() {
List<num> xs = [1]; // OK, inferred as `<num>[1]`.
xs.add(1.5); // OK statically and at run time.
List<num> ys = <int>[1]; // OK, by covariance.
ys.add(1.5); // OK statically, throws at run time.
} It's convenient to allow a variable of type So, in summary: Dynamically checked covariance causes Dart type inference to give a high priority to the context type. Operator I'll close the issue because it doesn't report on anything new, or anything that we are likely to change. However, if you wish to support the introduction of statically checked variance then you can vote for dart-lang/language#524. |
Just in passing, note that the specialized analysis of numeric operations will allow us to avoid the compile-time error in the original version of the example simply by adding the desired type to the variable T first<T>(List<T> list) {
return list[0];
}
int getInt() {
final ints = [1, 2, 3]; // List<int>.
final int n = 1 + first(ints); // <-- Just give it a hint, and it's `first<int>(...)`.
return n; // OK
} The point is that Just thought this might be useful to know. 😄 |
I ran into this error in some complex code, but I've reduced the reproduction down to this:
The same problem doesn't occur if you change
1 + first(ints)
tofirst(ints) + 1
. Or if you assign the result offirst(ints)
to a local variable.Reproduced in Dart 3.3.2 (stable) and main channel.
FWIW, this is easy to work around. You can write
first<int>(ints)
. It just shouldn't be necessary.My guess is the context of being after
+
somehow causes inference as num (even though only ints are involved).The text was updated successfully, but these errors were encountered: