Skip to content

Conversation

@eernstg
Copy link
Member

@eernstg eernstg commented Nov 25, 2025

This PR specifies that it is a compile-time error to assign a value to a formal parameter declared by a primary constructor in the initializer list of the body part of the primary constructor, as well as in the initializing expression of a non-late instance variable declaration.

class A(int x) {
  final int y = x++; // Error.
  this: assert((x = x + 10).isEven) { // Error.
    x = y / 2; // OK.
  }
}

…ons (but a primary parameter can still be modified in the body of a primary constructor)
…ons (but a primary parameter can still be modified in the body of a primary constructor)
@eernstg eernstg requested a review from lrhn November 25, 2025 16:31
@lrhn
Copy link
Member

lrhn commented Nov 25, 2025

Do we want this?
It's a loss of expressiveness compared to existing constructors.

Example of something you could do using side-effects:

class StreamWrapper<T>([StreamController<T>? existingController]) {
   final Stream<T> stream;
   final StreamController<T> controller;
   init: 
      controller = existingController ??= StreamController(),
      stream = controller.stream;
}

Initializer list entries are (probably) run after all initializing expressions, so asssignments only affect themselves and the body block.
I feel like they are sequential enough in nature that it should be OK to assume an order.

It may be a little confusing if we have:

class C(int x) {
   final x1 = x;
   this: x3 = ++x;
   final x2 = x;
   final int x3;
}

because the three references to x are not in order.

Then don't do that. Put the this: after the instance variables, and everything is fine.

```

It is a compile-time error if an assignment to a primary parameter occurs
in the initializing expression of a non-late instance variable, or in the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(And late instance variables do not have access to those parameters at all, so definitely also an error if they try to assign to it. Right?)

initializer list of the body part of a primary constructor.

*This includes expressions like `p++` where the assignment is implicit.*

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we allow assigning to primary constructor parameters in the this block body? I could see the answer being "no" to be consistent with initializers and the initializer list. I could also see the answer being "yes" to be consistent with assigning other parameters in function bodies.

Either way, we should probably spell it out explicitly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants