Skip to content

Module restrictions and mixins #1696

Closed
Closed
@lrhn

Description

@lrhn

Comments on https://github.com/dart-lang/language/blob/master/working/modules/feature-specification.md

The grammar declarations contain:

classDeclaration         ::= 'open'? 'interface'? 'mixin'? 'class' // ...
mixinDeclaration         ::= 'open'? 'interface'? 'mixin' // ...

I do not want to conflate mixins and classes. Those are two separate kinds of declarations, and I would very much like to get rid of the current ability to mix in classes (q.v. #1643). If the mixin class is intended to support the current mixin-able classes, I'd just remove it and not allow that. If we touch this area, that's a very good time to remove the ability to mix in classes entirely. (Any time is a good time IMO, the best time would be yesterday!)

I'm also not sure it makes sense to extend a mixin declaration.
Not yet, at least, we don't have composite mixins, and you can't do extends mixin anyway. I'd remove the 'open'? from mixinDeclaration for now, writing open in front doesn't mean anything unless we add the ability to actually extend them.
(Unless lacking open would mean that you cannot extend something mixing in the mixin. I'm not sure that's a good idea, but it would be consistent. We'd then need a different word if we ever introduce composite mixin declarations, so I think I'd prefer to reserve open for that).

That means that anywhere later where it talks about instantiating mixins, or mixins having generative constructors (any constructors, really), it should be dropped. Mixins do not have constructors, and cannot be instantiated.

(I also think abstract interface class should be a possibility, cannot instantiate, can extend or implement).

Like slightly later where it states:

  • It is a compile-time error to invoke a generative constructor of a type if the type defines or inherits any unimplemented abstract members. You can directly construct anything internally if it wouldn't cause a problem to do so, even an interface or an abstract class. TODO: Even a mixin?

You can't instantiate a mixin declaration. It must be mixed onto a superclass before it even becomes a class, which is what can be instantiated. While we still, effectively, have mixin class declarations, it's the class you are instantiating, not the mixin which can be derived from it.

(The usual model for the first sentence is to say:

  • It's a compile-time error to invoke a generative constructor of a class if the class does not have a valid implementation for all members of its interface.

So, don't look at declarations, look at implementation vs interface. We might need another name for "interface" if we have classes without an interface, they still have a signature, just not one you can implements).

And much later:

  • It is a compile-time error if a public-named type marked mixin defines any constructors. TODO: Is this restriction correct?

Yes, it's currently correct. We could allow factory constructors (we do allow static methods, and factory constructors are basically static methods with trickier type parameters and a fixed return type), and with interface mixin declarations we might want to allow factory constructors.


If we allow any use "internally", but only declared uses externally, then it does become an issue that we separate mixins and class declarations.
You cannot do interface Foo { ... } and use it as a mixin, because it is not a mixin and you can't mix-in non-mixins (please, do not allow that!). But if you write interface mixin Foo { ... } then the type is publicly a mixin.

Instead of allowing you to internally ignore any constraints, should we instead allow you to declare something as interface _mixin where it's only privately a mixin?


About:

Capabilities on legacy classes

The above syntax means that it an error to implement, mixin, or extend a class declared just using class. This would break nearly all existing Dart code. To avoid that, we specify that Dart classes that are not in modules are implicitly treated as if they were declared as open interface mixin class.

That sounds like an implicit language versioning. Why not just use explicit language versioning, and migrate existing code by adding open interface in front of all classes, and maybe combine with #1643 to migrate code extending a "mixin class" to with Name instead of extends Name.

(Might be worth mentioning that you can make non-extensible classes today by not exposing a public generative constructor.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions