From 87c2907bca4fbb4fabb909c6da5988a97866938d Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 15 Jun 2022 06:35:51 -0400 Subject: [PATCH] remove compare-fn and use erased-ty --- .../rustc_infer/src/infer/outlives/verify.rs | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index bc6fb5ebf7c..e17ec3034a5 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -123,14 +123,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { ) -> Vec, 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 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { param_ty: ty::ParamTy, ) -> Vec, 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 `>::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::Region<'tcx>>> { let tcx = self.tcx; @@ -235,7 +239,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // like `T` and `T::Item`. It may not work as well for things // like `>::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 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // 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 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// 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>, ) -> impl Iterator, 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) } }