]> git.lizzy.rs Git - rust.git/commitdiff
remove compare-fn and use erased-ty
authorNiko Matsakis <niko@alum.mit.edu>
Wed, 15 Jun 2022 10:35:51 +0000 (06:35 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 15 Jun 2022 15:47:04 +0000 (11:47 -0400)
compiler/rustc_infer/src/infer/outlives/verify.rs

index bc6fb5ebf7c29b6ba8a518def99028682ab5cfad..e17ec3034a5613c389d9068e342f66a486711c28 100644 (file)
@@ -123,14 +123,7 @@ pub fn projection_approx_declared_bounds_from_env(
     ) -> Vec<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> {
         let projection_ty = GenericKind::Projection(projection_ty).to_ty(self.tcx);
         let erased_projection_ty = self.tcx.erase_regions(projection_ty);
-        self.declared_generic_bounds_from_env_with_compare_fn(|ty| {
-            if let ty::Projection(..) = ty.kind() {
-                let erased_ty = self.tcx.erase_regions(ty);
-                erased_ty == erased_projection_ty
-            } else {
-                false
-            }
-        })
+        self.declared_generic_bounds_from_env_for_erased_ty(erased_projection_ty)
     }
 
     /// Searches the where-clauses in scope for regions that
@@ -219,12 +212,23 @@ fn declared_generic_bounds_from_env(
         param_ty: ty::ParamTy,
     ) -> Vec<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> {
         let generic_ty = param_ty.to_ty(self.tcx);
-        self.declared_generic_bounds_from_env_with_compare_fn(|ty| ty == generic_ty)
+        self.declared_generic_bounds_from_env_for_erased_ty(generic_ty)
     }
 
-    fn declared_generic_bounds_from_env_with_compare_fn(
+    /// Searches the environment to find all bounds that apply to `erased_ty`.
+    /// Obviously these must be approximate -- they are in fact both *over* and
+    /// and *under* approximated:
+    ///
+    /// * Over-approximated because we erase regions, so
+    /// * Under-approximated because we look for syntactic equality and so for complex types
+    ///   like `<T as Foo<fn(&u32, &u32)>>::Item` or whatever we may fail to figure out
+    ///   all the subtleties.
+    ///
+    /// In some cases, such as when `erased_ty` represents a `ty::Param`, however,
+    /// the result is precise.
+    fn declared_generic_bounds_from_env_for_erased_ty(
         &self,
-        compare_ty: impl Fn(Ty<'tcx>) -> bool,
+        erased_ty: Ty<'tcx>,
     ) -> Vec<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> {
         let tcx = self.tcx;
 
@@ -235,7 +239,7 @@ fn declared_generic_bounds_from_env_with_compare_fn(
         // like `T` and `T::Item`. It may not work as well for things
         // like `<T as Foo<'a>>::Item`.
         let c_b = self.param_env.caller_bounds();
-        let param_bounds = self.collect_outlives_from_predicate_list(&compare_ty, c_b.into_iter());
+        let param_bounds = self.collect_outlives_from_predicate_list(erased_ty, c_b.into_iter());
 
         // Next, collect regions we scraped from the well-formedness
         // constraints in the fn signature. To do that, we walk the list
@@ -250,18 +254,19 @@ fn declared_generic_bounds_from_env_with_compare_fn(
         // don't know that this holds from first principles.
         let from_region_bound_pairs = self.region_bound_pairs.iter().filter_map(|&(r, p)| {
             debug!(
-                "declared_generic_bounds_from_env_with_compare_fn: region_bound_pair = {:?}",
+                "declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}",
                 (r, p)
             );
             let p_ty = p.to_ty(tcx);
-            compare_ty(p_ty).then_some(ty::OutlivesPredicate(p_ty, r))
+            let erased_p_ty = self.tcx.erase_regions(p_ty);
+            (erased_p_ty == erased_ty).then_some(ty::OutlivesPredicate(p.to_ty(tcx), r))
         });
 
         param_bounds
             .chain(from_region_bound_pairs)
             .inspect(|bound| {
                 debug!(
-                    "declared_generic_bounds_from_env_with_compare_fn: result predicate = {:?}",
+                    "declared_generic_bounds_from_env_for_erased_ty: result predicate = {:?}",
                     bound
                 )
             })
@@ -341,12 +346,13 @@ fn region_bounds_declared_on_associated_item(
     /// otherwise want a precise match.
     fn collect_outlives_from_predicate_list(
         &self,
-        compare_ty: impl Fn(Ty<'tcx>) -> bool,
+        erased_ty: Ty<'tcx>,
         predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
     ) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> {
+        let tcx = self.tcx;
         predicates
             .filter_map(|p| p.to_opt_type_outlives())
             .filter_map(|p| p.no_bound_vars())
-            .filter(move |p| compare_ty(p.0))
+            .filter(move |p| tcx.erase_regions(p.0) == erased_ty)
     }
 }