From df668b9fb960855ca1483ea520862c1eb8184d25 Mon Sep 17 00:00:00 2001
From: Ali MJ Al-Nasrawy <alimjalnasrawy@gmail.com>
Date: Mon, 3 Oct 2022 12:14:48 +0300
Subject: [PATCH 1/2] simplify applying closure requirements

Don't use `ConstraintCategory::ClosureBounds`!
Set the category and the span for the promoted constraints to that of
the original constraint earlier than before.
This eliminates the need for `closure_bounds_mapping`.
---
 .../rustc_borrowck/src/constraints/graph.rs   |   1 +
 .../rustc_borrowck/src/constraints/mod.rs     |   3 +
 compiler/rustc_borrowck/src/nll.rs            |   2 -
 .../src/region_infer/dump_mir.rs              |   3 +-
 .../rustc_borrowck/src/region_infer/mod.rs    | 146 ++----------------
 .../src/type_check/constraint_conversion.rs   |  75 +++++++--
 compiler/rustc_borrowck/src/type_check/mod.rs |  96 +++---------
 .../src/type_check/relate_tys.rs              |   1 +
 ...tion-two-region-trait-bound-closure.stderr |   7 +-
 9 files changed, 97 insertions(+), 237 deletions(-)

diff --git a/compiler/rustc_borrowck/src/constraints/graph.rs b/compiler/rustc_borrowck/src/constraints/graph.rs
index 609fbc2bc1515..385f153174c3c 100644
--- a/compiler/rustc_borrowck/src/constraints/graph.rs
+++ b/compiler/rustc_borrowck/src/constraints/graph.rs
@@ -163,6 +163,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> {
                 span: DUMMY_SP,
                 category: ConstraintCategory::Internal,
                 variance_info: VarianceDiagInfo::default(),
+                from_closure: false,
             })
         } else {
             None
diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs
index df04128135b89..9d9c4abb0aa57 100644
--- a/compiler/rustc_borrowck/src/constraints/mod.rs
+++ b/compiler/rustc_borrowck/src/constraints/mod.rs
@@ -96,6 +96,9 @@ pub struct OutlivesConstraint<'tcx> {
 
     /// Variance diagnostic information
     pub variance_info: VarianceDiagInfo<'tcx>,
+
+    /// If this constraint is promoted from closure requirements.
+    pub from_closure: bool,
 }
 
 impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> {
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 08fdd28eb01b7..4e0205f8d43a1 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -242,7 +242,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
         mut liveness_constraints,
         outlives_constraints,
         member_constraints,
-        closure_bounds_mapping,
         universe_causes,
         type_tests,
     } = constraints;
@@ -264,7 +263,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
         universal_region_relations,
         outlives_constraints,
         member_constraints,
-        closure_bounds_mapping,
         universe_causes,
         type_tests,
         liveness_constraints,
diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
index fe5193102f958..cc9450999525a 100644
--- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
+++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
@@ -74,8 +74,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
         constraints.sort_by_key(|c| (c.sup, c.sub));
         for constraint in &constraints {
-            let OutlivesConstraint { sup, sub, locations, category, span, variance_info: _ } =
-                constraint;
+            let OutlivesConstraint { sup, sub, locations, category, span, .. } = constraint;
             let (name, arg) = match locations {
                 Locations::All(span) => {
                     ("All", tcx.sess.source_map().span_to_embeddable_string(*span))
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 0e7f243bcf36c..6782fc0665f04 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -6,10 +6,9 @@ use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::graph::scc::Sccs;
 use rustc_errors::Diagnostic;
-use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
+use rustc_hir::def_id::CRATE_DEF_ID;
 use rustc_hir::CRATE_HIR_ID;
 use rustc_index::vec::IndexVec;
-use rustc_infer::infer::canonical::QueryOutlivesConstraint;
 use rustc_infer::infer::outlives::test_type_match;
 use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
 use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
@@ -19,9 +18,7 @@ use rustc_middle::mir::{
 };
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::traits::ObligationCauseCode;
-use rustc_middle::ty::{
-    self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable,
-};
+use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable};
 use rustc_span::Span;
 
 use crate::{
@@ -89,10 +86,6 @@ pub struct RegionInferenceContext<'tcx> {
     /// `member_region_scc`.
     member_constraints_applied: Vec<AppliedMemberConstraint>,
 
-    /// Map closure bounds to a `Span` that should be used for error reporting.
-    closure_bounds_mapping:
-        FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
-
     /// Map universe indexes to information on why we created it.
     universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
 
@@ -265,10 +258,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
         outlives_constraints: OutlivesConstraintSet<'tcx>,
         member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
-        closure_bounds_mapping: FxHashMap<
-            Location,
-            FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>,
-        >,
         universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
         type_tests: Vec<TypeTest<'tcx>>,
         liveness_constraints: LivenessValues<RegionVid>,
@@ -310,7 +299,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             rev_scc_graph: None,
             member_constraints,
             member_constraints_applied: Vec::new(),
-            closure_bounds_mapping,
             universe_causes,
             scc_universes,
             scc_representatives,
@@ -1804,18 +1792,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
     }
 
-    pub(crate) fn retrieve_closure_constraint_info(
-        &self,
-        constraint: OutlivesConstraint<'tcx>,
-    ) -> Option<(ConstraintCategory<'tcx>, Span)> {
-        match constraint.locations {
-            Locations::All(_) => None,
-            Locations::Single(loc) => {
-                self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub)).copied()
-            }
-        }
-    }
-
     /// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`.
     pub(crate) fn find_outlives_blame_span(
         &self,
@@ -1921,6 +1897,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     span: p_c.definition_span,
                     category: ConstraintCategory::OpaqueType,
                     variance_info: ty::VarianceDiagInfo::default(),
+                    from_closure: false,
                 };
                 handle_constraint(constraint);
             }
@@ -2066,31 +2043,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // Classify each of the constraints along the path.
         let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
             .iter()
-            .map(|constraint| {
-                let (category, span, from_closure, cause_code) =
-                    if constraint.category == ConstraintCategory::ClosureBounds {
-                        if let Some((category, span)) =
-                            self.retrieve_closure_constraint_info(*constraint)
-                        {
-                            (category, span, true, ObligationCauseCode::MiscObligation)
-                        } else {
-                            (
-                                constraint.category,
-                                constraint.span,
-                                false,
-                                ObligationCauseCode::MiscObligation,
-                            )
-                        }
-                    } else {
-                        (constraint.category, constraint.span, false, cause_code.clone())
-                    };
-                BlameConstraint {
-                    category,
-                    from_closure,
-                    cause: ObligationCause::new(span, CRATE_HIR_ID, cause_code),
-                    variance_info: constraint.variance_info,
-                    outlives_constraint: *constraint,
-                }
+            .map(|constraint| BlameConstraint {
+                category: constraint.category,
+                from_closure: constraint.from_closure,
+                cause: ObligationCause::new(constraint.span, CRATE_HIR_ID, cause_code.clone()),
+                variance_info: constraint.variance_info,
+                outlives_constraint: *constraint,
             })
             .collect();
         debug!("categorized_path={:#?}", categorized_path);
@@ -2274,92 +2232,6 @@ impl<'tcx> RegionDefinition<'tcx> {
     }
 }
 
-pub trait ClosureRegionRequirementsExt<'tcx> {
-    fn apply_requirements(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        closure_def_id: DefId,
-        closure_substs: SubstsRef<'tcx>,
-    ) -> Vec<QueryOutlivesConstraint<'tcx>>;
-}
-
-impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx> {
-    /// Given an instance T of the closure type, this method
-    /// instantiates the "extra" requirements that we computed for the
-    /// closure into the inference context. This has the effect of
-    /// adding new outlives obligations to existing variables.
-    ///
-    /// As described on `ClosureRegionRequirements`, the extra
-    /// requirements are expressed in terms of regionvids that index
-    /// into the free regions that appear on the closure type. So, to
-    /// do this, we first copy those regions out from the type T into
-    /// a vector. Then we can just index into that vector to extract
-    /// out the corresponding region from T and apply the
-    /// requirements.
-    fn apply_requirements(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        closure_def_id: DefId,
-        closure_substs: SubstsRef<'tcx>,
-    ) -> Vec<QueryOutlivesConstraint<'tcx>> {
-        debug!(
-            "apply_requirements(closure_def_id={:?}, closure_substs={:?})",
-            closure_def_id, closure_substs
-        );
-
-        // Extract the values of the free regions in `closure_substs`
-        // into a vector.  These are the regions that we will be
-        // relating to one another.
-        let closure_mapping = &UniversalRegions::closure_mapping(
-            tcx,
-            closure_substs,
-            self.num_external_vids,
-            closure_def_id.expect_local(),
-        );
-        debug!("apply_requirements: closure_mapping={:?}", closure_mapping);
-
-        // Create the predicates.
-        self.outlives_requirements
-            .iter()
-            .map(|outlives_requirement| {
-                let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
-
-                match outlives_requirement.subject {
-                    ClosureOutlivesSubject::Region(region) => {
-                        let region = closure_mapping[region];
-                        debug!(
-                            "apply_requirements: region={:?} \
-                             outlived_region={:?} \
-                             outlives_requirement={:?}",
-                            region, outlived_region, outlives_requirement,
-                        );
-                        (
-                            ty::Binder::dummy(ty::OutlivesPredicate(
-                                region.into(),
-                                outlived_region,
-                            )),
-                            ConstraintCategory::BoringNoLocation,
-                        )
-                    }
-
-                    ClosureOutlivesSubject::Ty(ty) => {
-                        debug!(
-                            "apply_requirements: ty={:?} \
-                             outlived_region={:?} \
-                             outlives_requirement={:?}",
-                            ty, outlived_region, outlives_requirement,
-                        );
-                        (
-                            ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region)),
-                            ConstraintCategory::BoringNoLocation,
-                        )
-                    }
-                }
-            })
-            .collect()
-    }
-}
-
 #[derive(Clone, Debug)]
 pub struct BlameConstraint<'tcx> {
     pub category: ConstraintCategory<'tcx>,
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index d5bfc2f520826..88be80c0b558d 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -1,10 +1,10 @@
-use rustc_infer::infer::canonical::QueryOutlivesConstraint;
+use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
 use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
 use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
 use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
-use rustc_middle::mir::ConstraintCategory;
+use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::TypeFoldable;
 use rustc_middle::ty::{self, TyCtxt};
@@ -38,6 +38,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
     locations: Locations,
     span: Span,
     category: ConstraintCategory<'tcx>,
+    from_closure: bool,
     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
 }
 
@@ -64,6 +65,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
             span,
             category,
             constraints,
+            from_closure: false,
         }
     }
 
@@ -81,12 +83,62 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
         }
         self.constraints.member_constraints = tmp;
 
-        for query_constraint in outlives {
-            self.convert(query_constraint);
+        for (predicate, constraint_category) in outlives {
+            // At the moment, we never generate any "higher-ranked"
+            // region constraints like `for<'a> 'a: 'b`. At some point
+            // when we move to universes, we will, and this assertion
+            // will start to fail.
+            let predicate = predicate.no_bound_vars().unwrap_or_else(|| {
+                bug!("query_constraint {:?} contained bound vars", predicate,);
+            });
+
+            self.convert(predicate, *constraint_category);
+        }
+    }
+
+    /// Given an instance of the closure type, this method instantiates the "extra" requirements
+    /// that we computed for the closure. This has the effect of adding new outlives obligations
+    /// to existing region variables in `closure_substs`.
+    #[instrument(skip(self), level = "debug")]
+    pub fn apply_closure_requirements(
+        &mut self,
+        closure_requirements: &ClosureRegionRequirements<'tcx>,
+        closure_def_id: DefId,
+        closure_substs: ty::SubstsRef<'tcx>,
+    ) {
+        // Extract the values of the free regions in `closure_substs`
+        // into a vector.  These are the regions that we will be
+        // relating to one another.
+        let closure_mapping = &UniversalRegions::closure_mapping(
+            self.tcx,
+            closure_substs,
+            closure_requirements.num_external_vids,
+            closure_def_id.expect_local(),
+        );
+        debug!(?closure_mapping);
+
+        // Create the predicates.
+        let backup = (self.category, self.span, self.from_closure);
+        self.from_closure = true;
+        for outlives_requirement in &closure_requirements.outlives_requirements {
+            let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
+            let subject = match outlives_requirement.subject {
+                ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(),
+                ClosureOutlivesSubject::Ty(ty) => ty.into(),
+            };
+
+            self.category = outlives_requirement.category;
+            self.span = outlives_requirement.blame_span;
+            self.convert(ty::OutlivesPredicate(subject, outlived_region), self.category);
         }
+        (self.category, self.span, self.from_closure) = backup;
     }
 
-    fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
+    fn convert(
+        &mut self,
+        predicate: ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>,
+        constraint_category: ConstraintCategory<'tcx>,
+    ) {
         debug!("generate: constraints at: {:#?}", self.locations);
 
         // Extract out various useful fields we'll need below.
@@ -94,17 +146,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
             tcx, region_bound_pairs, implicit_region_bound, param_env, ..
         } = *self;
 
-        // At the moment, we never generate any "higher-ranked"
-        // region constraints like `for<'a> 'a: 'b`. At some point
-        // when we move to universes, we will, and this assertion
-        // will start to fail.
-        let ty::OutlivesPredicate(k1, r2) =
-            query_constraint.0.no_bound_vars().unwrap_or_else(|| {
-                bug!("query_constraint {:?} contained bound vars", query_constraint,);
-            });
-
-        let constraint_category = query_constraint.1;
-
+        let ty::OutlivesPredicate(k1, r2) = predicate;
         match k1.unpack() {
             GenericArgKind::Lifetime(r1) => {
                 let r1_vid = self.to_region_vid(r1);
@@ -188,6 +230,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
             sub,
             sup,
             variance_info: ty::VarianceDiagInfo::default(),
+            from_closure: self.from_closure,
         });
     }
 
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 3c1c3ab45ce7a..3d9e08b4ca7ba 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -27,7 +27,7 @@ use rustc_middle::mir::AssertKind;
 use rustc_middle::mir::*;
 use rustc_middle::ty::adjustment::PointerCast;
 use rustc_middle::ty::cast::CastTy;
