-
Notifications
You must be signed in to change notification settings - Fork 214
[Field Promotion] Promotion of fields on final classes #3050
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
Comments
(Local promotion only:)
We need to be sure that we are actually accessing the final field, so all subclasses must be declared inside the same library (so the class must be sealed, final or private, and all subclasses must also be sealed, final or private), and all concrete subclasses must all have promotable fields too. Our existing local final field promotion handles the "private" part of this. We could extend it to cover Or more generally: If we have a library-contained subclass hierarchy, and all concrete subclasses in this hierarchy have final fields for a particular name, then we can safely consider that getter stable inside that library, and promote its value. But we can now add However, including "private" in the allowed subclasses is probably too tricky. We need to prevent type aliases for the private class being visible outside of the library too, so maybe "sealed or final" for the class, and all subtypes declared in the same library, and all of those having only final fields for that getter. What we have today (soon) is:
What we can add is:
|
Your summary of the objections covers my exact concerns with allowing promotion on all
Exactly right. And, in fact, a large part of the motivation for adding both That suggests a strawman: Sealed fieldsA field can be marked
By the last two bullet points, I mean basically that every implementation of a But the basic idea is that we give users a different modifier they can use on fields that gives them promotability but in turn makes the API more rigid with regards to breaking API changes and overrides. I don't know if this is actually a good idea or not. Asking users to choose promotability versus evolvability for each field declaration might be a big lift. I don't know what the best practices would be around when to use |
I'd much rather have a modifier like |
thats what final is for. i think that it would be sane to just have final classes allow for local field promotion since you can easily tell that nothing else overrides it. it also will not be breaking to remove final, or add a re-opened subclass, because you, the owner of the library, are the only one affected. outside of the library, its treated as the getter it sees. (since its not like anything outside of the class can know its a field anyway - that's what the stable getters proposal is for.) |
Uh oh!
There was an error while loading. Please reload this page.
With the new class modifiers feature, we have the ability express classes for which all subtypes are restricted to the same library as the defining class. This provides a path to defining a sound version of field promotion in which
final fields
on instances offinal
(orsealed
) classes could be subject to promotion. This issue is for discussing the tradeoffs involved.Reasons not to do this
Several objections have been raised to this proposal, summarized here.
Removing the
final
modifier becomes a breaking changeCurrently, it is not a breaking change to remove the
final
modifier from a class. Allowing promotion on fields of final classes would change this - if the class had any publicfinal
fields, removingfinal
from the class breaks downstream clients. Forsealed
, it is already very breaking to remove the modifier: however sincesealed
classes are abstract, they are mostly only useful through their non-sealed
subclasses which just pushes the issue off.Changing a final field to a getter (and vice versa) becomes a breaking change.
Currently in Dart it is not a breaking change to switch between a
final
field and a getter. This field/getter symmetry is valued by many Dart programmers. Allowing promotion of final fields would break this, since changing a final field on a final class would break any clients using promotion. Moving in the other direction (getter to field) is also in principle breaking, since in more limited cases it can be breaking to do promotion where it was not previously done.Note that this does not just apply to fields defined in final classes. For any public class except one marked
interface
, moving between a field and a getter would be breaking:Options for addressing the concerns above
Local promotion only
We could allow promotion only for uses of final fields on final classes within the same library as the definition of the class. We'd also need to restrict this to fields which are themselves declared in the same library as the class (rather than inherited) to avoid implicitly promoting a field from another library.
Note that it's not clear that we would want to restrict ourselves to final classes in this case: there's no real reason not to do this for all classes.[Edit: as pointed out below, this doesn't work of course because of overrides]Explicit opt in at the field declaration
Use some kind of syntax at the definition site of the field (e.g. something like stable getters) to mark fields which are intended to be promoted
cc @dart-lang/language-team @mraleph
The text was updated successfully, but these errors were encountered: