Rollup merge of #56043 - nikomatsakis:issue-55756-via-outlives, r=eddyb
remove "approx env bounds" if we already know from trait Alternative to https://github.com/rust-lang/rust/pull/55988 that fixes #55756 -- smaller fix that I cannot see having (correctness) repercussions beyond the test at hand, and hence better for backporting. (Famous last words, I know.) r? @eddyb
This commit is contained in:
commit
10565c45ac
2 changed files with 63 additions and 10 deletions
|
@ -389,16 +389,6 @@ where
|
||||||
// rule might not apply (but another rule might). For now, we err
|
// rule might not apply (but another rule might). For now, we err
|
||||||
// on the side of adding too few edges into the graph.
|
// on the side of adding too few edges into the graph.
|
||||||
|
|
||||||
// Compute the bounds we can derive from the environment. This
|
|
||||||
// is an "approximate" match -- in some cases, these bounds
|
|
||||||
// may not apply.
|
|
||||||
let approx_env_bounds = self.verify_bound
|
|
||||||
.projection_approx_declared_bounds_from_env(projection_ty);
|
|
||||||
debug!(
|
|
||||||
"projection_must_outlive: approx_env_bounds={:?}",
|
|
||||||
approx_env_bounds
|
|
||||||
);
|
|
||||||
|
|
||||||
// Compute the bounds we can derive from the trait definition.
|
// Compute the bounds we can derive from the trait definition.
|
||||||
// These are guaranteed to apply, no matter the inference
|
// These are guaranteed to apply, no matter the inference
|
||||||
// results.
|
// results.
|
||||||
|
@ -406,6 +396,32 @@ where
|
||||||
.projection_declared_bounds_from_trait(projection_ty)
|
.projection_declared_bounds_from_trait(projection_ty)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
// Compute the bounds we can derive from the environment. This
|
||||||
|
// is an "approximate" match -- in some cases, these bounds
|
||||||
|
// may not apply.
|
||||||
|
let mut approx_env_bounds = self.verify_bound
|
||||||
|
.projection_approx_declared_bounds_from_env(projection_ty);
|
||||||
|
debug!(
|
||||||
|
"projection_must_outlive: approx_env_bounds={:?}",
|
||||||
|
approx_env_bounds
|
||||||
|
);
|
||||||
|
|
||||||
|
// Remove outlives bounds that we get from the environment but
|
||||||
|
// which are also deducable from the trait. This arises (cc
|
||||||
|
// #55756) in cases where you have e.g. `<T as Foo<'a>>::Item:
|
||||||
|
// 'a` in the environment but `trait Foo<'b> { type Item: 'b
|
||||||
|
// }` in the trait definition.
|
||||||
|
approx_env_bounds.retain(|bound| {
|
||||||
|
match bound.0.sty {
|
||||||
|
ty::Projection(projection_ty) => {
|
||||||
|
self.verify_bound.projection_declared_bounds_from_trait(projection_ty)
|
||||||
|
.all(|r| r != bound.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => panic!("expected only projection types from env, not {:?}", bound.0),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// If declared bounds list is empty, the only applicable rule is
|
// If declared bounds list is empty, the only applicable rule is
|
||||||
// OutlivesProjectionComponent. If there are inference variables,
|
// OutlivesProjectionComponent. If there are inference variables,
|
||||||
// then, we can break down the outlives into more primitive
|
// then, we can break down the outlives into more primitive
|
||||||
|
|
37
src/test/ui/nll/ty-outlives/issue-55756.rs
Normal file
37
src/test/ui/nll/ty-outlives/issue-55756.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// Regression test for #55756.
|
||||||
|
//
|
||||||
|
// In this test, the result of `self.callee` is a projection `<D as
|
||||||
|
// Database<'?0>>::Guard`. As it may contain a destructor, the dropck
|
||||||
|
// rules require that this type outlivess the scope of `state`. Unfortunately,
|
||||||
|
// our region inference is not smart enough to figure out how to
|
||||||
|
// translate a requirement like
|
||||||
|
//
|
||||||
|
// <D as Database<'0>>::guard: 'r
|
||||||
|
//
|
||||||
|
// into a requirement that `'0: 'r` -- in particular, it fails to do
|
||||||
|
// so because it *also* knows that `<D as Database<'a>>::Guard: 'a`
|
||||||
|
// from the trait definition. Faced with so many choices, the current
|
||||||
|
// solver opts to do nothing.
|
||||||
|
//
|
||||||
|
// Fixed by tweaking the solver to recognize that the constraint from
|
||||||
|
// the environment duplicates one from the trait.
|
||||||
|
//
|
||||||
|
// compile-pass
|
||||||
|
|
||||||
|
#![crate_type="lib"]
|
||||||
|
|
||||||
|
pub trait Database<'a> {
|
||||||
|
type Guard: 'a;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Stateful<'a, D: 'a>(&'a D);
|
||||||
|
|
||||||
|
impl<'b, D: for <'a> Database<'a>> Stateful<'b, D> {
|
||||||
|
pub fn callee<'a>(&'a self) -> <D as Database<'a>>::Guard {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
pub fn caller<'a>(&'a self) -> <D as Database<'a>>::Guard {
|
||||||
|
let state = self.callee();
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue