dart-lang / dart-lang/language

Promoting variables of type T? to a nullable type

Open
#3,239 5 comments 0 reactions 0 assignees View on GitHub
question
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.