Skip to content

Lint generic function literal in non-generic context #60415

@eernstg

Description

@eernstg

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-devexpFor issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages.devexp-linterIssues with the analyzer's support for the linter package

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions