dart-lang / dart-lang/language
Allow subtype constraint generation to strip null off of `Null`, following a similar rule for `dynamic` and `void`
- Dominant language
- TeX
- Stars
- 2.9k
- Forks
- 239
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 14
Description
This is a proposal in response to the request raised in https://github.com/dart-lang/language/issues/3796. The difficulty which is reported in said issue is that the following program is rejected:
```dart
void main() {
final w1 = W(D());
final w2 = W(E());
final w3 = W(null); // Compile-time error, "Couldn't infer type parameter 'T'".
}
abstract class C> {}
class D extends C {}
class E extends C {}
class W> {
const W(this.obj);
final T? obj;
}
```
We would probably be able to infer the type argument as `Never` by adding one case to one of [the rules](https://github.com/dart-lang/language/blob/main/resources/type-system/inference.md#rules) about subtype constraint generation:
> - If `Q` is `Q0?` the match holds under constraint set `C`:
> - If `P` is `P0?` and `P0` is a subtype match for `Q0` under constraint set `C`.
> - Or if `P` is `dynamic` or `void` and `Object` is a subtype match for `Q0` under constraint set `C`.
> - Or if `P` is `Null` and `Never` is a subtype match for `Q0` under constraint set `C`. **<--- Add this new case**
> - Or if `P` is a subtype match for `Q0` under **non-empty** constraint set `C`.
> - Or if `P` is a subtype match for `Null` under constraint set `C`.
> - Or if `P` is a subtype match for `Q0` under **empty** constraint set `C`.
This could be a useful behavior, also in practice, in spite of the fact that it introduces the type `Never`. Considering the given example, it does make sense to have an instance of `W` (which will be usable as a `W` for _any_ `T`), in particular because its `obj` is allowed to be "absent" by having type `T?`.
Intuitively, this rule will "strip the null off of `Null`", yielding `Never`, just like the previous rule allows us to strip the null off of `dynamic` and `void`, yielding `Object`.
Contributor guide
Research direction
Start with the subtype constraint generation rules in resources/type-system/inference.md and compare the existing handling of dynamic and void with the proposed Null case. Check the sample W, C, D, and E program against the inference behavior; done means the proposal is resolved and the intended inference of W is specified or accepted.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- dart
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100