about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-11-04 20:18:44 +0000
committerMichael Goulet <michael@errs.io>2023-11-04 20:36:21 +0000
commit32294fc0ed1810a16fcea649955a9b21ea061734 (patch)
treed17bbe4deebb01d6df2d8576af14d923ed1a8926
parentadda05fe3ebf4942aea1c0b8085ac2b46ce63fcf (diff)
downloadrust-32294fc0ed1810a16fcea649955a9b21ea061734.tar.gz
rust-32294fc0ed1810a16fcea649955a9b21ea061734.zip
Make sure that predicates with unmentioned bound vars are still considered global in the old solver
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs4
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs26
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs14
-rw-r--r--compiler/rustc_type_ir/src/flags.rs3
-rw-r--r--tests/ui/late-bound-lifetimes/predicate-is-global.rs32
5 files changed, 47 insertions, 32 deletions
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index 7895993ccff..3371ea3bec8 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<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);
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index a348e9f608a..ec36bdc5a51 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<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 @@ 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 ab0999b3f19..8fc5c030277 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -494,15 +494,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor {
         &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)
diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs
index d5cadd4e83a..8472a084505 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 00000000000..ee4c4706005
--- /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() {}