Skip to content

Allow var type id in non-declaring constructor parameter lists? #4179

Open
@lrhn

Description

@lrhn

@munificent has a glorious write-up of declaring constructors: #4169

It allows var int x as a parameter in declaring constructors, as a way to introduce a mutable instance variable. 🎉
The grammar allows 'var' <type> <identifier> in every parameter, and the feature spec then disallows a var+type from occurring in a non-declaring constructor using prose (it's a compile-time error if a parameter containing var occurs in a non-declaring constructor parameter list).

I suggest we just allow it everywhere. It's easier than disallowing it, and the meaning is obvious. It makes var and final (finally) be symmetric.
It is unnecessary, because var int x means the same as int x, but var x and x also means the same thing in parameters, and we allow both.

One argument against is that if anyone does write var int x as a normal parameter, someone else might initially read it as a field parameter, even though it's not a declaring constructor.
Most likley, nobody will write that. They don't write var x today, even though it's valid. They don't write final int x in parametes, even in code that insists on every local variable being final if it can be.
I don't think we'll see an up-tick in occurrences of final int x in normal parameters, or occurrences of var int x at all, so the confusion risk should be minimal.
That also means that there is no benefit to allowing the syntax. (Hypothetically, allowing var int x everywhere means that you can safely change any final to var in a variable declaration, without having to do anything else. Might be easier for code generators. But I don't expect users to just blindly replace final with var without looking at a declaration.)

It does mean that the same syntax means different things in different places, which is usually bad.
That's already the case for final int x in declaring constructors, and this way, the issue would be symmetric in var and final. It'll be one less exception to remember, you can think of var and final as symmetric.
(Rather than: "You can use var int x and final int x in declaring constructors to declare a var/final field. In other parameters var int x is an error. In other constructors final int x means a final parameter.", it becomes "You can use (var|final) int x in declaring constructors to declare a var/final field. In other parameters, (var|final) int x just introduces a var/final parameter variable." It's symmetric, if you understand the difference between var and final, you can apply the consistenly, so I'd count this as a complexity score of 2 vs 3 when disallowing var int x elsewhere. It all counts!)

It's only parameters, though, you can't actually declare a field as var int x;. But you can write var (int x) = .... I'd be fine with allowing var int x; for variables too.
(Allowing var int x; may be a stepping stone to final-by-default, if we ever want that. I do, don't know about "we".)

Options:

  • Allow var int x as parameter everywhere. (My proposal.)
    • Go all in: Allow it in variable declarations too, late var int x = 42;. (Maybe, eventually.)
  • Disallow in parameters not in a declaring constructor. (Specified in feature spec.)
    • Also, eventually, disallow final in non-declaring constructor parameters. (Suggested in feature spec.)
    • Or lint against it. (Suggested in feature spec.)

WDYT?
@dart-lang/language-team

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureProposed language feature that solves one or more problemsprimary-constructors

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions