Skip to content

Commit

Permalink
remove snapshot calls from "match" operations during select
Browse files Browse the repository at this point in the history
Motivation:

- we want to use leak-check sparingly, first off
- these calls were essentially the same as doing the check during subtyping
  • Loading branch information
nikomatsakis committed Jun 22, 2020
1 parent 1e00e1b commit 70cf33f
Show file tree
Hide file tree
Showing 16 changed files with 138 additions and 188 deletions.
10 changes: 5 additions & 5 deletions src/librustc_trait_selection/traits/select/candidate_assembly.rs
Expand Up @@ -163,9 +163,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
_ => return,
}

let result = self.infcx.probe(|snapshot| {
self.match_projection_obligation_against_definition_bounds(obligation, snapshot)
});
let result = self
.infcx
.probe(|_| self.match_projection_obligation_against_definition_bounds(obligation));

if result {
candidates.vec.push(ProjectionCandidate);
Expand Down Expand Up @@ -345,8 +345,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation.predicate.def_id(),
obligation.predicate.skip_binder().trait_ref.self_ty(),
|impl_def_id| {
self.infcx.probe(|snapshot| {
if let Ok(_substs) = self.match_impl(impl_def_id, obligation, snapshot) {
self.infcx.probe(|_| {
if let Ok(_substs) = self.match_impl(impl_def_id, obligation) {
candidates.vec.push(ImplCandidate(impl_def_id));
}
});
Expand Down
9 changes: 4 additions & 5 deletions src/librustc_trait_selection/traits/select/confirmation.rs
Expand Up @@ -121,9 +121,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}

fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) {
self.infcx.commit_unconditionally(|snapshot| {
let result =
self.match_projection_obligation_against_definition_bounds(obligation, snapshot);
self.infcx.commit_unconditionally(|_| {
let result = self.match_projection_obligation_against_definition_bounds(obligation);
assert!(result);
})
}
Expand Down Expand Up @@ -265,8 +264,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

// First, create the substitutions by matching the impl again,
// this time not in a probe.
self.infcx.commit_unconditionally(|snapshot| {
let substs = self.rematch_impl(impl_def_id, obligation, snapshot);
self.infcx.commit_unconditionally(|_| {
let substs = self.rematch_impl(impl_def_id, obligation);
debug!("confirm_impl_candidate: substs={:?}", substs);
let cause = obligation.derived_cause(ImplDerivedObligation);
ensure_sufficient_stack(|| {
Expand Down
29 changes: 5 additions & 24 deletions src/librustc_trait_selection/traits/select/mod.rs
Expand Up @@ -21,7 +21,7 @@ use super::{Normalized, ProjectionCacheKey};
use super::{ObligationCause, PredicateObligation, TraitObligation};
use super::{Overflow, SelectionError, Unimplemented};

use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, TypeFreshener};
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
use crate::traits::error_reporting::InferCtxtExt;
use crate::traits::project::ProjectionCacheKeyExt;
use rustc_ast::attr;
Expand Down Expand Up @@ -1268,7 +1268,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn match_projection_obligation_against_definition_bounds(
&mut self,
obligation: &TraitObligation<'tcx>,
snapshot: &CombinedSnapshot<'_, 'tcx>,
) -> bool {
let poly_trait_predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate);
let (placeholder_trait_predicate, _) =
Expand Down Expand Up @@ -1299,12 +1298,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if let ty::PredicateKind::Trait(bound, _) = bound.kind() {
let bound = bound.to_poly_trait_ref();
if self.infcx.probe(|_| {
self.match_projection(
obligation,
bound,
placeholder_trait_predicate.trait_ref,
snapshot,
)
self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref)
}) {
return Some(bound);
}
Expand All @@ -1321,12 +1315,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
None => false,
Some(bound) => {
// Repeat the successful match, if any, this time outside of a probe.
let result = self.match_projection(
obligation,
bound,
placeholder_trait_predicate.trait_ref,
snapshot,
);
let result =
self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref);

assert!(result);
true
Expand All @@ -1339,14 +1329,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &TraitObligation<'tcx>,
trait_bound: ty::PolyTraitRef<'tcx>,
placeholder_trait_ref: ty::TraitRef<'tcx>,
snapshot: &CombinedSnapshot<'_, 'tcx>,
) -> bool {
debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars());
self.infcx
.at(&obligation.cause, obligation.param_env)
.sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
.is_ok()
&& self.infcx.leak_check(false, snapshot).is_ok()
}

fn evaluate_where_clause<'o>(
Expand Down Expand Up @@ -1811,9 +1799,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&mut self,
impl_def_id: DefId,
obligation: &TraitObligation<'tcx>,
snapshot: &CombinedSnapshot<'_, 'tcx>,
) -> Normalized<'tcx, SubstsRef<'tcx>> {
match self.match_impl(impl_def_id, obligation, snapshot) {
match self.match_impl(impl_def_id, obligation) {
Ok(substs) => substs,
Err(()) => {
bug!(
Expand All @@ -1829,7 +1816,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&mut self,
impl_def_id: DefId,
obligation: &TraitObligation<'tcx>,
snapshot: &CombinedSnapshot<'_, 'tcx>,
) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();

Expand Down Expand Up @@ -1872,11 +1858,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?;
nested_obligations.extend(obligations);

if let Err(e) = self.infcx.leak_check(false, snapshot) {
debug!("match_impl: failed leak check due to `{}`", e);
return Err(());
}

if !self.intercrate
&& self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
{
Expand Down
35 changes: 19 additions & 16 deletions src/test/ui/associated-types/associated-types-eq-hr.rs
Expand Up @@ -7,7 +7,7 @@ pub trait TheTrait<T> {
}

struct IntStruct {
x: isize
x: isize,
}

impl<'a> TheTrait<&'a isize> for IntStruct {
Expand All @@ -19,7 +19,7 @@ impl<'a> TheTrait<&'a isize> for IntStruct {
}

struct UintStruct {
x: isize
x: isize,
}

impl<'a> TheTrait<&'a isize> for UintStruct {
Expand All @@ -30,8 +30,7 @@ impl<'a> TheTrait<&'a isize> for UintStruct {
}
}

struct Tuple {
}
struct Tuple {}

impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple {
type A = &'a isize;
Expand All @@ -42,37 +41,43 @@ impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple {
}

fn foo<T>()
where T : for<'x> TheTrait<&'x isize, A = &'x isize>
where
T: for<'x> TheTrait<&'x isize, A = &'x isize>,
{
// ok for IntStruct, but not UintStruct
}

fn bar<T>()
where T : for<'x> TheTrait<&'x isize, A = &'x usize>
where
T: for<'x> TheTrait<&'x isize, A = &'x usize>,
{
// ok for UintStruct, but not IntStruct
}

fn tuple_one<T>()
where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>
where
T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>,
{
// not ok for tuple, two lifetimes and we pick first
}

fn tuple_two<T>()
where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>
where
T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>,
{
// not ok for tuple, two lifetimes and we pick second
}

fn tuple_three<T>()
where T : for<'x> TheTrait<(&'x isize, &'x isize), A = &'x isize>
where
T: for<'x> TheTrait<(&'x isize, &'x isize), A = &'x isize>,
{
// ok for tuple
}

fn tuple_four<T>()
where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)>
where
T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>,
{
// not ok for tuple, two lifetimes, and lifetime matching is invariant
}
Expand All @@ -89,14 +94,12 @@ pub fn call_bar() {

pub fn call_tuple_one() {
tuple_one::<Tuple>();
//~^ ERROR not satisfied
//~| ERROR type mismatch
//~^ ERROR type mismatch
}

pub fn call_tuple_two() {
tuple_two::<Tuple>();
//~^ ERROR not satisfied
//~| ERROR type mismatch
//~^ ERROR type mismatch
}

pub fn call_tuple_three() {
Expand All @@ -105,7 +108,7 @@ pub fn call_tuple_three() {

pub fn call_tuple_four() {
tuple_four::<Tuple>();
//~^ ERROR not satisfied
//~^ ERROR implementation of `TheTrait` is not general enough
}

fn main() { }
fn main() {}
87 changes: 32 additions & 55 deletions src/test/ui/associated-types/associated-types-eq-hr.stderr
@@ -1,10 +1,11 @@
error[E0271]: type mismatch resolving `for<'x> <UintStruct as TheTrait<&'x isize>>::A == &'x isize`
--> $DIR/associated-types-eq-hr.rs:82:5
--> $DIR/associated-types-eq-hr.rs:87:5
|
LL | fn foo<T>()
| --- required by a bound in this
LL | where T : for<'x> TheTrait<&'x isize, A = &'x isize>
| ------------- required by this bound in `foo`
LL | where
LL | T: for<'x> TheTrait<&'x isize, A = &'x isize>,
| ------------- required by this bound in `foo`
...
LL | foo::<UintStruct>();
| ^^^^^^^^^^^^^^^^^ expected `isize`, found `usize`
Expand All @@ -13,84 +14,60 @@ LL | foo::<UintStruct>();
found reference `&usize`

error[E0271]: type mismatch resolving `for<'x> <IntStruct as TheTrait<&'x isize>>::A == &'x usize`
--> $DIR/associated-types-eq-hr.rs:86:5
--> $DIR/associated-types-eq-hr.rs:91:5
|
LL | fn bar<T>()
| --- required by a bound in this
LL | where T : for<'x> TheTrait<&'x isize, A = &'x usize>
| ------------- required by this bound in `bar`
LL | where
LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>,
| ------------- required by this bound in `bar`
...
LL | bar::<IntStruct>();
| ^^^^^^^^^^^^^^^^ expected `usize`, found `isize`
|
= note: expected reference `&usize`
found reference `&isize`

error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
--> $DIR/associated-types-eq-hr.rs:91:17
|
LL | fn tuple_one<T>()
| --------- required by a bound in this
LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>
| ---------------------------------------------------------- required by this bound in `tuple_one`
...
LL | tuple_one::<Tuple>();
| ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
|
= help: the following implementations were found:
<Tuple as TheTrait<(&'a isize, &'a isize)>>

error[E0271]: type mismatch resolving `for<'x, 'y> <Tuple as TheTrait<(&'x isize, &'y isize)>>::A == &'x isize`
--> $DIR/associated-types-eq-hr.rs:91:5
--> $DIR/associated-types-eq-hr.rs:96:5
|
LL | fn tuple_one<T>()
| --------- required by a bound in this
LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>
| ------------- required by this bound in `tuple_one`
LL | where
LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>,
| ------------- required by this bound in `tuple_one`
...
LL | tuple_one::<Tuple>();
| ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'y, found concrete lifetime

error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
--> $DIR/associated-types-eq-hr.rs:97:17
|
LL | fn tuple_two<T>()
| --------- required by a bound in this
LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>
| ---------------------------------------------------------- required by this bound in `tuple_two`
...
LL | tuple_two::<Tuple>();
| ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
|
= help: the following implementations were found:
<Tuple as TheTrait<(&'a isize, &'a isize)>>
| ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime

error[E0271]: type mismatch resolving `for<'x, 'y> <Tuple as TheTrait<(&'x isize, &'y isize)>>::A == &'y isize`
--> $DIR/associated-types-eq-hr.rs:97:5
--> $DIR/associated-types-eq-hr.rs:101:5
|
LL | fn tuple_two<T>()
| --------- required by a bound in this
LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>
| ------------- required by this bound in `tuple_two`
LL | where
LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>,
| ------------- required by this bound in `tuple_two`
...
LL | tuple_two::<Tuple>();
| ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime
| ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'y, found concrete lifetime

error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
--> $DIR/associated-types-eq-hr.rs:107:18
error: implementation of `TheTrait` is not general enough
--> $DIR/associated-types-eq-hr.rs:110:5
|
LL | fn tuple_four<T>()
| ---------- required by a bound in this
LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)>
| ------------------------------------------- required by this bound in `tuple_four`
LL | / pub trait TheTrait<T> {
LL | | type A;
LL | |
LL | | fn get(&self, t: T) -> Self::A;
LL | | }
| |_- trait `TheTrait` defined here
...
LL | tuple_four::<Tuple>();
| ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
LL | tuple_four::<Tuple>();
| ^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough
|
= help: the following implementations were found:
<Tuple as TheTrait<(&'a isize, &'a isize)>>
= note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`...
= note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`

error: aborting due to 7 previous errors
error: aborting due to 5 previous errors

Some errors have detailed explanations: E0271, E0277.
For more information about an error, try `rustc --explain E0271`.
For more information about this error, try `rustc --explain E0271`.
21 changes: 10 additions & 11 deletions src/test/ui/hrtb/hrtb-conflate-regions.stderr
@@ -1,17 +1,16 @@
error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied
--> $DIR/hrtb-conflate-regions.rs:27:22
error: implementation of `Foo` is not general enough
--> $DIR/hrtb-conflate-regions.rs:27:10
|
LL | fn want_foo2<T>()
| --------- required by a bound in this
LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)>
| -------------------------------------- required by this bound in `want_foo2`
LL | / trait Foo<X> {
LL | | fn foo(&self, x: X) { }
LL | | }
| |_- trait `Foo` defined here
...
LL | fn b() { want_foo2::<SomeStruct>(); }
| ^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct`
LL | fn b() { want_foo2::<SomeStruct>(); }
| ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
= help: the following implementations were found:
<SomeStruct as Foo<(&'a isize, &'a isize)>>
= note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`...
= note: ...but `SomeStruct` actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.

0 comments on commit 70cf33f

Please sign in to comment.