Make sure that predicates with unmentioned bound vars are still considered global in the old solver

This commit is contained in:
Michael Goulet 2023-11-04 20:18:44 +00:00
parent adda05fe3e
commit 32294fc0ed
5 changed files with 47 additions and 32 deletions

View File

@ -20,8 +20,8 @@ pub fn erase_regions<T>(self, value: T) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
// If there's nothing to erase avoid performing the query at all
if !value.has_type_flags(TypeFlags::HAS_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
// If there's nothing to erase or anonymize, avoid performing the query at all
if !value.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) {
return value;
}
debug!("erase_regions({:?})", value);

View File

@ -34,26 +34,6 @@ pub fn for_const(c: ty::Const<'_>) -> TypeFlags {
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) {
self.flags = self.flags | flags;
}
@ -77,7 +57,11 @@ fn bound_computation<T, F>(&mut self, value: ty::Binder<'_, T>, f: F)
where
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());

View File

@ -494,15 +494,11 @@ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
// If we're looking for any of the HAS_*_LATE_BOUND flags, we need to
// additionally consider the bound vars on the binder itself, even if
// the contents of a the binder (e.g. a `TraitRef`) doesn't reference
// the bound vars.
if self.flags.intersects(TypeFlags::HAS_LATE_BOUND) {
let bound_var_flags = FlagComputation::bound_var_flags(t.bound_vars());
if bound_var_flags.flags.intersects(self.flags) {
return ControlFlow::Break(FoundFlags);
}
// If we're looking for the HAS_BINDER_VARS flag, check if the
// binder has vars. This won't be present in the binder's bound
// value, so we need to check here too.
if self.flags.intersects(TypeFlags::HAS_BINDER_VARS) && !t.bound_vars().is_empty() {
return ControlFlow::Break(FoundFlags);
}
t.super_visit_with(self)

View File

@ -115,5 +115,8 @@ pub struct TypeFlags: u32 {
/// Does this have `Coroutine` or `CoroutineWitness`?
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;
}
}

View 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() {}