about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/mir/mod.rs7
-rw-r--r--src/librustc_mir/borrow_check/nll/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs32
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/mod.rs25
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs123
-rw-r--r--src/test/ui/issues/issue-10291.nll.stderr14
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr25
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr28
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr27
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-val.rs2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr25
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr8
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr8
-rw-r--r--src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr15
-rw-r--r--src/test/ui/regions/regions-nested-fns.nll.stderr15
18 files changed, 214 insertions, 148 deletions
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 61e8ad4a8c4..eef9c0f1cf8 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -2639,11 +2639,14 @@ pub struct ClosureOutlivesRequirement<'tcx> {
     // This region or type ...
     pub subject: ClosureOutlivesSubject<'tcx>,
 
-    // .. must outlive this one.
+    // ... must outlive this one.
     pub outlived_free_region: ty::RegionVid,
 
-    // If not, report an error here.
+    // If not, report an error here ...
     pub blame_span: Span,
+
+    // ... due to this reason.
+    pub category: ConstraintCategory,
 }
 
 /// Outlives constraints can be categorized to determine whether and why they
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index 723b0e6fff6..6e35f2e63f7 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -138,6 +138,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     let MirTypeckRegionConstraints {
         mut liveness_constraints,
         outlives_constraints,
+        closure_bounds_mapping,
         type_tests,
     } = constraints;
 
@@ -157,6 +158,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
         universal_region_relations,
         mir,
         outlives_constraints,
+        closure_bounds_mapping,
         type_tests,
         liveness_constraints,
         elements,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index 9acfe42e6ca..43dc68fdb3b 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -10,6 +10,7 @@
 
 use borrow_check::nll::constraints::{OutlivesConstraint};
 use borrow_check::nll::region_infer::RegionInferenceContext;
+use borrow_check::nll::type_check::Locations;
 use rustc::hir::def_id::DefId;
 use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
 use rustc::infer::InferCtxt;
@@ -18,7 +19,6 @@ use rustc::ty::{self, RegionVid};
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_errors::{Diagnostic, DiagnosticBuilder};
 use std::collections::VecDeque;
-use std::fmt;
 use syntax::symbol::keywords;
 use syntax_pos::Span;
 use syntax::errors::Applicability;
@@ -93,7 +93,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // Classify each of the constraints along the path.
         let mut categorized_path: Vec<(ConstraintCategory, Span)> = path
             .iter()
-            .map(|constraint| (constraint.category, constraint.locations.span(mir)))
+            .map(|constraint| {
+                if constraint.category == ConstraintCategory::ClosureBounds {
+                    self.retrieve_closure_constraint_info(mir, &constraint)
+                } else {
+                    (constraint.category, constraint.locations.span(mir))
+                }
+            })
             .collect();
         debug!(
             "best_blame_constraint: categorized_path={:#?}",
@@ -474,8 +480,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         mir: &Mir<'tcx>,
         fr1: RegionVid,
         fr2: RegionVid,
-    ) -> Span {
-        let (_, span, _) = self.best_blame_constraint(mir, fr1, |r| r == fr2);
-        span
+    ) -> (ConstraintCategory, Span) {
+        let (category, span, _) = self.best_blame_constraint(mir, fr1, |r| r == fr2);
+        (category, span)
+    }
+
+    fn retrieve_closure_constraint_info(
+        &self,
+        mir: &Mir<'tcx>,
+        constraint: &OutlivesConstraint
+    ) -> (ConstraintCategory, Span) {
+        let loc = match constraint.locations {
+            Locations::All(span) => return (constraint.category, span),
+            Locations::Single(loc) => loc,
+        };
+
+        let opt_span_category = self
+            .closure_bounds_mapping[&loc]
+            .get(&(constraint.sup, constraint.sub));
+        *opt_span_category.unwrap_or(&(constraint.category, mir.source_info(loc).span))
     }
 }
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index a6730fa847f..56bb6a87d44 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -25,9 +25,11 @@ use rustc::mir::{
 use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
 use rustc::util::common;
 use rustc_data_structures::bit_set::BitSet;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::graph::scc::Sccs;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_errors::{Diagnostic, DiagnosticBuilder};
+use syntax_pos::Span;
 
 use std::rc::Rc;
 
@@ -60,10 +62,16 @@ pub struct RegionInferenceContext<'tcx> {
     /// the SCC (see `constraint_sccs`) and for error reporting.
     constraint_graph: Rc<NormalConstraintGraph>,
 
-    /// The SCC computed from `constraints` and the constraint graph. Used to compute the values
-    /// of each region.
+    /// The SCC computed from `constraints` and the constraint graph. Used to
+    /// compute the values of each region.
     constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
 
+    /// Map closure bounds to a `Span` that should be used for error reporting.
+    closure_bounds_mapping: FxHashMap<
+        Location,
+        FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
+    >,
+
     /// Contains the minimum universe of any variable within the same
     /// SCC. We will ensure that no SCC contains values that are not
     /// visible from this index.
@@ -187,6 +195,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
         _mir: &Mir<'tcx>,
         outlives_constraints: ConstraintSet,
+        closure_bounds_mapping: FxHashMap<
+            Location,
+            FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
+        >,
         type_tests: Vec<TypeTest<'tcx>>,
         liveness_constraints: LivenessValues<RegionVid>,
         elements: &Rc<RegionValueElements>,
@@ -220,6 +232,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             constraints,
             constraint_graph,
             constraint_sccs,
+            closure_bounds_mapping,
             scc_universes,
             scc_representatives,
             scc_values,
@@ -727,6 +740,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 subject,
                 outlived_free_region: non_local_ub,
                 blame_span: locations.span(mir),
+                category: ConstraintCategory::Boring,
             };
             debug!("try_promote_type_test: pushing {:#?}", requirement);
             propagated_outlives_requirements.push(requirement);
