dart-lang / dart-lang/language

Behavior of implicit coercions is inconsistent in the presence of assignments to promoted variables

Open
#1,968 1 comment 1 reaction 0 assignees View on GitHub
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

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.