Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhanced Constructors #4246

Open
stereotype441 opened this issue Jan 31, 2025 · 3 comments
Open

Enhanced Constructors #4246

stereotype441 opened this issue Jan 31, 2025 · 3 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@stereotype441
Copy link
Member

This feature proposal extends the set of actions that can be performed in the body of a non-redirecting generative constructor to include writing to non-late final fields and explicitly invoking super constructors.

This makes constructors more flexible, avoids the need for constructor initializer lists, and allows constructor augmentations to behave more consistently with function augmentations.

To preserve soundness, flow analysis is enhanced to ensure that a reference to this cannot escape from a constructor body before the object has been completely constructed.

For details please see https://github.com/dart-lang/language/blob/main/working/enhanced-constructors/feature-specification.md

@stereotype441 stereotype441 added the feature Proposed language feature that solves one or more problems label Jan 31, 2025
@lrhn
Copy link
Member

lrhn commented Jan 31, 2025

Also a sketch of a similar feature here: #3002

I like the proposal. It handles all the tricky parts (I think).

I would suggest allowing const constructor bodies to also declare local final or const variables. That would finally avoid needing a redirect to introduce a named value that needs to be accessed from two initializer list entries.
And maybe if with throws. (But throw should be a constant expression anyway.)

I worry about closures created before the super constructor invocation.
Not because they can access variables, but because they close over this. That implies that there is an uninitialized object at that point. The current specification allows an implementation where field values are just stored in the stack, and the actual heap object isn't allocated until teaching the Object constructor, with the field values being copied from the stock at that point. That way there is never any partially initialized object, it goes from not existing to being fully initialized in one step.

Or in short: If you can close over this before it's initialized, it implies that an uninitialized object exists, and I'd rather not do that.

(The things I really want closures for are not things that can be allowed before being fully initialized.)

Hmm. Could you close over reading a late variable with an initializer expression? (Because those can refer to this, so you definitely can't be allowed to do that. So only definitely assigned variables can be read from closures, if any.)

@stereotype441
Copy link
Member Author

Thanks for the link, @lrhn! I searched for a little bit for prior art but somehow managed to miss #3002. There's a lot of good discussion in that issue.

@munificent
Copy link
Member

I love it. Ship it!

We might consider restricting field writes so that they can only occur as the top-level expression in an expression statement which is itself a direct descendant of the constructor body block.

I think this restriction would be annoying. It's a feature of this proposal that it enables users to do control flow in order to initialize fields. That's one of the main reasons I end up writing a factory constructor that forwards to a generative constructor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests

3 participants