@@ -1125,7 +1139,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 longer_fr, shorter_fr,
             );
 
-            let blame_span = self.find_outlives_blame_span(mir, longer_fr, shorter_fr);
+            let blame_span_category = self.find_outlives_blame_span(mir, longer_fr, shorter_fr);
 
             if let Some(propagated_outlives_requirements) = propagated_outlives_requirements {
                 // Shrink `fr` until we find a non-local region (if we do).
@@ -1150,7 +1164,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     propagated_outlives_requirements.push(ClosureOutlivesRequirement {
                         subject: ClosureOutlivesSubject::Region(fr_minus),
                         outlived_free_region: shorter_fr_plus,
-                        blame_span: blame_span,
+                        blame_span: blame_span_category.1,
+                        category: blame_span_category.0,
                     });
                     return;
                 }
@@ -1213,7 +1228,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         };
 
         // Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
-        let span = self.find_outlives_blame_span(mir, longer_fr, error_region);
+        let (_, span) = self.find_outlives_blame_span(mir, longer_fr, error_region);
 
         // Obviously, this error message is far from satisfactory.
         // At present, though, it only appears in unit tests --
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 553d4a426a7..36eb695186c 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -42,7 +42,7 @@ use rustc::traits::query::type_op::custom::CustomTypeOp;
 use rustc::traits::query::{Fallible, NoSolution};
 use rustc::traits::{ObligationCause, PredicateObligations};
 use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::Subst;
+use rustc::ty::subst::{Subst, UnpackedKind};
 use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
 use std::rc::Rc;
 use std::{fmt, iter};
