Make sure that predicates with unmentioned bound vars are still considered global in the old solver
This commit is contained in:
parent
adda05fe3e
commit
32294fc0ed
@ -20,8 +20,8 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
where
|
where
|
||||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||||
{
|
{
|
||||||
// If there's nothing to erase avoid performing the query at all
|
// If there's nothing to erase or anonymize, avoid performing the query at all
|
||||||
if !value.has_type_flags(TypeFlags::HAS_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
|
if !value.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
debug!("erase_regions({:?})", value);
|
debug!("erase_regions({:?})", value);
|
||||||
|
@ -34,26 +34,6 @@ impl FlagComputation {
|
|||||||
result.flags
|
result.flags
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bound_var_flags(vars: &ty::List<ty::BoundVariableKind>) -> FlagComputation {
|
|
||||||
let mut computation = FlagComputation::new();
|
|
||||||
|
|
||||||
for bv in vars {
|
|
||||||
match bv {
|
|
||||||
ty::BoundVariableKind::Ty(_) => {
|
|
||||||
computation.flags |= TypeFlags::HAS_TY_LATE_BOUND;
|
|
||||||
}
|
|
||||||
ty::BoundVariableKind::Region(_) => {
|
|
||||||
computation.flags |= TypeFlags::HAS_RE_LATE_BOUND;
|
|
||||||
}
|
|
||||||
ty::BoundVariableKind::Const => {
|
|
||||||
computation.flags |= TypeFlags::HAS_CT_LATE_BOUND;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
computation
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_flags(&mut self, flags: TypeFlags) {
|
fn add_flags(&mut self, flags: TypeFlags) {
|
||||||
self.flags = self.flags | flags;
|
self.flags = self.flags | flags;
|
||||||
}
|
}
|
||||||
@ -77,7 +57,11 @@ impl FlagComputation {
|
|||||||
where
|
where
|
||||||
F: FnOnce(&mut Self, T),
|
F: FnOnce(&mut Self, T),
|
||||||
{
|
{
|
||||||
let mut computation = FlagComputation::bound_var_flags(value.bound_vars());
|
let mut computation = FlagComputation::new();
|
||||||
|
|
||||||
|
if !value.bound_vars().is_empty() {
|
||||||
|
computation.add_flags(TypeFlags::HAS_BINDER_VARS);
|
||||||
|
}
|
||||||
|
|
||||||
f(&mut computation, value.skip_binder());
|
f(&mut computation, value.skip_binder());
|
||||||
|
|
||||||
|
@ -494,15 +494,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor {
|
|||||||
&mut self,
|
&mut self,
|
||||||
t: &Binder<'tcx, T>,
|
t: &Binder<'tcx, T>,
|
||||||
) -> ControlFlow<Self::BreakTy> {
|
) -> ControlFlow<Self::BreakTy> {
|
||||||
// If we're looking for any of the HAS_*_LATE_BOUND flags, we need to
|
// If we're looking for the HAS_BINDER_VARS flag, check if the
|
||||||
// additionally consider the bound vars on the binder itself, even if
|
// binder has vars. This won't be present in the binder's bound
|
||||||
// the contents of a the binder (e.g. a `TraitRef`) doesn't reference
|
// value, so we need to check here too.
|
||||||
// the bound vars.
|
if self.flags.intersects(TypeFlags::HAS_BINDER_VARS) && !t.bound_vars().is_empty() {
|
||||||
if self.flags.intersects(TypeFlags::HAS_LATE_BOUND) {
|
return ControlFlow::Break(FoundFlags);
|
||||||
let bound_var_flags = FlagComputation::bound_var_flags(t.bound_vars());
|
|
||||||
if bound_var_flags.flags.intersects(self.flags) {
|
|
||||||
return ControlFlow::Break(FoundFlags);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
t.super_visit_with(self)
|
t.super_visit_with(self)
|
||||||
|
@ -115,5 +115,8 @@ bitflags! {
|
|||||||
|
|
||||||
/// Does this have `Coroutine` or `CoroutineWitness`?
|
/// Does this have `Coroutine` or `CoroutineWitness`?
|
||||||
const HAS_TY_COROUTINE = 1 << 23;
|
const HAS_TY_COROUTINE = 1 << 23;
|
||||||
|
|
||||||
|
/// Does this have any binders with bound vars (e.g. that need to be anonymized)?
|
||||||
|
const HAS_BINDER_VARS = 1 << 24;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
32
tests/ui/late-bound-lifetimes/predicate-is-global.rs
Normal file
32
tests/ui/late-bound-lifetimes/predicate-is-global.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// check-pass
|
||||||
|
|
||||||
|
trait Foo {
|
||||||
|
type Assoc;
|
||||||
|
|
||||||
|
fn do_it(_: &Self::Assoc)
|
||||||
|
where
|
||||||
|
for<'a> Self: Baz<'a>;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Baz<'a>: Foo {}
|
||||||
|
|
||||||
|
impl Foo for () {
|
||||||
|
type Assoc = Inherent;
|
||||||
|
|
||||||
|
// Ensure that the `for<'a> Self: Baz<'a>` predicate, which has
|
||||||
|
// a supertrait `for<'a> Self: Foo`, does not cause us to fail
|
||||||
|
// to normalize `Self::Assoc`.
|
||||||
|
fn do_it(x: &Self::Assoc)
|
||||||
|
where
|
||||||
|
for<'a> Self: Baz<'a>,
|
||||||
|
{
|
||||||
|
x.inherent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Inherent;
|
||||||
|
impl Inherent {
|
||||||
|
fn inherent(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
x
Reference in New Issue
Block a user