Skip to content

Can't use const constructors with mixins #29396

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

Closed
Hixie opened this issue Apr 19, 2017 · 5 comments
Closed

Can't use const constructors with mixins #29396

Hixie opened this issue Apr 19, 2017 · 5 comments
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language).

Comments

@Hixie
Copy link
Contributor

Hixie commented Apr 19, 2017

Consider this code:

class Superclass {
  const Superclass(this.foo);
  final int foo;
}

abstract class Mixin {
  factory Mixin.fixed(int baz) = _FixedMixin;
}

class _FixedMixin extends Object with Mixin {
  _FixedMixin(this.baz);
  final int baz;
}

class Subclass extends Superclass with Mixin {
  Subclass(int foo, this.bar) : super(foo);
  final int bar;
}

I want the Mixin.fixed and Subclass constructors to be const, but today that isn't possible. It's not clear why.

@bwilkerson bwilkerson added the area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). label Apr 20, 2017
@eernstg
Copy link
Member

eernstg commented Apr 21, 2017

The main reason why these constructors cannot be const is that certain constructors are omitted when mixin application occurs. For example:

In order for _FixedMixin(this.baz); to be a correct constructor, it must include a superinitializer (that is, a clause that causes a constructor in the superclass to be invoked during instance creation). In your example that superinitializer is implicit because there is no explicit superinitializer, but it corresponds to having _FixedMixin(this.baz): super();.

The superclass of _FixedMixin is Object with Mixin, i.e., it is a class which is introduced by mixin application rather than a class which is introduced by a regular class definition. Such a class is implicitly equipped with some constructors (spec section 'Mixin Application'):

For each generative constructor named $q_i(T_{i1}$ $ a_{i1}, \ldots , T_{ik_i}$ $ a_{ik_i}),
i \in 1..n$ of $S$ that is accessible to $L_M$, $C$ has an implicitly declared 
constructor named $q'_i = [C/S]q_i$ of the form

  $q'_i(a_{i1}, \ldots , a_{ik_i}):\SUPER(a_{i1}, \ldots , a_{ik_i});$.

Decrypting the LaTeX and considering the same example, what we get is _owm(): super(), where _owm is the actual (generated) name for the class that I previously called Object with Mixin.

There is a problem here: The implicitly declared constructor is non-const, even in the case where its superinitializer invokes a const constructor (in which case the implicitly generated constructor could itself also have been const).

So, unfortunately, there is no way to obtain a complete chain of const constructors up to Object when some (direct or indirect) superclass is created by mixin application.

This is a known problem, and the overly simple implicit generation of constructors creates some other problems as well (see #9745, #15101). The problem has been known for a long time, and it hasn't had enough urgency to be fixed so far (and the fix isn't necessarily trivial), but it is certainly on the agenda at this point and this issue helps pushing it upwards.

I'll close this issue as a duplicate of #9745, and refer to this issue from there.

@eernstg eernstg closed this as completed Apr 21, 2017
@Hixie
Copy link
Contributor Author

Hixie commented Apr 6, 2018

This was marked as a duplicate of #9745, which is closed now, but it still doesn't seem to work. Taking the example above and marking the constructors const where the original comment says the desire is to have them be const gives:

test.dart:11:9: Error: Can't extend a mixin application and be 'const'.
  const _FixedMixin(this.baz);
	^
test.dart:16:9: Error: Can't extend a mixin application and be 'const'.
  const Subclass(int foo, this.bar) : super(foo);
	^
test.dart:11:9: Error: Can't extend a mixin application and be 'const'.
  const _FixedMixin(this.baz);
	^
test.dart:16:9: Error: Can't extend a mixin application and be 'const'.
  const Subclass(int foo, this.bar) : super(foo);
	^

...and:

  error • Const constructor can't be declared for a class with a mixin at test.dart:11:9 • const_constructor_with_mixin
  error • Const constructor can't be declared for a class with a mixin at test.dart:16:9 • const_constructor_with_mixin
class Superclass {
  const Superclass(this.foo);
  final int foo;
}
 
abstract class Mixin {
  const factory Mixin.fixed(int baz) = _FixedMixin;
}
 
class _FixedMixin extends Object with Mixin {
  const _FixedMixin(this.baz);
  final int baz;
}
 
class Subclass extends Superclass with Mixin {
  const Subclass(int foo, this.bar) : super(foo);
  final int bar;
}
 
void main() {
  const Subclass(0, 1);
  const Mixin.fixed(0);
}

I'm using Dart VM version: 2.0.0-dev.46.0.flutter-09e1766e6c (Thu Apr 5 18:12:11 2018 +0000) on "linux_x64".

@eernstg
Copy link
Member

eernstg commented Apr 9, 2018

You're looking for #32223, which is the request for implementation of this feature (this is area-language). You might say that we should have had a meta-bug for keeping track of these connections, but that didn't happen because the original request is so old.

@lrhn
Copy link
Member

lrhn commented Apr 9, 2018

The current specification for Dart 2 says that a mixin application of a mixin derived from a class with no field declarations, on top of a class with a const constructor, should make the forwarding constructor const.

That might not be implemented yet, but it should be eventually.

@eernstg
Copy link
Member

eernstg commented Apr 9, 2018

might not be implemented yet ..

Right, but it is requested in #32223, so that's the place to check out the current implementation status (and also to advocate for getting it done, if the current priority assigned to this task appears to be too low).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language).
Projects
None yet
Development

No branches or pull requests

4 participants