dart-lang / dart-lang/language
Behavior of implicit coercions is inconsistent in the presence of assignments to promoted variables
- Dominant language
- TeX
- Stars
- 2.9k
- Forks
- 239
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 14
Description
The Dart language currently supports three kinds of implicit coercions based on context type:
- Coercion of an expression with generic function type to one with non-generic function type by implicitly supplying type arguments (when the context type is an appropriate non-generic function type).
- Coercion of an integer literal to a double literal (when the context type is `int`).
- Coercion of an interface type that supports `.call` to a tearoff of `.call` (when the context type is an appropriate function type).
With null safety, when there is an assignment to a promoted variable, the promoted type is used as the context type for analyzing the RHS of the assignment; the variable is only demoted if the static type of the RHS fails to be assignable to the promoted type. So I would expect all three of these kinds of coercions to take place on the RHS of an assignment to a promoted variable, when the promoted type is appropriate to trigger the promotion.
According to my experiments, this appears to be true of the first two types of coercions, but not the third (note, however, that there's an open bug on the CFE when the RHS is a function literal: https://github.com/dart-lang/sdk/issues/47607). For example:
```dart
T g(T t) => t;
main() {
Object o = (int x) => x;
o as int Function(int); // Promote o
o = g; // Is this demoted or coerced by implicitly applying ``?
print(o(1)); // OK; it must have been coerced.
}
```
```dart
void f(double d) {
print(d);
}
main() {
Object o = 1.5;
o as double; // Promote o
o = 1; // Is this demoted or coerced to 1.0?
f(o); // OK; apparently it was coerced.
}
```
```dart
class C {
int call(int x) => x;
}
main() {
Object o = (int x) => x;
o as int Function(int); // Promote o
o = C(); // Is this demoted or coerced using implicit `.call`?
print(o(1)); // ERROR; apparently it was demoted.
}
```
In my mind, the third example should also be free from errors, because `o = C();` should trigger a coercion (and thus be desugared to `o = C().call;`), so the assignment shouldn't demote.
Contributor guide
Assessment
This issue has not been assessed yet.