@@ -50,7 +50,7 @@ use syntax_pos::{Span, DUMMY_SP};
 use transform::{MirPass, MirSource};
 
 use either::Either;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 
 macro_rules! span_mirbug {
     ($context:expr, $elem:expr, $($message:tt)*) => ({
@@ -128,6 +128,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
     let mut constraints = MirTypeckRegionConstraints {
         liveness_constraints: LivenessValues::new(elements),
         outlives_constraints: ConstraintSet::default(),
+        closure_bounds_mapping: FxHashMap(),
         type_tests: Vec::default(),
     };
     let mut placeholder_indices = PlaceholderIndices::default();
@@ -752,6 +753,11 @@ crate struct MirTypeckRegionConstraints<'tcx> {
 
     crate outlives_constraints: ConstraintSet,
 
+    crate closure_bounds_mapping: FxHashMap<
+        Location,
+        FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
+    >,
+
     crate type_tests: Vec<TypeTest<'tcx>>,
 }
 
@@ -860,7 +866,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         &mut self,
         locations: Locations,
         category: ConstraintCategory,
-        op: impl type_op::TypeOp<'gcx, 'tcx, Output = R>,
+        op: impl type_op::TypeOp<'gcx, 'tcx, Output=R>,
     ) -> Fallible<R> {
         let (r, opt_data) = op.fully_perform(self.infcx)?;
 
@@ -1103,9 +1109,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 let place_ty = place.ty(mir, tcx).to_ty(tcx);
                 let rv_ty = rv.ty(mir, tcx);
                 if let Err(terr) =
-                    self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category)
-                {
-                    span_mirbug!(
+                self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category)
+                    {
+                        span_mirbug!(
                         self,
                         stmt,
                         "bad assignment ({:?} = {:?}): {:?}",
@@ -1113,7 +1119,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                         rv_ty,
                         terr
                     );
-                }
+                    }
 
                 if let Some(user_ty) = self.rvalue_user_ty(rv) {
                     if let Err(terr) = self.relate_type_and_user_type(
@@ -1233,9 +1239,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
 
                 let locations = term_location.to_locations();
                 if let Err(terr) =
-                    self.sub_types(rv_ty, place_ty, locations, ConstraintCategory::Assignment)
-                {
-                    span_mirbug!(
+                self.sub_types(rv_ty, place_ty, locations, ConstraintCategory::Assignment)
+                    {
+                        span_mirbug!(
                         self,
                         term,
                         "bad DropAndReplace ({:?} = {:?}): {:?}",
@@ -1243,7 +1249,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                         rv_ty,
                         terr
                     );
-                }
+                    }
             }
             TerminatorKind::SwitchInt {
                 ref discr,
@@ -1387,9 +1393,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 let locations = term_location.to_locations();
 
                 if let Err(terr) =
-                    self.sub_types_or_anon(sig.output(), dest_ty, locations, category)
-                {
-                    span_mirbug!(
+                self.sub_types_or_anon(sig.output(), dest_ty, locations, category)
+                    {
+                        span_mirbug!(
                         self,
                         term,
                         "call dest mismatch ({:?} <- {:?}): {:?}",
@@ -1397,7 +1403,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                         sig.output(),
                         terr
                     );
-                }
+                    }
 
                 // When `#![feature(unsized_locals)]` is not enabled,
                 // this check is done at `check_local`.
@@ -2038,7 +2044,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             aggregate_kind, location
         );
 
-        let instantiated_predicates = match aggregate_kind {
+        let instantiated_predicates = match aggregate_kind  {
             AggregateKind::Adt(def, _, substs, _, _) => {
                 tcx.predicates_of(def.did).instantiate(tcx, substs)
             }
@@ -2064,24 +2070,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             // these extra requirements are basically like where
             // clauses on the struct.
             AggregateKind::Closure(def_id, substs) => {
-                if let Some(closure_region_requirements) =
-                    tcx.mir_borrowck(*def_id).closure_requirements
-                {
-                    let closure_constraints = closure_region_requirements.apply_requirements(
-                        self.infcx.tcx,
-                        location,
-                        *def_id,
-                        *substs,
-                    );
-
-                    self.push_region_constraints(
-                        location.to_locations(),
-                        ConstraintCategory::ClosureBounds,
-                        &closure_constraints,
-                    );
-                }
-
-                tcx.predicates_of(*def_id).instantiate(tcx, substs.substs)
+                self.prove_closure_bounds(tcx, *def_id, *substs, location)
             }
 
             AggregateKind::Generator(def_id, substs, _) => {
@@ -2097,6 +2086,72 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         );
     }
 
+    fn prove_closure_bounds(
+        &mut self,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        def_id: DefId,
+        substs: ty::ClosureSubsts<'tcx>,
+        location: Location,
+    ) -> ty::InstantiatedPredicates<'tcx> {
+        if let Some(closure_region_requirements) =
+            tcx.mir_borrowck(def_id).closure_requirements
+        {
+            let closure_constraints = closure_region_requirements.apply_requirements(
+                tcx,
+                location,
+                def_id,
+                substs,
+            );
+
+            if let Some(ref mut borrowck_context) = self.borrowck_context {
+                let bounds_mapping = closure_constraints
+                    .iter()
+                    .enumerate()
+                    .filter_map(|(idx, constraint)| {
+                        let ty::OutlivesPredicate(k1, r2) =
+                            constraint.no_late_bound_regions().unwrap_or_else(|| {
+                                bug!(
+                                    "query_constraint {:?} contained bound regions",
+                                    constraint,
+                                );
+                            });
+
+                        match k1.unpack() {
+                            UnpackedKind::Lifetime(r1) => {
+                                // constraint is r1: r2
+                                let r1_vid = borrowck_context.universal_regions.to_region_vid(r1);
+                                let r2_vid = 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,
+                                    ),
+                                ))
+                            }
+                            UnpackedKind::Type(_) => None,
+                        }
+                    })
+                    .collect();
+
+                let existing = borrowck_context.constraints
+                    .closure_bounds_mapping
+                    .insert(location, bounds_mapping);
+                assert!(existing.is_none(), "Multiple closures at the same location.");
+            }
+
+            self.push_region_constraints(
+                location.to_locations(),
+                ConstraintCategory::ClosureBounds,
+                &closure_constraints,
+            );
+        }
+
+        tcx.predicates_of(def_id).instantiate(tcx, substs.substs)
+    }
+
     fn prove_trait_ref(
         &mut self,
         trait_ref: ty::TraitRef<'tcx>,
diff --git a/src/test/ui/issues/issue-10291.nll.stderr b/src/test/ui/issues/issue-10291.nll.stderr
index 201a3b3d54a..a21336654f3 100644
--- a/src/test/ui/issues/issue-10291.nll.stderr
+++ b/src/test/ui/issues/issue-10291.nll.stderr
@@ -1,13 +1,11 @@
 error: unsatisfied lifetime constraints
-  --> $DIR/issue-10291.rs:12:65
+  --> $DIR/issue-10291.rs:13:9
    |
-LL |   fn test<'x>(x: &'x isize) {
-   |           -- lifetime `'x` defined here
-LL |       drop::<Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
-   |  _________________________________________________________________^
-LL | |         x //~ ERROR E0312
-LL | |     }));
-   | |_____^ closure body requires that `'x` must outlive `'static`
+LL | fn test<'x>(x: &'x isize) {
+   |         -- lifetime `'x` defined here
+LL |     drop::<Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+LL |         x //~ ERROR E0312
+   |         ^ returning this value requires that `'x` must outlive `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
index 700c0dffb70..3f7e400ed43 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
@@ -51,10 +51,10 @@ fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u3
 #[rustc_regions]
 fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-        //~^ ERROR unsatisfied lifetime constraints
 
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
+        //~^ ERROR unsatisfied lifetime constraints
     });
 }
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
index 2e1249a5e81..ef84820de38 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -3,10 +3,10 @@ note: External requirements
    |
 LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
    |  _______________________________________________^
-LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
+LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |     });
    | |_____^
    |
@@ -24,8 +24,8 @@ note: No external requirements
    |
 LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
 LL | |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |
+LL | |         // Only works if 'x: 'y:
 ...  |
 LL | |     });
 LL | | }
@@ -34,20 +34,15 @@ LL | | }
    = note: defining type: DefId(0/0:6 ~ propagate_approximated_ref[317d]::supply[0]) with substs []
 
 error: unsatisfied lifetime constraints
-  --> $DIR/propagate-approximated-ref.rs:53:47
+  --> $DIR/propagate-approximated-ref.rs:56:9
    |
-LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
-   |             --  -- lifetime `'b` defined here
-   |             |
-   |             lifetime `'a` defined here
-LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-   |  _______________________________________________^
-LL | |         //~^ ERROR unsatisfied lifetime constraints
-LL | |
-LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get())
-LL | |     });
-   | |_____^ closure body requires that `'a` must outlive `'b`
+LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+...
+LL |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs
index 9963954c9c2..49b62581640 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs
@@ -44,10 +44,10 @@ fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u3
 fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
         //~^ ERROR borrowed data escapes outside of function
