dart-lang / language

Design of the Dart language
Other
2.65k stars 201 forks source link

Can class fields be assigned in pattern assignments? #3096

Open deakjahn opened 1 year ago

deakjahn commented 1 year ago

Trying to decompose a record to class fields gives the error "Only local variables can be assigned in pattern assignments". Is this unavoidable? Couldn't it be solved so that we can assign to class fields as well?

lrhn commented 1 year ago

It's not unavoidable, but it gets harder to parse when the thing inside the pattern can be either a destructuring or a an assignable expression. Currently the only assignable expressions allowed are plain identifiers, and only ones referring to local variables.

Nothing prevents allowing more assignable selectors, like:

(foo.x, elements[0], z /* non-local variable in scope */) = (1, 2, 3);

We just need to be absolutely sure we can parse it correctly, and that it's also readable by humans.

Allowing any selector means allowing any expression to start the position, because:

(expression.foo,) = (1,);

allows any expression (which has a type which has a foo setter), so it opens up a large can of worms to allow general assignable expressions.

deakjahn commented 1 year ago

As a first step, the "plain identifiers" restriction would seem acceptable to me but not only to local variables. Straight fields, in my opinion, might be needed in this place very often.

munificent commented 1 year ago

Even that restriction can get weird because you could still be invoking a setter method or initializing a late field. It's probably tractable and I can see us enabling this at some point. The initial version of the proposal did. But it does get sort of complex which is why we don't currently allow it.

ilovelinux commented 1 year ago

As a first step, the "plain identifiers" restriction would seem acceptable to me but not only to local variables. Straight fields, in my opinion, might be needed in this place very often.

Totally agree. My use case was about assigning values to instance variables.

natebosch commented 2 months ago

I just ran into this today in a review. I wanted to suggest that a serialized set of async tasks could use the record .wait extension, but I can't do it when some of the assignments are to class fields.

munificent commented 2 months ago

Yeah, it's a reasonable extension, we just have to work through all of the consequences around late and lazy statics.

Also, if we allow irrefutable pattern assignment expressions to assign to fields, then users might also expect patterns in field and top-level declarations, like:

class C {
  final (int x, int y);
}

Then we have to figure out how that interacts with late and initializer lists.