dart-lang / language

Design of the Dart language
Other
2.67k stars 205 forks source link

Allow "abstract" mixin application classes with missing parts in augmentations? #4060

Open eernstg opened 2 months ago

eernstg commented 2 months ago

Thanks to @sgrekhov for bringing up this topic. This issue is similar to https://github.com/dart-lang/language/issues/4025 and https://github.com/dart-lang/language/issues/4008 in that it is concerned with incomplete declarations whose semantics can be well-defined because the missing elements are provided by augmentations.

In this issue it's about mixin application classes (the class declarations with an =):

class A {}
mixin M1 {}
mixin M2 {}

class B = A with M1;
augment class B1 = A with M2; // Allowed? Means `B1 = A with M1, M2`.
augment class B2 = with M2; // Allowed? Means `B2 = A with M1, M2`.

I'd recommend that we keep this in mind, but don't do anything at this time. It should not be a problem to add support for this kind of augmentation later on, and it will not be a breaking change.

@dart-lang/language-team, WDYT?

lrhn commented 2 months ago

The syntax is annoying.

We could allow you to augment

class B = A with M;

as

augment class B with M2;

Here class B is a class with no declared body, one declared superclass and one declared mixin. The concrete syntax doesn't matter (but it's the only syntax that allows having no class body).

The augmentation is allowed to add further declared mixins and interfaces, and does that with the same syntax as for any other augmenting class declaration, but it can add no members and no class body, since B has no member scope to augment.

jakemac53 commented 2 months ago

Yeah I think we should not do this at this time, but we could always allow it later and figure out the syntax at that point (although I much prefer something like the proposed alternate fwiw).

leafpetersen commented 2 months ago

I think my proposal would be to remove the mixin application class syntax in an upcoming language versioned release (or the next major release), and then we don't have to worry about this at all.

eernstg commented 1 month ago

If we drop this syntax then we might want to introduce some other way to request the implicit provision of a bunch of forwarding constructors:

abstract class A {
  A.constructor1(); // This would be verbose: Lots of parameters and stuff.
  A.constructor2(); // Ditto.
  // ... lots more

  void foo();
}

mixin M1 {
  void foo() => print('One implementation of `foo`.');
}
mixin M2 {
  void foo() => print('Another implementation of `foo`.');  
}

class B1 = A with M1;
class B2 = A with M2;

Class B1 and B2 would be rather verbose if we didn't have this mechanism, and they would contain a lot of redundant elements that we can't otherwise abstract away.