-use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
+use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{
     self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
@@ -61,7 +61,7 @@ use crate::{
     region_infer::values::{
         LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
     },
-    region_infer::{ClosureRegionRequirementsExt, TypeTest},
+    region_infer::TypeTest,
     type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
     universal_regions::{DefiningTy, UniversalRegions},
     Upvar,
@@ -144,7 +144,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
         liveness_constraints: LivenessValues::new(elements.clone()),
         outlives_constraints: OutlivesConstraintSet::default(),
         member_constraints: MemberConstraintSet::default(),
-        closure_bounds_mapping: Default::default(),
         type_tests: Vec::default(),
         universe_causes: FxHashMap::default(),
     };
@@ -585,7 +584,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         let all_facts = &mut None;
         let mut constraints = Default::default();
         let mut type_tests = Default::default();
-        let mut closure_bounds = Default::default();
         let mut liveness_constraints =
             LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body)));
         // Don't try to add borrow_region facts for the promoted MIR
@@ -597,10 +595,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                 &mut constraints,
             );
             mem::swap(&mut this.cx.borrowck_context.constraints.type_tests, &mut type_tests);
-            mem::swap(
-                &mut this.cx.borrowck_context.constraints.closure_bounds_mapping,
-                &mut closure_bounds,
-            );
             mem::swap(
                 &mut this.cx.borrowck_context.constraints.liveness_constraints,
                 &mut liveness_constraints,
@@ -653,18 +647,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                     .add_element(region, location);
             }
         }
-
-        if !closure_bounds.is_empty() {
-            let combined_bounds_mapping =
-                closure_bounds.into_iter().flat_map(|(_, value)| value).collect();
-            let existing = self
-                .cx
-                .borrowck_context
-                .constraints
-                .closure_bounds_mapping
-                .insert(location, combined_bounds_mapping);
-            assert!(existing.is_none(), "Multiple promoteds/closures at the same location.");
-        }
     }
 
     fn sanitize_projection(
@@ -941,9 +923,6 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
 
     pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
 
-    pub(crate) closure_bounds_mapping:
-        FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
-
     pub(crate) universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
 
     pub(crate) type_tests: Vec<TypeTest<'tcx>>,
@@ -2562,6 +2541,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                 span: location.to_locations().span(body),
                                 category,
                                 variance_info: ty::VarianceDiagInfo::default(),
+                                from_closure: false,
                             });
 
                             match mutbl {
@@ -2679,62 +2659,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         substs: SubstsRef<'tcx>,
         location: Location,
     ) -> ty::InstantiatedPredicates<'tcx> {
-        if let Some(ref closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements
-        {
-            let closure_constraints = QueryRegionConstraints {
-                outlives: closure_region_requirements.apply_requirements(
-                    tcx,
-                    def_id.to_def_id(),
-                    substs,
-                ),
-
-                // Presently, closures never propagate member
-                // constraints to their parents -- they are enforced
-                // locally.  This is largely a non-issue as member
-                // constraints only come from `-> impl Trait` and
-                // friends which don't appear (thus far...) in
-                // closures.
-                member_constraints: vec![],
-            };
-
-            let bounds_mapping = closure_constraints
-                .outlives
-                .iter()
-                .enumerate()
-                .filter_map(|(idx, constraint)| {
-                    let ty::OutlivesPredicate(k1, r2) =
-                        constraint.0.no_bound_vars().unwrap_or_else(|| {
-                            bug!("query_constraint {:?} contained bound vars", constraint,);
-                        });
-
-                    match k1.unpack() {
-                        GenericArgKind::Lifetime(r1) => {
-                            // constraint is r1: r2
-                            let r1_vid = self.borrowck_context.universal_regions.to_region_vid(r1);
-                            let r2_vid = self.borrowck_context.universal_regions.to_region_vid(r2);
-                            let outlives_requirements =
-                                &closure_region_requirements.outlives_requirements[idx];
-                            Some((
-                                (r1_vid, r2_vid),
-                                (outlives_requirements.category, outlives_requirements.blame_span),
-                            ))
-                        }
-                        GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
-                    }
-                })
-                .collect();
-
-            let existing = self
-                .borrowck_context
-                .constraints
-                .closure_bounds_mapping
-                .insert(location, bounds_mapping);
-            assert!(existing.is_none(), "Multiple closures at the same location.");
-
-            self.push_region_constraints(
+        if let Some(ref closure_requirements) = tcx.mir_borrowck(def_id).closure_requirements {
+            constraint_conversion::ConstraintConversion::new(
+                self.infcx,
+                self.borrowck_context.universal_regions,
+                self.region_bound_pairs,
+                self.implicit_region_bound,
+                self.param_env,
                 location.to_locations(),
-                ConstraintCategory::ClosureBounds,
-                &closure_constraints,
+                DUMMY_SP,                   // irrelevant; will be overrided.
+                ConstraintCategory::Boring, // same as above.
+                &mut self.borrowck_context.constraints,
+            )
+            .apply_closure_requirements(
+                &closure_requirements,
+                def_id.to_def_id(),
+                substs,
             );
         }
 
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 4f2dc263bf57b..94d5103286609 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -136,6 +136,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
                 span: self.locations.span(self.type_checker.body),
                 category: self.category,
                 variance_info: info,
+                from_closure: false,
             },
         );
     }
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
index 0195a693e5ffb..1260a656c98f2 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
@@ -167,7 +167,7 @@ LL | |     T: Anything<'b, 'b>,
    = note: defining type: two_regions::<'_#1r, T>
 
 error: lifetime may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:87:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:87:5
    |
 LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                --  -- lifetime `'b` defined here
@@ -175,9 +175,12 @@ LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                lifetime `'a` defined here
 ...
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of the type `Cell<&'_#8r ()>`, which makes the generic argument `&'_#8r ()` invariant
+   = note: the struct `Cell<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 note: external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:97:29

From 02f78fdb940b913228953b7530c9e429ce35bb8a Mon Sep 17 00:00:00 2001
From: Ali MJ Al-Nasrawy <alimjalnasrawy@gmail.com>
Date: Mon, 3 Oct 2022 13:45:02 +0300
Subject: [PATCH 2/2] use spans in TypeTest rather than mir::Location

Spans are independent of the body being borrow-checked, so they don't
need remapping when promoting type-tests and they yield more specific
error spans inside bodies of closures/inline consts.
---
 .../src/diagnostics/region_errors.rs          |  2 +-
 .../rustc_borrowck/src/region_infer/mod.rs    | 16 ++++-----
 .../src/type_check/constraint_conversion.rs   |  7 ++--
 compiler/rustc_borrowck/src/type_check/mod.rs |  9 -----
 src/test/ui/consts/issue-102117.rs            |  4 +--
 src/test/ui/consts/issue-102117.stderr        | 24 ++++---------
 .../generic-associated-types/issue-91139.rs   |  1 +
 .../issue-91139.stderr                        | 13 ++++++-
 .../propagate-from-trait-match.rs             |  3 +-
 .../propagate-from-trait-match.stderr         | 13 ++-----
 ...98589-closures-relate-named-regions.stderr |  8 ++---
 src/test/ui/nll/issue-98693.rs                |  2 +-
 src/test/ui/nll/issue-98693.stderr            |  9 ++---
 .../projection-implied-bounds.stderr          |  4 +--
 .../projection-no-regions-closure.stderr      |  8 ++---
 .../projection-one-region-closure.stderr      |  8 ++---
 ...tion-two-region-trait-bound-closure.stderr |  8 ++---
 ...ram-closure-approximate-lower-bound.stderr |  4 +--
 ...m-closure-outlives-from-return-type.stderr |  4 +--
 ...aram-closure-outlives-from-where-clause.rs |  5 ++-
 ...-closure-outlives-from-where-clause.stderr | 36 +++++++------------
 21 files changed, 76 insertions(+), 112 deletions(-)

diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 15230718dc0de..196ddbe8d5046 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -181,7 +181,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     // Try to convert the lower-bound region into something named we can print for the user.
                     let lower_bound_region = self.to_error_region(type_test.lower_bound);
 
-                    let type_test_span = type_test.locations.span(&self.body);
+                    let type_test_span = type_test.span;
 
                     if let Some(lower_bound_region) = lower_bound_region {
                         let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 6782fc0665f04..94e9e05e5d640 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -214,8 +214,8 @@ pub struct TypeTest<'tcx> {
     /// The region `'x` that the type must outlive.
     pub lower_bound: RegionVid,
 
-    /// Where did this constraint arise and why?
-    pub locations: Locations,
+    /// The span to blame.
+    pub span: Span,
 
     /// A test which, if met by the region `'x`, proves that this type
     /// constraint is satisfied.
@@ -870,13 +870,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             if deduplicate_errors.insert((
                 erased_generic_kind,
                 type_test.lower_bound,
-                type_test.locations,
+                type_test.span,
             )) {
                 debug!(
                     "check_type_test: reporting error for erased_generic_kind={:?}, \
                      lower_bound_region={:?}, \
-                     type_test.locations={:?}",
-                    erased_generic_kind, type_test.lower_bound, type_test.locations,
+                     type_test.span={:?}",
+                    erased_generic_kind, type_test.lower_bound, type_test.span,
                 );
 
                 errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() });
@@ -919,7 +919,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ) -> bool {
         let tcx = infcx.tcx;
 
-        let TypeTest { generic_kind, lower_bound, locations, verify_bound: _ } = type_test;
+        let TypeTest { generic_kind, lower_bound, span: _, verify_bound: _ } = type_test;
 
         let generic_ty = generic_kind.to_ty(tcx);
         let Some(subject) = self.try_promote_type_test_subject(infcx, generic_ty) else {
@@ -947,7 +947,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             propagated_outlives_requirements.push(ClosureOutlivesRequirement {
                 subject,
                 outlived_free_region: static_r,
-                blame_span: locations.span(body),
+                blame_span: type_test.span,
                 category: ConstraintCategory::Boring,
             });
 
@@ -999,7 +999,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 let requirement = ClosureOutlivesRequirement {
                     subject,
                     outlived_free_region: upper_bound,
-                    blame_span: locations.span(body),
+                    blame_span: type_test.span,
                     category: ConstraintCategory::Boring,
                 };
                 debug!("try_promote_type_test: pushing {:#?}", requirement);
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 88be80c0b558d..ce7f857e27310 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -169,10 +169,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
                 .type_must_outlive(origin, t1, r2, constraint_category);
             }
 
-            GenericArgKind::Const(_) => {
-                // Consts cannot outlive one another, so we
-                // don't need to handle any relations here.
-            }
+            GenericArgKind::Const(_) => unreachable!(),
         }
     }
 
