dart-lang / dart-lang/language
Flow analysis feature request: on join, promote to LUB
- Dominant language
- TeX
- Stars
- 2.9k
- Forks
- 239
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 14
Description
(This suggestion has come up a few times, most recently in https://github.com/dart-lang/sdk/issues/47105.)
Flow analysis currently maintains a list of promoted types for each variable called the variables promotion chain. When two control flow paths are joined, the promotion chains for each variable are intersected (meaning we retain any promotions made on both control paths, but exclude any promotions made on only one path or another). When types get excluded by this algorithm, we don't make any effort to replace them with a least upper bound.
So for example, this doesn't work:
```dart
f(Object x) {
if (x is int) {
// ...
} else if (x is double) {
// ...
} else {
return;
}
print(x + 1); // ERROR: x has type `Object`, which doesn't support operator `+`
}
```
In principle, flow analysis could be smarter and see that after the `if` statement, since `x` has either type `int` or `double`, it must have type `num`, in which case `x + 1` would be allowed.
I think a lot of the reason this sort of thing surprises people is that there are other places where the language does use least upper bound, for example:
```dart
f(int? x, double y) {
var z = x ?? y;
print(z + 1); // OK: z has type `num`
}
```
Contributor guide
Research direction
Start by studying flow analysis promotion chains and how they are intersected when control-flow paths join. Use the issue's int/double example as the target behavior, and consider the work complete when the joined variable is promoted to num so the subsequent addition is accepted without changing the existing int? and double example.
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
- Mostly clear
- Newbie friendliness
- 35/100