dart-lang / dart-lang/language
Promoting variables of type T? to a nullable type
- Dominant language
- TeX
- Stars
- 2.9k
- Forks
- 239
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 14
Description
Consider the following program.
```dart
test(T? t) {
if (t is String?) {
T? t2 = t;
String? t3 = t;
var l = [t];
l.add(null);
print(l);
}
}
main() => test("foo");
```
The program attempts to promote a variable of type `T?` to `String?`, ensures that it's assignable to both `T?` and `String?` after the promotion, creates a list containing `t` as its only element, relying on the static type of `t` in inference of the type argument of the type of the list, and then adds `null` as another element of that list.
The program is accepted by both the CFE and the Analyzer, and prints the following when run.
```
[foo, null]
List
```
Some observations on the behaviour of the tools are the following:
1. Promotions of variables of type `T?` where `T` is a type variable should not be possible in the language, but both tools seem to be fine with it.
2. The reified type, provided as the type argument to the list literal by the inference, seem to be nullable, according to both the CFE and the Analyzer.
3. According to the output of the program, the type of the list literal is `List`, even though the CFE provides `T?` as the type argument in the Kernel intermediate representation, as shown below.
```
library /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
static method test(self::test::T? t) → dynamic {
if(t is{ForNonNullableByDefault} core::String?) {
self::test::T? t2 = t{self::test::T? & core::String? /* '?' & '?' = '?' */};
core::String? t3 = t{self::test::T? & core::String? /* '?' & '?' = '?' */};
core::List l = core::_GrowableList::_literal1(t{self::test::T? & core::String? /* '?' & '?' = '?' */});
l.{core::List::add}(null){(self::test::T?) → void};
core::print(l);
core::print(l.{core::Object::runtimeType}{core::Type});
}
}
static method main() → dynamic
return self::test("foo");
```
As far as I remember, promotions of variables with static type `T?`, where `T` is a type variable, should not be possible. Given that both tools allow it, removing such promotion would be a potentially breaking change. Should we allow such promotions in the spec?
If so, what static type should the promoted variables have? The CFE currently provides `T? & String?`, as I guess it, by accident. An alternative would be `(T & String)?`.
What the reified type of the promoted type should be, that is, what should be given as the type argument to the list type in the example? What is the expected behaviour of the backends in regards to that type?
Contributor guide
Assessment
This issue has not been assessed yet.