Description
The discussion in dart-lang/sdk#54284 showed that the following declarations are accepted by the analyzer as well as the common front end (808fa4ca8b5fbc3d79ade02f607b8533c9714029):
class Foo1 {
final Function a;
final int b;
Foo1()
: a = <T>() {},
b = 0;
}
class Foo2 {
final Function a;
Foo2() : a = <T>() => 0;
}
void main() {}
However, the language specification has a rule which says that <initializerExpression>
does not derive a <functionExpression>
. This should cause the above constructor declarations to be syntax errors.
It could be argued, though, that this is benign: The rule against deriving an initializer expression into a function expression is motivated by a readability issue. In particular, it is in some situations impossible to decide whether a given function body is the body of a function literal which is used to initialize an instance variable, or it's the body of the enclosing constructor declaration, until the very end of that body has been reached: If there's a semicolon then it was the function literal body, if there is no semicolon then it was the constructor body. That's a potentially large amount of code to scan, just to see if there is a semicolon (and nobody will do it unless they are syntax nerds ;-).
However, this ambiguity only exists because the formal parameter list may look like an expression (()
could be a formal parameter list or the empty record, (x)
could be a parameter list or a parenthesized expression, and (x, y)
could be a parameter list or a record literal). This is not true when the function literal is generic: <T>(...)
is not an expression (for now, at least ;-).
So we could update the spec to say that <initializerExpression>
cannot derive a non-generic function expression.
This spec change would not give rise to any implementation effort because the tools already behave in this way.
@dart-lang/language-team, WDYT?