-        //~| ERROR unsatisfied lifetime constraints
 
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
+        //~^ ERROR unsatisfied lifetime constraints
     });
 }
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
index 9f1d9d21d11..7ebd36e10b5 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -4,10 +4,10 @@ note: External requirements
 LL |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
    |  _______________________________________________^
 LL | |         //~^ ERROR borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
 LL | |
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
+LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |     });
    | |_____^
    |
@@ -26,7 +26,7 @@ note: No external requirements
 LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
 LL | |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
 LL | |         //~^ ERROR borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
+LL | |
 ...  |
 LL | |     });
 LL | | }
@@ -41,29 +41,23 @@ LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
    |                     ------ `cell_a` is a reference that is only valid in the function body
 LL | /     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
 LL | |         //~^ ERROR borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
 LL | |
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
+LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |     });
    | |______^ `cell_a` escapes the function body here
 
 error: unsatisfied lifetime constraints
-  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:47
+  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:49:9
    |
-LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
-   |             --  -- lifetime `'b` defined here
-   |             |
-   |             lifetime `'a` defined here
-LL |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
-   |  _______________________________________________^
-LL | |         //~^ ERROR borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
-LL | |
-LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get())
-LL | |     });
-   | |_____^ closure body requires that `'a` must outlive `'b`
+LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+...
+LL |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs
index d35b5c34a91..0181792cbdc 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs
@@ -47,9 +47,9 @@ fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u3
 fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
         //~^ ERROR borrowed data escapes outside of function
-        //~| ERROR unsatisfied lifetime constraints
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
+        //~^ ERROR unsatisfied lifetime constraints
     });
 }
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
index 4e72fe4bb28..d62910576b0 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -4,9 +4,9 @@ note: External requirements
 LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
    |  _______________________________________________^
 LL | |         //~^ ERROR borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
+LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |     });
    | |_____^
    |
@@ -25,7 +25,7 @@ note: No external requirements
 LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
 LL | |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
 LL | |         //~^ ERROR borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
+LL | |         // Only works if 'x: 'y:
 ...  |
 LL | |     });
 LL | | }
@@ -40,27 +40,22 @@ LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
    |                     ------ `cell_a` is a reference that is only valid in the function body
 LL | /     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
 LL | |         //~^ ERROR borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
+LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |     });
    | |______^ `cell_a` escapes the function body here
 
 error: unsatisfied lifetime constraints
-  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:47
+  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:51:9
    |
-LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
-   |             --  -- lifetime `'b` defined here
-   |             |
-   |             lifetime `'a` defined here
-LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-   |  _______________________________________________^
-LL | |         //~^ ERROR borrowed data escapes outside of function
-LL | |         //~| ERROR unsatisfied lifetime constraints
-LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get())
-LL | |     });
-   | |_____^ closure body requires that `'a` must outlive `'b`
+LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+...
+LL |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
index 75641943f2f..1a0531cbd42 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
@@ -44,10 +44,10 @@ fn demand_y<'x, 'y>(_outlives1: Cell<&&'x u32>, _outlives2: Cell<&'y &u32>, _y:
 #[rustc_regions]
 fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
-        //~^ ERROR unsatisfied lifetime constraints
 
         // Only works if 'x: 'y:
         demand_y(outlives1, outlives2, x.get())
+        //~^ ERROR unsatisfied lifetime constraints
     });
 }
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
index de60b23ef6b..aa193682404 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -3,10 +3,10 @@ note: External requirements
    |
 LL |       establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
    |  _____________________________________________^
-LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(outlives1, outlives2, x.get())
+LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |     });
    | |_____^
    |
@@ -24,8 +24,8 @@ note: No external requirements
    |
 LL | / fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
 LL | |     establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
-LL | |         //~^ ERROR unsatisfied lifetime constraints
 LL | |
+LL | |         // Only works if 'x: 'y:
 ...  |
 LL | |     });
 LL | | }
@@ -34,20 +34,15 @@ LL | | }
    = note: defining type: DefId(0/0:6 ~ propagate_approximated_val[317d]::test[0]) with substs []
 
 error: unsatisfied lifetime constraints
-  --> $DIR/propagate-approximated-val.rs:46:45
+  --> $DIR/propagate-approximated-val.rs:49:9
    |
