-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Generic type not correctly resolved for <T, C extends Iterable<T>> #46117
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
Comments
This is a front-end issue related to inference.
All issues are inference issues and not VM issues. Reassigning. |
This is a known property of the Dart inference algorithm (cf. dart-lang/language#731). The core issue is that the inference does not support flow of information from one argument to another in a generic function call. Note that the extension example can be resolved by providing the type arguments explicitly, which is possible in the case where the extension method is invoked explicitly (that is, using the name of the extension in a way that resembles a constructor invocation): void main() {
final List<int> list = [1, 2, 3];
final List<int> listReturn = OnEach<int, List<int>>(list).onEach((it) {
print(it.abs());
});
}
extension OnEach<T, C extends Iterable<T>> on C {
C onEach(void Function(T) action) {
for (final item in this) {
action(item);
}
return this;
}
} |
Ran into the same issue today. It would be really, really cool if the Dart team would solve this. |
Dart 3.7.0 includes the feature 'inference-using-bounds' (dart-lang/language#3009). This feature generalizes type inference such that it is able to extract more information from the declared bounds. In particular, the following will now work: // ignore_for_file: unused_local_variable
// extension example
void main() {
final List<int> list = [1, 2, 3];
final List<int> listReturn = list.onEach((it) {
// `it` has type `int`.
print(it.abs());
});
final Set<int> set = {1, 2, 3};
final Set<int> setReturn = set.onEach((it) {
// `it` has type `int`.
print(it.abs());
});
}
extension OnEach<C extends Iterable<T>, T> on C {
C onEach(void Function(T) action) {
for (final item in this) {
action(item);
}
return this;
}
} This program compiles and runs without issues. To see that the type of So in that sense the problem has been solved already (unless your tool chain is older than 3.7.0). However, it doesn't work on the original example program: It requires the type parameters to be declared in the right order, such that the information from the bound is available at the time where the type parameter that needs this information is being inferred. So we need to declare them as This is actually a different topic (namely: type inference depends on the ordering of type parameter declarations), which is already the topic of #40423. So I'll close this issue as resolved. |
@MarvinHannott, if your use case isn't handled by declaring the type parameters in a suitable order and using Dart 3.7.0 or higher then it's a different thing—in that case, please create a new issue. |
While trying to create chainable extensions for
Iterable
, whereList
andSet
both return itself correctly I ran into a type issue. Theiterable
type is correctly returned but information aboutT
is lost, resulting indynamic
This bug is not related to extensions. It also occurs for plain top-level functions
Adding a type manually allows compilation for topLevel functions
But adding a type for extensions crashes
Expected:
// extension example
compiles without errors and returnsint
as parameter ofonEach
Tested with
Related: #35518
The text was updated successfully, but these errors were encountered: