dart-lang / dart-lang/language
Generalize mixin inference to other superinterfaces?
- Dominant language
- TeX
- Stars
- 2.9k
- Forks
- 239
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 14
Description
### Mixin inference
[Mixin inference](https://github.com/dart-lang/language/blob/main/accepted/2.1/super-mixins/mixin-inference.md) allows us to omit type arguments from mixins in mixin applications and have them inferred:
```dart
interface class I {}
mixin M on I {
void showX() => print(X);
}
class A = I with M;
class B extends I with M {}
void main() {
A().showX(); // 'int'.
B().showX(); // 'String'.
}
```
This is possible because Dart prevents every interface type from having two superinterfaces of the form `S` and `S` where one or more `j` is such that `Tj` and `Uj` are different types (that is, `Tj <: Uj <: Tj` is not true, so they can actually differ in the choice of top type).
### A limitation: Types implemented by the mixin are ignored
The example above does not work if we change `on` to `implements`:
```dart
// Everything is identical to the previous example, except:
mixin M implements I {
void showX() => print(X);
}
```
With this variant of `M` the mixin inference algorithm chooses `M`, and we incur the error that `A` can't implement `I` and `I` at the same time, and similarly for `B`.
**Proposal**: We could include the types in the `implements` clause of the mixin as well as the ones in the `on` clause. This would provide more information about the actual requirements on the type arguments of the mixin as they are inferred, and hence it will succeed in some cases where the current algorithm fails.
We would need to handle the situation where the superclass `S` that the mixin is being applied to does not have a given interface type `I` in its superinterface graph. This will never happen when `I` was obtained from the `on` clause unless the mixin application is a compile-time error, but it _can_ happen when `I` came from the `implements` clause. If it does happen then `I` should just be discarded (there is no way it could contribute to the mixin inference result).
### Limitation 2: Types implemented by the class could have their type arguments inferred, too
It could make sense to infer omitted type arguments for types in the `implements` clause of a class using a similar approach. However, it makes no sense to have a type `T` in the implements clause if `T` already occurs in the superinterface graph of some other superinterface. So if we have `implements ... I ...` then we can't expect to find `I<...>` as a superinterface of the superclass.
**Proposal**: If we have `implements ... I ...` where `I` is a raw type, and `K` is a generic superinterface of `I` whose type has some type arguments that are influenced by `I` then we could use `K` to help finding some actual type arguments for `I`. We'd want to use the "nearest" superinterface in the superinterface graph of `I` which is present in the superinterface graph for the superclass.
This would presumably be big enough to be a separate feature.
### Limitation 3: Types implemented by the class could be used during mixin inference
This should be a rather simple addition to the mixin inference algorithm.
**Proposal**: Search the superinterface graph of each implemented type of the class in order to derive constraints about the actual type arguments of the mixin.
This would allow us to have successful mixin inference in cases where it currently fails because the type arguments of the mixin are underconstrained by the superclass.
### Implementation
A prototype implementation of the first proposal in the analyzer is available in https://dart-review.googlesource.com/c/sdk/+/376140.
Contributor guide
Assessment
This issue has not been assessed yet.