-
Notifications
You must be signed in to change notification settings - Fork 1.7k
[analyzer, cfe] Type inference fails with function type as type argument #52850
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
Here is a simpler version where type inference still fails (and uncommenting abstract class A {}
class C<Y, Z> {}
R m<R>(R Function<V>(C<V, V Function(V)>) body) => throw 0;
typedef F = List<U> Function<U>(C<U, U Function(U)>);
List<Object?> bar(F f) => m(<W>(d) => f/*<W>*/(d));
void main() {} This may or may not be related, but there is another behavior which is surprising: Comment out
|
Here's what's happening in this example (with
So as far as I can tell, everything is happening as designed. Our algorithm for type inference was deliberately designed to eagerly choose types after downwards inference if possible, because this makes things more tractable and tends to reduce spooky action at a distance. But it has the disadvantage that it doesn't take advantage of all the information that's avaiable. Specifically, in this case, at the time of downward inference on
...which is trivially satisfied by any choice of
...which is equivalent to:
...and hence can only be satisfied by choosing to set A possible improvement we could consider would be to leave the type List<Object?> x = [1, 2, 3]; // Means `<Object?>[1, 2, 3]` due to downwards inference
x.add('foo'); // If the line above is inferred differently, this will become a runtime error We might be able to achieve this by an algorithm like this:
|
That's an amazing analysis, @stereotype441! Here is a minimal example: abstract class A {}
class C<Y> {}
List<U> Function<U>(U Function(U)) f = <U>(c) => <U>[];
List<Object?> g<W>(W Function(W) d) => f/*<W>*/(d); This library causes a compile-time error to be reported at In short, the context type This normally fine: The context type is usually an upper bound (so if we can't use an actual type argument However, in this particular case we can't use the supertype, because the type parameter In other words, we might want to use the current approach (based on the context type whenever possible) in all cases where we are inferring actual type arguments for a generic function invocation where the parameter types are covariant in all type parameters, but in the case where some parameter types are non-covariant in some type parameters we could use bottom-up inference. |
I've developed the idea above a bit more and created dart-lang/language#3212 to discuss it. |
I'll close this issue because type inference proceeds as intended. The issue dart-lang/language#3212 contains a proposal about how it could be adjusted, based on the lessons learned in this issue. |
Consider the following program:
This program is rejected by the analyzer and the CFE (6a4ef6c), indicating that the type inference step failed to find a suitable type argument for the invocation of
f
:The program has no errors if
f(d)
is replaced byf<X10>(d)
.The surprising part is that the error message seems to imply that the static type of the actual argument is
_C<X10, X10 Function(X10)>
(which may also be written asC<X10>
), and the formal parameter type is_C<A, A Function(A)>
akaC<A>
, so the inferred type argument for the invocation off
isA
, even though that does not satisfy the given constraints.Is this working as intended, or should we generate some additional constraints during this type inference step?
The text was updated successfully, but these errors were encountered: