diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 247fbc259652e..7a21c2883d1ac 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -192,7 +192,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// Obviously these must be approximate -- they are in fact both *over* and /// and *under* approximated: /// - /// * Over-approximated because we erase regions, so + /// * Over-approximated because we don't consider equality of regions. /// * 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. @@ -205,13 +205,14 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { erased_ty: Ty<'tcx>, ) -> Vec> { let tcx = self.tcx; + let mut bounds = vec![]; // To start, collect bounds from user environment. Note that // parameter environments are already elaborated, so we don't // have to worry about that. - let param_bounds = self.caller_bounds.iter().copied().filter(move |outlives_predicate| { + bounds.extend(self.caller_bounds.iter().copied().filter(move |outlives_predicate| { super::test_type_match::can_match_erased_ty(tcx, *outlives_predicate, erased_ty) - }); + })); // Next, collect regions we scraped from the well-formedness // constraints in the fn signature. To do that, we walk the list @@ -224,37 +225,27 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // The problem is that the type of `x` is `&'a A`. To be // well-formed, then, A must outlive `'a`, but we don't know that // this holds from first principles. - let from_region_bound_pairs = - self.region_bound_pairs.iter().filter_map(|&OutlivesPredicate(p, r)| { - debug!( - "declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}", - (r, p) - ); - // Fast path for the common case. - match (&p, erased_ty.kind()) { - // In outlive routines, all types are expected to be fully normalized. - // And therefore we can safely use structural equality for alias types. - (GenericKind::Param(p1), ty::Param(p2)) if p1 == p2 => {} - (GenericKind::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => {} - (GenericKind::Alias(a1), ty::Alias(_, a2)) if a1.def_id == a2.def_id => {} - _ => return None, - } + bounds.extend(self.region_bound_pairs.iter().filter_map(|&OutlivesPredicate(p, r)| { + debug!( + "declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}", + (r, p) + ); + // Fast path for the common case. + match (&p, erased_ty.kind()) { + // In outlive routines, all types are expected to be fully normalized. + // And therefore we can safely use structural equality for alias types. + (GenericKind::Param(p1), ty::Param(p2)) if p1 == p2 => {} + (GenericKind::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => {} + (GenericKind::Alias(a1), ty::Alias(_, a2)) if a1.def_id == a2.def_id => {} + _ => return None, + } - let p_ty = p.to_ty(tcx); - let erased_p_ty = self.tcx.erase_regions(p_ty); - (erased_p_ty == erased_ty) - .then_some(ty::Binder::dummy(ty::OutlivesPredicate(p_ty, r))) - }); + let p_ty = p.to_ty(tcx); + let erased_p_ty = self.tcx.erase_regions(p_ty); + (erased_p_ty == erased_ty).then_some(ty::Binder::dummy(ty::OutlivesPredicate(p_ty, r))) + })); - param_bounds - .chain(from_region_bound_pairs) - .inspect(|bound| { - debug!( - "declared_generic_bounds_from_env_for_erased_ty: result predicate = {:?}", - bound - ) - }) - .collect() + bounds } /// Given a projection like `>::Bar`, returns any bounds