Skip to content

[Field Promotion] Promotion of fields on final classes #3050

Open
@leafpetersen

Description

@leafpetersen

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 of final (or sealed) 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 change

Currently, 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 public final fields, removing final from the class breaks downstream clients. For sealed, it is already very breaking to remove the modifier: however since sealed 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:

  • For a final class, doing so changes promotion behavior directly
  • For a base or simple class, there may be unknown final classes which inherit from the class and expose the member to promotion

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    class-modifiersIssues related to "base", "final", "interface", and "mixin" modifiers on classes and mixins.field-promotionIssues related to addressing the lack of field promotion

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions