dart-lang / dart-lang/language
Infer the return type of a cycle-free arrow getter
- Dominant language
- TeX
- Stars
- 2.9k
- Forks
- 239
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 14
Description
Cf. [this comment](https://github.com/dart-lang/language/issues/395#issuecomment-1639762517).
Type inference is applied to non-local variable declarations. For instance:
```dart
var x = 10;
void main() {
x = true; // Error, because `x` has the inferred declared type `int`.
}
```
Type inference fails and causes a compile-time error in the case where it involves circular dependencies, even in cases where those dependencies do not give rise to non-termination of the initialization step:
```dart
// Circular dependency error.
var x = () { print(y); return 1; } ();
var y = () { print(x); };
```
Interestingly, a variant of this program that makes `x` a getter is accepted:
```dart
get x { print(y); return 1; }
var y = () { print(x); };
void main() {
print('$x, $y'); // Terminates.
}
```
Presumably, this choice was made because getters are assumed to give rise to general computation, and hence it is a futile exercise to try to show that non-termination is guaranteed or even likely.
The other notable difference is that `get x` has return type `dynamic`, because no attempt is made to infer the return type of a getter.
As @roblframpton mentions in https://github.com/dart-lang/language/issues/395, this difference seems to have a rather tenuous motivation. In particular, there is no apparent difference between the complexity associated with type inference of a getter of the form `get x => e;` and a variable declaration of the form `late final x = e;`.
We could make the choice to perform the same cyclicity analysis on getter declarations as the analysis that we currently use on non-local variable declarations, and infer the return type of a getter in the case where no cycles were detected.
For getter declarations with cyclic dependencies we could (1) report a compile-time error and ask the developer to write the return type explicitly, or (2) use `dynamic` (same as today). The former option would be helpful for anyone who wants to avoid `dynamic` in the signatures of widely available declarations, and the latter option would be less breaking in software where many getters have return type `dynamic` because no return type was declared.
This proposal should not make Dart software less statically typed than it would otherwise be, even in the case where we choose option (2): Some getters with no declared return type would now have a non-`dynamic` return type, and other getters would keep the same return type (which is `dynamic`). Also, we will presumably continue to help developers who wish to avoid the type `dynamic` in their APIs (`strict-inference: true` in 'analysis_options.yaml' will do).
@dart-lang/language-team, WDYT? Is there a good reason why we shouldn't perform type inference on non-recursive getters with no declared return type?
Contributor guide
Research direction
Start with the linked comment and Dart language issue 395 to understand the existing inference rules for non-local variables and getters. Compare the proposed cycle analysis with the current behavior described in the examples. Done requires an agreed design for recursive and cycle-free getters, including whether cyclic cases report an error or retain dynamic.
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
- 30/100