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

conditional fallback for the ! type #79366

Conversation

nikomatsakis
Copy link
Contributor

@nikomatsakis nikomatsakis commented Nov 23, 2020

This branch represents a proposed means to handle fallback for the ! type. The intuition is that it sometimes falls back to ! and sometimes (). We prefer to fallback to ! but will fallback to () if the ! type may escape into live code.

Here is a write-up:

https://gist.github.com/nikomatsakis/7a07b265dc12f5c3b3bd0422018fa660

Fixes #66173
Fixes #67225
Fixes #66757

cc @rust-lang/lang
r? @matthewjasper

We used to avoid doing this because we didn't want to make coercion depend on
the state of inference. For better or worse, we have moved away from this
position over time. Therefore, I am going to go ahead and resolve the `b`
target type early on so that it is done uniformly.

(The older technique for managing this was always something of a hack
regardless; if we really wanted to avoid integrating coercion and inference we
needed to be more disciplined about it.)
I didn't like the sub-unify code executing when a predicate was
ENQUEUED, that felt fragile. I would have preferred to move the
sub-unify code so that it only occurred during generalization, but
that impacted diagnostics, so having it also occur when we process
subtype predicates felt pretty reasonable. (I guess we only need one
or the other, but I kind of prefer both, since the generalizer
ultimately feels like the *right* place to guarantee the properties we
want.)
Motivation: in upcoming commits, we are going to create a graph of the
coercion relationships between variables. We want to
distinguish *coercion* specifically from other sorts of subtyping, as
it indicates values flowing from one place to another via assignment.
Along the way, simplify and document the logic more clearly.
We now fallback type variables using the following rules:

* Construct a coercion graph `A -> B` where `A` and `B` are unresolved
  type variables or the `!` type.
* Let D be those variables that are reachable from `!`.
* Let N be those variables that are reachable from a variable not in
D.
* All variables in (D \ N) fallback to `!`.
* All variables in (D & N) fallback to `()`.
The comment seems incorrect. Testing revealed that the examples in
question still work (as well as some variants) even without the
special casing here.
Instead, we now record those type variables that are the target of a
`NeverToAny` adjustment and consider those to be the "diverging" type
variables. This allows us to remove the special case logic that
creates a type variable for `!` in coercion.
Instead, we now rely on the code that looks for a NeverToAny adjustment.
This could cause us to visit the start node twice.
Extend the `DepthFirstSearch` iterator so that it can be re-used and
extended with add'l start nodes. Then replace the FxHashSets of nodes
we were using in the fallback analysis with a single iterator. This
way we won't re-walk portions of the graph that are reached more than
once, and we also do less allocation etc.
@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Nov 23, 2020
@nikomatsakis nikomatsakis added I-nominated T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Nov 23, 2020
@mark-i-m
Copy link
Member

Fixes #67255

Is this the right one?

Also am I correct in assuming that this paves away for finally stabilizing !?

@nikomatsakis
Copy link
Contributor Author

@mark-i-m

Is this the right one?

Nope, fixed, thanks =)

Also am I correct in assuming that this paves away for finally stabilizing !?

That is my hope, yes.

@nikomatsakis
Copy link
Contributor Author

@bors rollup=never

@nikomatsakis
Copy link
Contributor Author

I'm thinking of preparing a variant of this PR that "stabilizes" the ! type so we can run a crater run and see what the effect would be if we used this fallback

@joshtriplett
Copy link
Member

That sounds like a great plan.

@nikomatsakis
Copy link
Contributor Author

Created #79470 for crater run

@crlf0710 crlf0710 added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 18, 2020
@bors
Copy link
Contributor

bors commented Dec 29, 2020

☔ The latest upstream changes (presumably #80449) made this pull request unmergeable. Please resolve the merge conflicts.

@camelid camelid added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jan 22, 2021
@JohnCSimon JohnCSimon removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 7, 2021
@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 1, 2021
@Dylan-DPC-zz
Copy link

@nikomatsakis do you still need this PR or we can close it and reopen later?

@nikomatsakis
Copy link
Contributor Author

@Dylan-DPC I think we can close it, although @Mark-Simulacrum and I were talking about some possible extensions here. But I don't see that having this PR open is helping anything.

@Mark-Simulacrum
Copy link
Member

Yeah, I don't think the PR being open is helpful. I still need to type up a summary of our discussion, but that'll go into a new issue.

bors added a commit to rust-lang-ci/rust that referenced this pull request Aug 21, 2021
…ckh726

Refactor fallback code to prepare for never type

This PR contains cherry-picks of some of `@nikomatsakis's` work from rust-lang#79366, and shouldn't (AFAICT) represent any change in behavior. However, the refactoring is good regardless of the never type work being landed, and will reduce the size of those eventual PR(s) (and rebase pain).

I am not personally an expert on this code, and the commits are essentially 100% `@nikomatsakis's,` but they do seem reasonable to me by my understanding. Happy to edit with review, of course. Commits are best reviewed in sequence rather than all together.

r? `@jackh726` perhaps?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet