-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
The never type and diverging type variables #85021
Conversation
(rust-highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #84107) made this pull request unmergeable. Please resolve the merge conflicts. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Previously, the never type will be replaced by a diverging type variable (generally) only if some coercion occurs. It can cause inconsistent behaviors like ```rust return.foo(); //~ ERROR no method named `foo` found for type `!` { return }.foo(); //~ ERROR type annotations needed ``` ```rust let a = (return, ); // The type is `(!, )`. let a = ({ return }, ); // The type is `(_, )`. let a: (_, ) = (return, ); // The type is `(_, )`. ``` With this commit, the never type will be replaced by a diverging type variable just at the end of the type check for every expression, even if no coercion occurs. Thus the problems above get solved and the consistency should be improved.
Previously, we issue "type annotations needed" when types must be known at some point but the resolution failed, even if the type variables are just some diverging ones. A typical example is `{ return }.foo()`. With this commit, the information about diverging is recorded in the unification table, so that we can check whether performing the fallback affects other non-diverging type variables. If it doesn't, we will safely perform the fallback and we won't issue "type annotations needed" anymore. Note lots of auxiliary type variables should be ignored during the check, which is done with the help of `TypeVariableOriginKind`. As a result, "type annotations needed" will be issued for ```rust let a = return; { if true { a } else { return } }.foo(); ``` but not for ```rust let a: ! = return; { if true { a } else { return } }.foo(); ```
☔ The latest upstream changes (presumably #85290) made this pull request unmergeable. Please resolve the merge conflicts. |
Resolved conflicts in PR: #85558 |
Thanks for the PR @lrh2000 (and for the rebase, @lovishpuri!), sorry I haven't had time to go over it in detail yet. |
ping from triage: |
Closed due to inactivity and no positive feedback (so I'm not sure whether it is on the right road). |
Previously, the never type will be replaced by a diverging type variable (generally) only if some coercion occurs. It can cause inconsistent behaviors like
With the first commit, the never type will be replaced by a diverging type variable just at the end of the type check for every expression, even if no coercion occurs. Thus the problems above get solved and the consistency should be improved.
Then, another problem is we'll issue too many "type annotations needed". They are issued when types must be known at some point but the resolution failed, even if the type variables are just some diverging ones. A typical example is
{ return }.foo()
.With the second commit, the information about diverging is recorded in the unification table, so that we can check whether performing the fallback affects other non-diverging type variables. If it doesn't, we will safely perform the fallback and we won't issue "type annotations needed" anymore.
As a result, "type annotations needed" will be issued for
but not for
cc @nikomatsakis
cc @Mark-Simulacrum
Discussed at https://rust-lang.zulipchat.com/#narrow/stream/259160-t-lang.2Fproject-never-type/topic/Never.20type.20in.20tuple .