8000 move leak-check to during coherence, candidate eval by nikomatsakis · Pull Request #72493 · rust-lang/rust · GitHub
[go: up one dir, main page]

Skip to content

move leak-check to during coherence, candidate eval #72493

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

Merged
merged 13 commits into from
Jun 23, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
remove snapshot calls from "match" operations during select
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
commit 70cf33fccaac072a153f6e211aa907c83c465fef
10 changes: 5 additions & 5 deletions src/librustc_trait_selection/traits/select/candidate_assembly.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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`.
Loading
0