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

refactor autoderef to avoid prematurely registering obligations #33852

Merged
merged 2 commits into from
May 28, 2016

Conversation

arielb1
Copy link
Contributor

@arielb1 arielb1 commented May 24, 2016

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 #24819
Fixes #25801
Fixes #27631
Fixes #31258
Fixes #31964
Fixes #32320
Fixes #33515
Fixes #33755

r? @eddyb

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
@arielb1 arielb1 changed the title refactor autoderef to avoid registering obligations refactor autoderef to avoid prematurely registering obligations May 24, 2016
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();
Copy link
Member

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!

@eddyb
Copy link
Member

eddyb commented May 24, 2016

#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.

@arielb1
Copy link
Contributor Author

arielb1 commented May 25, 2016

updated

@eddyb
Copy link
Member

eddyb commented May 25, 2016

@bors r+

@bors
Copy link
Contributor

bors commented May 25, 2016

📌 Commit 040fc94 has been approved by eddyb

@nikomatsakis
Copy link
Contributor

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
Copy link
Contributor

@nikomatsakis nikomatsakis May 26, 2016

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.

@nikomatsakis
Copy link
Contributor

(The nits I noted aren't worth stopping bors, btw.)

@nikomatsakis
Copy link
Contributor

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 Deref to is an unresolved type variable, and we would have to process some obligations to figure out what it is, but because those obligations are not in the fufilllment context, we fail to make progress.

Manishearth added a commit to Manishearth/rust that referenced this pull request May 28, 2016
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
bors added a commit that referenced this pull request May 28, 2016
Rollup of 15 pull requests

- Successful merges: #33820, #33821, #33822, #33824, #33825, #33831, #33832, #33848, #33849, #33852, #33854, #33856, #33859, #33860, #33861
- Failed merges:
@bors bors merged commit 040fc94 into rust-lang:master May 28, 2016
@arielb1 arielb1 added the beta-nominated Nominated for backporting to the compiler in the beta channel. label May 28, 2016
@arielb1
Copy link
Contributor Author

arielb1 commented May 28, 2016

Beta-nominating for being a very annoying ICE.

@nikomatsakis nikomatsakis removed the beta-nominated Nominated for backporting to the compiler in the beta channel. label Jun 2, 2016
@nikomatsakis
Copy link
Contributor

In @rust-lang/compiler meeting, decided not to backport:

  • non-trivial refactoring
  • long-standing problem, not a regression afaik
  • most if not all of the cases where this occur would have been errors anyway

frewsxcv added a commit to frewsxcv/rust that referenced this pull request Apr 18, 2017
…=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
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Apr 18, 2017
…=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
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Apr 18, 2017
…=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
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Apr 18, 2017
…=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
bors added a commit that referenced this pull request Apr 19, 2017
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants