Open eernstg opened 2 months ago
Consider a more complex example:
class A<T> {}
class B<FirstT extends A<SecondT>, SecondT> {}
If we write:
B<A<int>, _>
Would this infer B<A<int>, int>
?
Current type inference would not generate any constraints on SecondT
, so it ends up being a top type. Here's a variant of the example that shows the outcome:
class A<X> {
A(X x);
}
class B<Y extends A<Z>, Z> {
B(Y a) {
print('B<$Y, $Z>');
}
}
void main() {
B(A(42)); // 'B<A<int>, dynamic>'.
}
This is a valid result from type inference because binding Z
to a top type is actually a choice that allows us to satisfy all the subtype constraints.
However, we're currently working on an improvement of the type inference algorithm (see https://github.com/dart-lang/language/issues/3009) that gives rise to additional constraints. This will allow us to infer a tighter solution, namely B<A<int>, int>
.
So the proposal in this issue would allow us to ask for inference, and we'd then rely on other enhancements (of type inference itself) in order to get the more tight result.
PS: Yes, #3009 is about F-bounded type parameters, but the solution that we're currently evaluating is more general than F-bounds, and in particular it does allow us to bind Z
to int
in this example.
This is a proposal for supporting expressions like
MyClass<int, _>('Hello')
, where_
is used to indicate that the corresponding type parameter should be obtained from type inference. This allows us to specify some type arguments whose value would otherwise not fit the needs, and omit other type arguments whose inferred value is as desired. For example:We could allow a wildcard type argument that occurs as the last element of the actual type argument list to stand for multiple type arguments. For example, this would allow us to use
C<T1, _>
to stand forC<T1, T2, T3>
where bothT2
andT3
are inferred.There should not be a large amount of expressive power in this feature, but it does take a few steps to emulate it in the current language.
We can get the same effect today if we're willing to create a type alias for each choice of fixed type arguments, and if those type arguments can be denoted globally:
We can also use a function to support arbitrary choices of "fixed" type arguments:
It is a new feature to include a special (wildcard-ish) treatment of
_
when it is used as an actual type argument. It is also (slightly) breaking because it is possible today to declare some entities whose name is_
(e.g., top-level variables or, indeed, type parameters).However, I think it's more helpful to allow developers to request this kind of partial type inference by means of
_
than it is to preserve the ability to use a type whose name is_
as an actual type argument.In the end, it would actually be possible to create a type alias to provide access to such types under a different name: