From 32294fc0ed1810a16fcea649955a9b21ea061734 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 4 Nov 2023 20:18:44 +0000 Subject: [PATCH] Make sure that predicates with unmentioned bound vars are still considered global in the old solver --- compiler/rustc_middle/src/ty/erase_regions.rs | 4 +-- compiler/rustc_middle/src/ty/flags.rs | 26 +++------------ compiler/rustc_middle/src/ty/visit.rs | 14 +++----- compiler/rustc_type_ir/src/flags.rs | 3 ++ .../predicate-is-global.rs | 32 +++++++++++++++++++ 5 files changed, 47 insertions(+), 32 deletions(-) create mode 100644 tests/ui/late-bound-lifetimes/predicate-is-global.rs diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 7895993ccffad..3371ea3bec8c5 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -20,8 +20,8 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - // 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); diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index a348e9f608aab..ec36bdc5a518b 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -34,26 +34,6 @@ impl FlagComputation { result.flags } - pub fn bound_var_flags(vars: &ty::List) -> 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 @@ impl FlagComputation { 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()); diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index ab0999b3f197f..8fc5c03027784 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -494,15 +494,11 @@ impl<'tcx> TypeVisitor> for HasTypeFlagsVisitor { &mut self, t: &Binder<'tcx, T>, ) -> ControlFlow { - // 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) diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index d5cadd4e83a7c..8472a08450537 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -115,5 +115,8 @@ bitflags! { /// 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; } } diff --git a/tests/ui/late-bound-lifetimes/predicate-is-global.rs b/tests/ui/late-bound-lifetimes/predicate-is-global.rs new file mode 100644 index 0000000000000..ee4c4706005f5 --- /dev/null +++ b/tests/ui/late-bound-lifetimes/predicate-is-global.rs @@ -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() {}