Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Be more strict on inferred types with no constraints? #4197

Open
eernstg opened this issue Dec 6, 2024 · 1 comment
Open

Be more strict on inferred types with no constraints? #4197

eernstg opened this issue Dec 6, 2024 · 1 comment
Labels
inference question Further information is requested type-inference Type inference, issues or improvements

Comments

@eernstg
Copy link
Member

eernstg commented Dec 6, 2024

The specification of type inference in inference.md says about the greatest closure of a type in the section Type variable elimination that

- If `S` is `X` where `X` is in `L`
  - The least closure of `S` with respect to L is `Never`
  - The greatest closure of `S` with respect to L is `Object?`

which in the context means that the greatest closure of a type parameter which is in the target set L is Object?.

The section Type schema elimination says that _ is treated as a type parameter in the target set.

Next, the section Grounded constraint solution for a type variable says that

- Otherwise the solution is the greatest closure of `Mt` with respect to `_`.

which in the context means that when a type variable X has the combined constraint _ <: X <: _ then the solution is the greatest closure of _, that is, Object?.

Nevertheless, the implemented behavior chooses dynamic, at least in some cases:

X getContextType<X>(Object? o) {
  print(X);
  return o as X;
}

void main() {
  getContextType(1)..arglebargle; // 'dynamic'.
}

The fact that the analyzer does not report a compile-time error at the invocation of arglebargle shows that the type inferred for getContextType(1) is dynamic rather than Object?. The common front end confirms this by also not reporting a compile-time error, and further by printing dynamic at run time.

It is a breaking change, but I'd recommend that type inference is adjusted to infer Object? rather than dynamic in such cases. We could at least experiment with this outcome and see how severe the breakage is. The change would be language versioned such that developers can opt in to the more strict analysis when they are ready.

@dart-lang/language-team, WDYT?

@eernstg eernstg added question Further information is requested inference type-inference Type inference, issues or improvements labels Dec 6, 2024
@lrhn
Copy link
Member

lrhn commented Dec 6, 2024

(Why is the greatest closure of a type variable with a bound not its bound? Is it because that doesn't work for F-bounded types, or because we want to allow super-bounded types?)

This would be one way to avoid an implicit and un-asked-for dynamics, so I'm all for it.

Might be better to combine it with other "no implicit dynamic changes, though, so we can wipe them all out in one swoop, and users only need to migrate once.

(I'd also make the context type of an expressionStatement's expression be void, but that's another thing.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
inference question Further information is requested type-inference Type inference, issues or improvements
Projects
None yet
Development

No branches or pull requests

2 participants