-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Consider the following program:
void foo(void Function(int) _) {}
void main() {
foo(<X>(p) => p.whatever); // Allowed because `p` has type `dynamic`.
}The treatment of the function literal <X>(p) => p.whatever is error prone: The context type is a non-generic function type (void Function(int)) and the function literal is generic, which gives rise to an implicit step known as a generic function instantiation that transforms the generic function into a non-generic function by providing actual type arguments for the given formal type parameters (here: a value for X is provided).
The crucial part is that the context type doesn't contribute to the choice of type annotations in the generic function literal because it doesn't "fit" (a generic and a non-generic function type are so different that no parameter in the function literal has a 'corresponding' parameter in the context type). So every parameter of such a function literal will get the type dynamic.
(It is possible to get a heads-up by enabling strict-inference, but by default this happens silently.)
The situation can very easily remain undetected because the resulting function literal uses the type dynamic for every parameter, and this gives the function literal a type which is a subtype of every function type with the same number of positional parameters and the same names for named parameters (that is: same shape, and we're happy!).
The situation further remains undetected because the body can do whatever it wants with the parameters, because they all have the type dynamic.
This means that the function literal seems to type check just fine, but it is in fact entirely unsafe.
Hence, this issue requests a lint that flags a function literal with the following properties:
- The function literal is generic.
- The context type is a non-generic function type.
It would be pragmatically useful to detect that there is no other error with this function literal. E.g., if the parameter list shapes are different in such a way that the function literal can't be a subtype of the context type (even after generic function instantiation) then we'll get a "not assignable" error (or we might get an unwanted demotion of a promotable variable). This may or may not cause the lint which is proposed here to be considered redundant.