opportunistically resolve regions
This commit is contained in:
parent
5683791ebb
commit
01377e8064
@ -82,15 +82,40 @@ impl CanonicalVarValues<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_identity_modulo_regions(&self) -> bool {
|
pub fn is_identity_modulo_regions(&self) -> bool {
|
||||||
self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() {
|
let mut var = ty::BoundVar::from_u32(0);
|
||||||
ty::GenericArgKind::Lifetime(_) => true,
|
for arg in self.var_values {
|
||||||
|
match arg.unpack() {
|
||||||
|
ty::GenericArgKind::Lifetime(r) => {
|
||||||
|
if let ty::ReLateBound(ty::INNERMOST, br) = *r
|
||||||
|
&& var == br.var
|
||||||
|
{
|
||||||
|
var = var + 1;
|
||||||
|
} else {
|
||||||
|
// It's ok if this region var isn't unique
|
||||||
|
}
|
||||||
|
},
|
||||||
ty::GenericArgKind::Type(ty) => {
|
ty::GenericArgKind::Type(ty) => {
|
||||||
matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv)
|
if let ty::Bound(ty::INNERMOST, bt) = *ty.kind()
|
||||||
|
&& var == bt.var
|
||||||
|
{
|
||||||
|
var = var + 1;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ty::GenericArgKind::Const(ct) => {
|
ty::GenericArgKind::Const(ct) => {
|
||||||
matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv)
|
if let ty::ConstKind::Bound(ty::INNERMOST, bc) = ct.kind()
|
||||||
|
&& var == bc
|
||||||
|
{
|
||||||
|
var = var + 1;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,8 +208,25 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
|
|||||||
t
|
t
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
fn fold_region(&mut self, mut r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
||||||
let r = self.infcx.shallow_resolve(r);
|
match self.canonicalize_mode {
|
||||||
|
CanonicalizeMode::Input => {
|
||||||
|
// Don't resolve infer vars in input, since it affects
|
||||||
|
// caching and may cause trait selection bugs which rely
|
||||||
|
// on regions to be equal.
|
||||||
|
}
|
||||||
|
CanonicalizeMode::Response { .. } => {
|
||||||
|
if let ty::ReVar(vid) = *r {
|
||||||
|
r = self
|
||||||
|
.infcx
|
||||||
|
.inner
|
||||||
|
.borrow_mut()
|
||||||
|
.unwrap_region_constraints()
|
||||||
|
.opportunistic_resolve_var(self.infcx.tcx, vid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let kind = match *r {
|
let kind = match *r {
|
||||||
ty::ReLateBound(..) => return r,
|
ty::ReLateBound(..) => return r,
|
||||||
|
|
||||||
|
@ -263,7 +263,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
|||||||
let (_orig_values, canonical_goal) = self.canonicalize_goal(goal);
|
let (_orig_values, canonical_goal) = self.canonicalize_goal(goal);
|
||||||
let new_canonical_response =
|
let new_canonical_response =
|
||||||
EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
|
EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
|
||||||
if !new_canonical_response.value.var_values.is_identity() {
|
// We only check for modulo regions as we convert all regions in
|
||||||
|
// the input to new existentials, even if they're expected to be
|
||||||
|
// `'static` or a placeholder region.
|
||||||
|
if !new_canonical_response.value.var_values.is_identity_modulo_regions() {
|
||||||
bug!(
|
bug!(
|
||||||
"unstable result: re-canonicalized goal={canonical_goal:#?} \
|
"unstable result: re-canonicalized goal={canonical_goal:#?} \
|
||||||
first_response={canonical_response:#?} \
|
first_response={canonical_response:#?} \
|
||||||
|
19
tests/ui/traits/new-solver/opportunistic-region-resolve.rs
Normal file
19
tests/ui/traits/new-solver/opportunistic-region-resolve.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// compile-flags: -Ztrait-solver=next
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
|
#[rustc_coinductive]
|
||||||
|
trait Trait {}
|
||||||
|
|
||||||
|
#[rustc_coinductive]
|
||||||
|
trait Indirect {}
|
||||||
|
impl<T: Trait + ?Sized> Indirect for T {}
|
||||||
|
|
||||||
|
impl<'a> Trait for &'a () where &'a (): Indirect {}
|
||||||
|
|
||||||
|
fn impls_trait<T: Trait>() {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
impls_trait::<&'static ()>();
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user