@@ -202,7 +199,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
         verify_bound: VerifyBound<'tcx>,
     ) -> TypeTest<'tcx> {
         let lower_bound = self.to_region_vid(region);
-        TypeTest { generic_kind, lower_bound, locations: self.locations, verify_bound }
+        TypeTest { generic_kind, lower_bound, span: self.span, verify_bound }
     }
 
     fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 3d9e08b4ca7ba..50af229baaaed 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -583,7 +583,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         // modify their locations.
         let all_facts = &mut None;
         let mut constraints = Default::default();
-        let mut type_tests = Default::default();
         let mut liveness_constraints =
             LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body)));
         // Don't try to add borrow_region facts for the promoted MIR
@@ -594,7 +593,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                 &mut this.cx.borrowck_context.constraints.outlives_constraints,
                 &mut constraints,
             );
-            mem::swap(&mut this.cx.borrowck_context.constraints.type_tests, &mut type_tests);
             mem::swap(
                 &mut this.cx.borrowck_context.constraints.liveness_constraints,
                 &mut liveness_constraints,
@@ -615,13 +613,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         swap_constraints(self);
 
         let locations = location.to_locations();
-
-        // Use location of promoted const in collected constraints
-        for type_test in type_tests.iter() {
-            let mut type_test = type_test.clone();
-            type_test.locations = locations;
-            self.cx.borrowck_context.constraints.type_tests.push(type_test)
-        }
         for constraint in constraints.outlives().iter() {
             let mut constraint = constraint.clone();
             constraint.locations = locations;
diff --git a/src/test/ui/consts/issue-102117.rs b/src/test/ui/consts/issue-102117.rs
index b77342c4135e1..3ed90aed2350d 100644
--- a/src/test/ui/consts/issue-102117.rs
+++ b/src/test/ui/consts/issue-102117.rs
@@ -14,11 +14,11 @@ pub struct VTable {
 impl VTable {
     pub fn new<T>() -> &'static Self {
         const {
-          //~^ ERROR the parameter type `T` may not live long enough
-          //~| ERROR the parameter type `T` may not live long enough
             &VTable {
                 layout: Layout::new::<T>(),
                 type_id: TypeId::of::<T>(),
+                //~^ ERROR the parameter type `T` may not live long enough
+                //~| ERROR the parameter type `T` may not live long enough
                 drop_in_place: unsafe {
                     transmute::<unsafe fn(*mut T), unsafe fn(*mut ())>(drop_in_place::<T>)
                 },
diff --git a/src/test/ui/consts/issue-102117.stderr b/src/test/ui/consts/issue-102117.stderr
index eb4b329bd8134..f42bcf90fb756 100644
--- a/src/test/ui/consts/issue-102117.stderr
+++ b/src/test/ui/consts/issue-102117.stderr
@@ -1,14 +1,8 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/issue-102117.rs:16:9
+  --> $DIR/issue-102117.rs:19:26
    |
-LL | /         const {
-LL | |
-LL | |
-LL | |             &VTable {
-...  |
-LL | |             }
-LL | |         }
-   | |_________^ ...so that the type `T` will meet its required lifetime bounds
+LL |                 type_id: TypeId::of::<T>(),
+   |                          ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
@@ -16,16 +10,10 @@ LL |     pub fn new<T: 'static>() -> &'static Self {
    |                 +++++++++
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/issue-102117.rs:16:9
+  --> $DIR/issue-102117.rs:19:26
    |
-LL | /         const {
-LL | |
-LL | |
-LL | |             &VTable {
-...  |
-LL | |             }
-LL | |         }
-   | |_________^ ...so that the type `T` will meet its required lifetime bounds
+LL |                 type_id: TypeId::of::<T>(),
+   |                          ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/generic-associated-types/issue-91139.rs b/src/test/ui/generic-associated-types/issue-91139.rs
index 5fc6071c93966..e321da53d5668 100644
--- a/src/test/ui/generic-associated-types/issue-91139.rs
+++ b/src/test/ui/generic-associated-types/issue-91139.rs
@@ -21,6 +21,7 @@ fn foo<T>() {
     //~| ERROR `T` does not live long enough
     //~| ERROR `T` does not live long enough
     //~| ERROR `T` may not live long enough
+    //~| ERROR `T` may not live long enough
     //
     // FIXME: This error is bogus, but it arises because we try to validate
     // that `<() as Foo<T>>::Type<'a>` is valid, which requires proving
diff --git a/src/test/ui/generic-associated-types/issue-91139.stderr b/src/test/ui/generic-associated-types/issue-91139.stderr
index 8bbe98fa1e501..5485570cecd76 100644
--- a/src/test/ui/generic-associated-types/issue-91139.stderr
+++ b/src/test/ui/generic-associated-types/issue-91139.stderr
@@ -22,6 +22,17 @@ error: `T` does not live long enough
 LL |     let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/issue-91139.rs:14:58
+   |
+LL |     let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
+   |                                                          ^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn foo<T: 'static>() {
+   |         +++++++++
+
 error: `T` does not live long enough
   --> $DIR/issue-91139.rs:14:58
    |
@@ -57,6 +68,6 @@ error: `T` does not live long enough
 LL |     let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
    |                                                          ^^^^^^^^^
 
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs
index 3bdb543394857..cda781d8e2637 100644
--- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs
+++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs
@@ -30,8 +30,6 @@ where
     T: Trait<'a>,
 {
     establish_relationships(value, |value| {
-        //~^ ERROR the parameter type `T` may not live long enough
-
         // This function call requires that
         //
         // (a) T: Trait<'a>
@@ -43,6 +41,7 @@ where
         // The latter does not hold.
 
         require(value);
+        //~^ ERROR the parameter type `T` may not live long enough
     });
 }
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
index 750b08bbe855c..038a5e11f88ce 100644
--- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
@@ -23,17 +23,10 @@ LL | |     T: Trait<'a>,
    = note: defining type: supply::<'_#1r, T>
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/propagate-from-trait-match.rs:32:36
+  --> $DIR/propagate-from-trait-match.rs:43:9
    |
-LL |       establish_relationships(value, |value| {
-   |  ____________________________________^
-LL | |
-LL | |
-LL | |         // This function call requires that
-...  |
-LL | |         require(value);
-LL | |     });
-   | |_____^ ...so that the type `T` will meet its required lifetime bounds
+LL |         require(value);
+   |         ^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr b/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr
index 6def5602e70b3..d8b26f0b0171e 100644
--- a/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr
+++ b/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr
@@ -35,10 +35,10 @@ LL |     || { None::<&'a &'b ()>; };
    = help: consider adding the following bound: `'b: 'a`
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/issue-98589-closures-relate-named-regions.rs:26:5
+  --> $DIR/issue-98589-closures-relate-named-regions.rs:26:10
    |
 LL |     || { None::<&'a T>; };
-   |     ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |          ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
@@ -46,10 +46,10 @@ LL | fn test_early_type<'a: 'a, T: 'a>() {
    |                             ++++
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/issue-98589-closures-relate-named-regions.rs:32:5
+  --> $DIR/issue-98589-closures-relate-named-regions.rs:32:10
    |
 LL |     || { None::<&'a T>; };
-   |     ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |          ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/nll/issue-98693.rs b/src/test/ui/nll/issue-98693.rs
index 18e6ec6304646..7a325e2e998f3 100644
--- a/src/test/ui/nll/issue-98693.rs
+++ b/src/test/ui/nll/issue-98693.rs
@@ -13,8 +13,8 @@ where
 
 fn test<T>() {
     || {
-        //~^ ERROR the parameter type `T` may not live long enough
         assert_static::<T>();
+        //~^ ERROR the parameter type `T` may not live long enough
     };
 }
 
diff --git a/src/test/ui/nll/issue-98693.stderr b/src/test/ui/nll/issue-98693.stderr
index 31689620c6414..15ca38aa25dce 100644
--- a/src/test/ui/nll/issue-98693.stderr
+++ b/src/test/ui/nll/issue-98693.stderr
@@ -1,11 +1,8 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/issue-98693.rs:15:5
+  --> $DIR/issue-98693.rs:16:9
    |
-LL | /     || {
-LL | |
-LL | |         assert_static::<T>();
-LL | |     };
-   | |_____^ ...so that the type `T` will meet its required lifetime bounds
+LL |         assert_static::<T>();
+   |         ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr
index 3b9b2956c5183..d949e29b2b812 100644
--- a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr
@@ -1,8 +1,8 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/projection-implied-bounds.rs:30:18
+  --> $DIR/projection-implied-bounds.rs:30:36
    |
 LL |     twice(value, |value_ref, item| invoke2(value_ref, item));
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
index ee1f7b64bb231..4933b93486831 100644
--- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
@@ -23,10 +23,10 @@ LL | |     T: Iterator,
    = note: defining type: no_region::<'_#1r, T>
 
 error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-closure.rs:25:23
+  --> $DIR/projection-no-regions-closure.rs:25:31
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
    = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
@@ -80,10 +80,10 @@ LL | |     T: 'b + Iterator,
    = note: defining type: wrong_region::<'_#1r, '_#2r, T>
 
 error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-closure.rs:42:23
+  --> $DIR/projection-no-regions-closure.rs:42:31
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
    = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
index 4e57dfad794e3..dbda04c42c5c7 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
@@ -25,10 +25,10 @@ LL | |     T: Anything<'b>,
    = note: defining type: no_relationships_late::<'_#1r, T>
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:45:29
+  --> $DIR/projection-one-region-closure.rs:45:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |                                       ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
@@ -75,10 +75,10 @@ LL | |     'a: 'a,
    = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:56:29
+  --> $DIR/projection-one-region-closure.rs:56:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |                                       ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
index 1260a656c98f2..90f04914286c1 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
@@ -24,10 +24,10 @@ LL | |     T: Anything<'b, 'c>,
    = note: defining type: no_relationships_late::<'_#1r, '_#2r, T>
 
 error[E0309]: the associated type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:38:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:38:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                       ^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType: 'a`...
    = note: ...so that the type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` will meet its required lifetime bounds
@@ -58,10 +58,10 @@ LL | |     'a: 'a,
    = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T>
 
 error[E0309]: the associated type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:48:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:48:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                       ^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: 'a`...
    = note: ...so that the type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` will meet its required lifetime bounds
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
index 61c7d2550caad..f316a551cffa6 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
@@ -44,10 +44,10 @@ LL | fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
    = note: defining type: generic_fail::<T>
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:31
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
-   |                        ^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |                               ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
index 50d9e3aabe2d4..35979c8bf5171 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
@@ -23,10 +23,10 @@ LL | |     T: Debug,
    = note: defining type: no_region::<'_#1r, T>
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:27
    |
 LL |     with_signature(x, |y| y)
-   |                       ^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |                           ^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
index d7702def32c52..b802876105041 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
@@ -25,13 +25,12 @@ where
 #[rustc_regions]
 fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
     with_signature(a, b, |x, y| {
-        //~^ ERROR the parameter type `T` may not live long enough
-        //
         // See `correct_region`, which explains the point of this
         // test.  The only difference is that, in the case of this
         // function, there is no where clause *anywhere*, and hence we
         // get an error (but reported by the closure creator).
         require(&x, &y)
+        //~^ ERROR the parameter type `T` may not live long enough
     })
 }
 
@@ -62,9 +61,9 @@ where
     T: 'b,
 {
     with_signature(a, b, |x, y| {
-        //~^ ERROR the parameter type `T` may not live long enough
         // See `correct_region`
         require(&x, &y)
+        //~^ ERROR the parameter type `T` may not live long enough
     })
 }
 
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
index 14c55e32a3ebe..4c97db58c6c3d 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
@@ -22,17 +22,10 @@ LL | fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
    = note: defining type: no_region::<T>
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:32:9
    |
-LL |       with_signature(a, b, |x, y| {
-   |  __________________________^
-LL | |
-LL | |         //
-LL | |         // See `correct_region`, which explains the point of this
-...  |
-LL | |         require(&x, &y)
-LL | |     })
-   | |_____^ ...so that the type `T` will meet its required lifetime bounds
+LL |         require(&x, &y)
+   |         ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
@@ -40,7 +33,7 @@ LL | fn no_region<'a, T: 'a>(a: Cell<&'a ()>, b: T) {
    |                   ++++
 
 note: external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:43:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:42:26
    |
 LL |     with_signature(a, b, |x, y| {
    |                          ^^^^^^
@@ -54,7 +47,7 @@ LL |     with_signature(a, b, |x, y| {
    = note: where T: '_#2r
 
 note: no external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:39:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:1
    |
 LL | / fn correct_region<'a, T>(a: Cell<&'a ()>, b: T)
 LL | | where
@@ -64,7 +57,7 @@ LL | |     T: 'a,
    = note: defining type: correct_region::<'_#1r, T>
 
 note: external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:63:26
    |
 LL |     with_signature(a, b, |x, y| {
    |                          ^^^^^^
@@ -79,7 +72,7 @@ LL |     with_signature(a, b, |x, y| {
    = note: where T: '_#2r
 
 note: no external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:60:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:59:1
    |
 LL | / fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
 LL | | where
@@ -89,15 +82,10 @@ LL | |     T: 'b,
    = note: defining type: wrong_region::<'_#1r, T>
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:65:9
    |
-LL |       with_signature(a, b, |x, y| {
-   |  __________________________^
-LL | |
-LL | |         // See `correct_region`
-LL | |         require(&x, &y)
-LL | |     })
-   | |_____^ ...so that the type `T` will meet its required lifetime bounds
+LL |         require(&x, &y)
+   |         ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
@@ -105,7 +93,7 @@ LL |     T: 'b + 'a,
    |           ++++
 
 note: external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:77:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26
    |
 LL |     with_signature(a, b, |x, y| {
    |                          ^^^^^^
@@ -119,7 +107,7 @@ LL |     with_signature(a, b, |x, y| {
    = note: where T: '_#3r
 
 note: no external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:72:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:71:1
    |
 LL | / fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
 LL | | where