Skip to content
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

mixin member invalid override on non conflicting types error #57005

Open
bar4488 opened this issue Oct 31, 2024 · 4 comments
Open

mixin member invalid override on non conflicting types error #57005

bar4488 opened this issue Oct 31, 2024 · 4 comments
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). type-question A question about expected behavior or functionality

Comments

@bar4488
Copy link

bar4488 commented Oct 31, 2024

It seems that if 2 mixins declare the same member with different bounds, the type of the latter mixin member must conform to the type first mixin member, which can throw an error even in cases where the class using the mixin is able to satisfy both types.

mixin LongRangeWeapon {}

mixin ExplosionWeapon {}

class Shotgun with LongRangeWeapon, ExplosionWeapon {}

mixin Shooter {
  LongRangeWeapon get weapon;
}

mixin Bomber {
  ExplosionWeapon get weapon;
}

abstract class Combatant with Shooter, Bomber { // 'Bomber.weapon' ('ExplosionWeapon Function()') isn't a valid override of 'Shooter.weapon' ('LongRangeWeapon Function()')
  @override
  Shotgun get weapon;
}

expected behavior: There should not be any error as long as the class itself validly satisfies both mixin.

@bar4488 bar4488 changed the title multiple mixin member error mixin member invalid override on non conflicting types error Oct 31, 2024
@dart-github-bot
Copy link
Collaborator

Summary: The issue arises when two mixins declare the same member with different bounds. The type of the latter mixin member must conform to the type of the first mixin member, even if the class using the mixin can satisfy both types. This leads to an invalid override error, even when the class provides a valid implementation.

@dart-github-bot dart-github-bot added area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). triage-automation See https://github.com/dart-lang/ecosystem/tree/main/pkgs/sdk_triage_bot. type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) labels Oct 31, 2024
@lrhn
Copy link
Member

lrhn commented Oct 31, 2024

The problem being reported is that the class Object with Shooter, Bomber (the superclass of Combatant) has an invalid override.

The class Object with Shooter has a member LongRangeWeapon get weapon;.
The class Object with Shooter, Bomber has that class as superclass, and then declares a member with signature ExplosionWeapon get weapon;

Since ExplosionWeapon get weapon; is not a valid override of LongRangeWeapon get weapon;, that class is invalid.
That class exists! It might be abstract, anonymous and generally inaccessible (other than through super calls inside Combatant), but the language doesn't care. The class exists and has to be valid. Also because the interface of that class is the interface that Combatant inherits.

If you need to inherit multiple independent abstract declaration, it's better to use interfaces. Those are all added to the same class, and can be overridden by that classs. Mixins are applied sequentially, and all the intermediate classes must be valid.

@lrhn lrhn added type-question A question about expected behavior or functionality and removed type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) triage-automation See https://github.com/dart-lang/ecosystem/tree/main/pkgs/sdk_triage_bot. labels Oct 31, 2024
@bar4488
Copy link
Author

bar4488 commented Nov 1, 2024

I see, it would be really great if we could support such use-cases. This patten seems quite common in order to describe complicated traits tree.

It seems that a support for extended types would solve this problem, and also allow much more flexibility to the type system:

class A{}
mixin B on A{}
mixin C on A{}

typedef D = A with B,C

This would also allow for a class to declare members with type D, thus solving the problem stated in the issue.

Is there any issue open to support such a feature?

@lrhn
Copy link
Member

lrhn commented Nov 1, 2024

Not sure what such extended types world be.
You can write

class D = A with B, C;

today, but it has the same issue because it does introduce the intermediate mixin application classes too.

I am not aware of any proposal that would remember this issue.

Such a feature would change how mixin application works, either by removing some normal class constraints from the anonymous mixin application classes, or by collapsing mixin applications into a single class (like being augmentations instead of separate classes, but then not having the same constraints as augmentations).

Maybe the solution is to use interfaces to drive the combined types, and only use mixins for the final implantation, with no two mixins containing the same member, not even as abstract.
Or using generics for anything that differs between subclasses.

mixin LongRangeWeapon {}

mixin ExplosionWeapon {}

class Shotgun with LongRangeWeapon, ExplosionWeapon {}

mixin Shooter<W extend LongRangeWeapon> {
  W get weapon;
}

mixin Bomber<W extends ExplosionWeapon> {
  W get weapon;
}

abstract class Combatant<W extends Shotgun> with Shooter<W>, Bomber<W> {
  @override
  W get weapon;
}

// Or, of Combatant will not be extended
abstract class Combatant with Shooter<Shotgun>, Bomber<Shotgun> {
  @override
  Shotgun get weapon;
}

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). type-question A question about expected behavior or functionality
Projects
None yet
Development

No branches or pull requests

4 participants
@lrhn @bar4488 @dart-github-bot and others