-LL |   fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
-   |           --  -- lifetime `'b` defined here
-   |           |
-   |           lifetime `'a` defined here
-LL |       establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
-   |  _____________________________________________^
-LL | |         //~^ ERROR unsatisfied lifetime constraints
-LL | |
-LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(outlives1, outlives2, x.get())
-LL | |     });
-   | |_____^ closure body requires that `'a` must outlive `'b`
+LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |         --  -- lifetime `'b` defined here
+   |         |
+   |         lifetime `'a` defined here
+...
+LL |         demand_y(outlives1, outlives2, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
 
 error: aborting due to previous error
 
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 455fbba2320..dc7f58fc8f8 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
@@ -41,7 +41,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`...
 
 error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-closure.rs:55:29
+  --> $DIR/projection-one-region-closure.rs:55:39
    |
 LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                          --  -- lifetime `'b` defined here
@@ -49,7 +49,7 @@ LL | fn no_relationships_late<'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`
 
 note: External requirements
   --> $DIR/projection-one-region-closure.rs:66:29
@@ -95,7 +95,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
 
 error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-closure.rs:66:29
+  --> $DIR/projection-one-region-closure.rs:66:39
    |
 LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                           --  -- lifetime `'b` defined here
@@ -103,7 +103,7 @@ LL | fn no_relationships_early<'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`
 
 note: External requirements
   --> $DIR/projection-one-region-closure.rs:80:29
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
index b98aca74058..18d35d8b9bf 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
@@ -32,7 +32,7 @@ LL | | }
            ]
 
 error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-trait-bound-closure.rs:47:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:47:39
    |
 LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                          --  -- lifetime `'b` defined here
@@ -40,7 +40,7 @@ LL | fn no_relationships_late<'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`
 
 note: External requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:57:29
@@ -77,7 +77,7 @@ LL | | }
            ]
 
 error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-trait-bound-closure.rs:57:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:57:39
    |
 LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                           --  -- lifetime `'b` defined here
@@ -85,7 +85,7 @@ LL | fn no_relationships_early<'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`
 
 note: External requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:70:29
diff --git a/src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr b/src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr
index 6e4bf26047e..fd52494b499 100644
--- a/src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr
+++ b/src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr
@@ -21,16 +21,13 @@ LL |             let p: &'static mut usize = &mut self.food; //~ ERROR cannot in
    = note: closure implements `FnMut`, so references to captured variables can't escape the closure
 
 error: unsatisfied lifetime constraints
-  --> $DIR/regions-addr-of-upvar-self.rs:19:18
+  --> $DIR/regions-addr-of-upvar-self.rs:20:17
    |
-LL |       pub fn chase_cat(&mut self) {
-   |                        - let's call the lifetime of this reference `'1`
-LL |           let _f = || {
-   |  __________________^
-LL | |             let p: &'static mut usize = &mut self.food; //~ ERROR cannot infer
-LL | |             *p = 3;
-LL | |         };
-   | |_________^ closure body requires that `'1` must outlive `'static`
+LL |     pub fn chase_cat(&mut self) {
+   |                      - let's call the lifetime of this reference `'1`
+LL |         let _f = || {
+LL |             let p: &'static mut usize = &mut self.food; //~ ERROR cannot infer
+   |                 ^ type annotation requires that `'1` must outlive `'static`
 
 error[E0597]: `self` does not live long enough
   --> $DIR/regions-addr-of-upvar-self.rs:20:46
diff --git a/src/test/ui/regions/regions-nested-fns.nll.stderr b/src/test/ui/regions/regions-nested-fns.nll.stderr
index 4bb602d572f..cbc1e6b787d 100644
--- a/src/test/ui/regions/regions-nested-fns.nll.stderr
+++ b/src/test/ui/regions/regions-nested-fns.nll.stderr
@@ -36,18 +36,13 @@ LL | }
    = note: borrowed value must be valid for the static lifetime...
 
 error: unsatisfied lifetime constraints
-  --> $DIR/regions-nested-fns.rs:23:68
+  --> $DIR/regions-nested-fns.rs:24:27
    |
-LL |   fn nested<'x>(x: &'x isize) {
-   |             -- lifetime `'x` defined here
+LL | fn nested<'x>(x: &'x isize) {
+   |           -- lifetime `'x` defined here
 ...
-LL |       ignore::< Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
-   |  ____________________________________________________________________^
-LL | |         if false { return x; } //~ ERROR E0312
-LL | |         if false { return ay; }
-LL | |         return z;
-LL | |     }));
-   | |_____^ closure body requires that `'x` must outlive `'static`
+LL |         if false { return x; } //~ ERROR E0312
+   |                           ^ returning this value requires that `'x` must outlive `'static`
 
 error: aborting due to 4 previous errors