-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
refactor autoderef to avoid prematurely registering obligations #33852
Conversation
Refactor `FnCtxt::autoderef` to use an external iterator and to not register any obligation from the main autoderef loop, but rather to register them after (and if) the loop successfully completes. Fixes rust-lang#24819 Fixes rust-lang#25801 Fixes rust-lang#27631 Fixes rust-lang#31258 Fixes rust-lang#31964 Fixes rust-lang#32320 Fixes rust-lang#33515 Fixes rust-lang#33755
let mut autoderef = self.autoderef(callee_expr.span, original_callee_ty); | ||
let result = autoderef.by_ref().flat_map(|(adj_ty, idx)| { | ||
self.try_overloaded_call_step(call_expr, callee_expr, adj_ty, idx) | ||
}).next(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice pattern, I like it!
#27631 is already closed btw, should it be in the description? I've noticed an observed change in behavior (picking mutable over immutable on field assignment, even through an immutable reference), and there's also the question of potentially hardening the system we have so obscure index out of bounds errors do not happen in the future. But other than that, it looks like a very nice refactoring, r=me with nits/questions addressed. |
updated |
@bors r+ |
📌 Commit 040fc94 has been approved by |
cc me |
@@ -463,24 +448,10 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { | |||
/////////////////////////////////////////////////////////////////////////// | |||
// RECONCILIATION | |||
|
|||
/// When we select a method with an `&mut self` receiver, we have to go convert any | |||
/// When we select a method with a mutable autoref, we have to go convert any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I think this comment is not as good as the one before, even if it is potentially more precise (at least in the future...). I always like to see concrete Rust code examples, particularly as our terminology tends to drift over time. :) "a mutable autoref (e.g., &mut self
)" would be better, for example.
Edit: tweaked wording.
(The nits I noted aren't worth stopping bors, btw.) |
So, just to be sure I'm following along: the ICEs here were caused by obligations that were being registered by the autoderef code, which were then in the fulfillcx but referencing type variables added in the snapshot -- thus when we rolled back, the variables leaked out, right? Hence this fixes it by just not registering any obligations during the snapshot. This seems good -- and in general I am trying to move us more towards returning obligations back up the stack vs registering them eagerly -- though I do wonder if we will encounter problems at some point where e.g. the type that we |
refactor autoderef to avoid prematurely registering obligations Refactor `FnCtxt::autoderef` to use an external iterator and to not register any obligation from the main autoderef loop, but rather to register them after (and if) the loop successfully completes. Fixes rust-lang#24819 Fixes rust-lang#25801 Fixes rust-lang#27631 Fixes rust-lang#31258 Fixes rust-lang#31964 Fixes rust-lang#32320 Fixes rust-lang#33515 Fixes rust-lang#33755 r? @eddyb
Beta-nominating for being a very annoying ICE. |
In @rust-lang/compiler meeting, decided not to backport:
|
…=arielb1 Ban registering obligations during InferCtxt snapshots. Back in rust-lang#33852, a flag was added to `InferCtxt` to prevent rolling back a snapshot if obligations were added to some `FulfillmentContext` during the snapshot, to prevent leaking fresh inference variables (created during that snapshot, so their indices would get reused) in obligations, which could ICE or worse. But that isn't enough in the long run, as type-checking ends up relying on success implying that eager side-effects are fine, and while stray obligations *do* get caught nowadays, those errors prevent, e.g. the speculative coercions from rust-lang#37658, which *have to* be rolled back *even* if they succeed. We can't just allow those obligations to stay around though, because we end up, again, in ICEs or worse. Instead, this PR modifies `lookup_method_in_trait_adjusted` to return `InferOk` containing the obligations that `Autoderef::finalize_as_infer_ok` can propagate to deref coercions. As there shouldn't be *anything* left that registers obligations during snapshots, it's completely banned. r? @nikomatsakis @arielb1
…=arielb1 Ban registering obligations during InferCtxt snapshots. Back in rust-lang#33852, a flag was added to `InferCtxt` to prevent rolling back a snapshot if obligations were added to some `FulfillmentContext` during the snapshot, to prevent leaking fresh inference variables (created during that snapshot, so their indices would get reused) in obligations, which could ICE or worse. But that isn't enough in the long run, as type-checking ends up relying on success implying that eager side-effects are fine, and while stray obligations *do* get caught nowadays, those errors prevent, e.g. the speculative coercions from rust-lang#37658, which *have to* be rolled back *even* if they succeed. We can't just allow those obligations to stay around though, because we end up, again, in ICEs or worse. Instead, this PR modifies `lookup_method_in_trait_adjusted` to return `InferOk` containing the obligations that `Autoderef::finalize_as_infer_ok` can propagate to deref coercions. As there shouldn't be *anything* left that registers obligations during snapshots, it's completely banned. r? @nikomatsakis @arielb1
…=arielb1 Ban registering obligations during InferCtxt snapshots. Back in rust-lang#33852, a flag was added to `InferCtxt` to prevent rolling back a snapshot if obligations were added to some `FulfillmentContext` during the snapshot, to prevent leaking fresh inference variables (created during that snapshot, so their indices would get reused) in obligations, which could ICE or worse. But that isn't enough in the long run, as type-checking ends up relying on success implying that eager side-effects are fine, and while stray obligations *do* get caught nowadays, those errors prevent, e.g. the speculative coercions from rust-lang#37658, which *have to* be rolled back *even* if they succeed. We can't just allow those obligations to stay around though, because we end up, again, in ICEs or worse. Instead, this PR modifies `lookup_method_in_trait_adjusted` to return `InferOk` containing the obligations that `Autoderef::finalize_as_infer_ok` can propagate to deref coercions. As there shouldn't be *anything* left that registers obligations during snapshots, it's completely banned. r? @nikomatsakis @arielb1
…=arielb1 Ban registering obligations during InferCtxt snapshots. Back in rust-lang#33852, a flag was added to `InferCtxt` to prevent rolling back a snapshot if obligations were added to some `FulfillmentContext` during the snapshot, to prevent leaking fresh inference variables (created during that snapshot, so their indices would get reused) in obligations, which could ICE or worse. But that isn't enough in the long run, as type-checking ends up relying on success implying that eager side-effects are fine, and while stray obligations *do* get caught nowadays, those errors prevent, e.g. the speculative coercions from rust-lang#37658, which *have to* be rolled back *even* if they succeed. We can't just allow those obligations to stay around though, because we end up, again, in ICEs or worse. Instead, this PR modifies `lookup_method_in_trait_adjusted` to return `InferOk` containing the obligations that `Autoderef::finalize_as_infer_ok` can propagate to deref coercions. As there shouldn't be *anything* left that registers obligations during snapshots, it's completely banned. r? @nikomatsakis @arielb1
Ban registering obligations during InferCtxt snapshots. Back in #33852, a flag was added to `InferCtxt` to prevent rolling back a snapshot if obligations were added to some `FulfillmentContext` during the snapshot, to prevent leaking fresh inference variables (created during that snapshot, so their indices would get reused) in obligations, which could ICE or worse. But that isn't enough in the long run, as type-checking ends up relying on success implying that eager side-effects are fine, and while stray obligations *do* get caught nowadays, those errors prevent, e.g. the speculative coercions from #37658, which *have to* be rolled back *even* if they succeed. We can't just allow those obligations to stay around though, because we end up, again, in ICEs or worse. Instead, this PR modifies `lookup_method_in_trait_adjusted` to return `InferOk` containing the obligations that `Autoderef::finalize_as_infer_ok` can propagate to deref coercions. As there shouldn't be *anything* left that registers obligations during snapshots, it's completely banned. r? @nikomatsakis @arielb1
Refactor
FnCtxt::autoderef
to use an external iterator and to notregister any obligation from the main autoderef loop, but rather to
register them after (and if) the loop successfully completes.
Fixes #24819
Fixes #25801
Fixes #27631
Fixes #31258
Fixes #31964
Fixes #32320
Fixes #33515
Fixes #33755
r? @eddyb