about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc/infer/opaque_types/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/constraints/graph.rs7
-rw-r--r--src/librustc_mir/borrow_check/nll/constraints/mod.rs39
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs4
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs152
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs27
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/mod.rs4
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs6
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs5
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/input_output.rs59
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs9
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs387
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs13
-rw-r--r--src/librustc_mir/build/mod.rs63
-rw-r--r--src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr15
-rw-r--r--src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr2
-rw-r--r--src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr15
-rw-r--r--src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr4
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr32
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.stderr32
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr6
-rw-r--r--src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr4
-rw-r--r--src/test/ui/impl-trait/type_parameters_captured.nll.stderr6
-rw-r--r--src/test/ui/issues/issue-10291.nll.stderr13
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/escape-argument-callee.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr7
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr21
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr20
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr7
-rw-r--r--src/test/ui/nll/issue-50716.stderr6
-rw-r--r--src/test/ui/nll/issue-52113.rs4
-rw-r--r--src/test/ui/nll/issue-52113.stderr7
-rw-r--r--src/test/ui/nll/issue-52742.stderr2
-rw-r--r--src/test/ui/nll/mir_check_cast_reify.rs2
-rw-r--r--src/test/ui/nll/mir_check_cast_reify.stderr6
-rw-r--r--src/test/ui/nll/mir_check_cast_unsafe_fn.rs2
-rw-r--r--src/test/ui/nll/mir_check_cast_unsafe_fn.stderr6
-rw-r--r--src/test/ui/nll/mir_check_cast_unsize.stderr2
-rw-r--r--src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr4
-rw-r--r--src/test/ui/nll/ty-outlives/impl-trait-outlives.rs4
-rw-r--r--src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr12
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr60
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr12
-rw-r--r--src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr4
-rw-r--r--src/test/ui/nll/type-alias-free-regions.rs33
-rw-r--r--src/test/ui/nll/type-alias-free-regions.stderr22
-rw-r--r--src/test/ui/nll/user-annotations/patterns.stderr4
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr6
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr6
-rw-r--r--src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr4
-rw-r--r--src/test/ui/regions/regions-addr-of-self.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr18
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-2.nll.stderr4
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-4.nll.stderr16
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-infer-paramd-indirect.nll.stderr11
-rw-r--r--src/test/ui/regions/regions-nested-fns.nll.stderr30
-rw-r--r--src/test/ui/regions/regions-trait-object-subtyping.nll.stderr2
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr2
-rw-r--r--src/test/ui/variance/variance-contravariant-arg-object.nll.stderr4
-rw-r--r--src/test/ui/variance/variance-covariant-arg-object.nll.stderr4
-rw-r--r--src/test/ui/variance/variance-invariant-arg-object.nll.stderr4
70 files changed, 746 insertions, 540 deletions
diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs
index 9d65c395062..c6f910c4ad7 100644
--- a/src/librustc/infer/opaque_types/mod.rs
+++ b/src/librustc/infer/opaque_types/mod.rs
@@ -284,7 +284,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
+    pub fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
         &self,
         def_id: DefId,
         opaque_defn: &OpaqueTypeDecl<'tcx>,
diff --git a/src/librustc_mir/borrow_check/nll/constraints/graph.rs b/src/librustc_mir/borrow_check/nll/constraints/graph.rs
index b1e8b974379..2e018f746f3 100644
--- a/src/librustc_mir/borrow_check/nll/constraints/graph.rs
+++ b/src/librustc_mir/borrow_check/nll/constraints/graph.rs
@@ -9,10 +9,12 @@
 // except according to those terms.
 
 use borrow_check::nll::type_check::Locations;
-use borrow_check::nll::constraints::{ConstraintIndex, ConstraintSet, OutlivesConstraint};
+use borrow_check::nll::constraints::{ConstraintCategory, ConstraintIndex};
+use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
 use rustc::ty::RegionVid;
 use rustc_data_structures::graph;
 use rustc_data_structures::indexed_vec::IndexVec;
+use syntax_pos::DUMMY_SP;
 
 /// The construct graph organizes the constraints by their end-points.
 /// It can be used to view a `R1: R2` constraint as either an edge `R1
@@ -174,7 +176,8 @@ impl<'s, D: ConstraintGraphDirecton> Iterator for Edges<'s, D> {
             Some(OutlivesConstraint {
                 sup: self.static_region,
                 sub: next_static_idx.into(),
-                locations: Locations::All,
+                locations: Locations::All(DUMMY_SP),
+                category: ConstraintCategory::Internal,
             })
         } else {
             None
diff --git a/src/librustc_mir/borrow_check/nll/constraints/mod.rs b/src/librustc_mir/borrow_check/nll/constraints/mod.rs
index 41c846509cd..76ebc06bfd2 100644
--- a/src/librustc_mir/borrow_check/nll/constraints/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/constraints/mod.rs
@@ -23,6 +23,42 @@ crate struct ConstraintSet {
     constraints: IndexVec<ConstraintIndex, OutlivesConstraint>,
 }
 
+/// Constraints can be categorized to determine whether and why they are
+/// interesting. Order of variants indicates sort order of the category,
+/// thereby influencing diagnostic output.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
+pub enum ConstraintCategory {
+    Return,
+    TypeAnnotation,
+    Cast,
+    CallArgument,
+
+    /// A constraint that came from checking the body of a closure.
+    ///
+    /// Ideally we would give an explanation that points to the relevant part
+    /// of the closure's body.
+    ClosureBounds,
+    CopyBound,
+    SizedBound,
+    Assignment,
+    OpaqueType,
+
+    /// A "boring" constraint (caused by the given location) is one that
+    /// the user probably doesn't want to see described in diagnostics,
+    /// because it is kind of an artifact of the type system setup.
+    /// Example: `x = Foo { field: y }` technically creates
+    /// intermediate regions representing the "type of `Foo { field: y
+    /// }`", and data flows from `y` into those variables, but they
+    /// are not very interesting. The assignment into `x` on the other
+    /// hand might be.
+    Boring,
+    // Boring and applicable everywhere.
+    BoringNoLocation,
+
+    /// A constraint that doesn't correspond to anything the user sees.
+    Internal,
+}
+
 impl ConstraintSet {
     crate fn push(&mut self, constraint: OutlivesConstraint) {
         debug!(
@@ -87,6 +123,9 @@ pub struct OutlivesConstraint {
 
     /// Where did this constraint arise?
     pub locations: Locations,
+
+    /// What caused this constraint?
+    pub category: ConstraintCategory,
 }
 
 impl fmt::Debug for OutlivesConstraint {
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
index d3b4f0a0447..ee900afc44d 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
@@ -88,11 +88,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 sup,
                 sub,
                 locations,
+                category,
             } = constraint;
             with_msg(&format!(
-                "{:?}: {:?} due to {:?}",
+                "{:?}: {:?} due to {:?} at {:?}",
                 sup,
                 sub,
+                category,
                 locations,
             ))?;
         }
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 67e4394c9aa..d287116029a 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
@@ -8,14 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use borrow_check::nll::constraints::OutlivesConstraint;
+use borrow_check::nll::constraints::{OutlivesConstraint, ConstraintCategory};
 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;
-use rustc::mir::{self, Location, Mir, Place, Rvalue, StatementKind, TerminatorKind};
-use rustc::ty::{self, TyCtxt, RegionVid};
+use rustc::mir::{Location, Mir};
+use rustc::ty::{self, RegionVid};
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_errors::{Diagnostic, DiagnosticBuilder};
 use std::collections::VecDeque;
@@ -29,19 +28,6 @@ mod var_name;
 
 use self::region_name::RegionName;
 
-/// Constraints that are considered interesting can be categorized to
-/// determine why they are interesting. Order of variants indicates
-/// sort order of the category, thereby influencing diagnostic output.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
-enum ConstraintCategory {
-    Cast,
-    Assignment,
-    Return,
-    CallArgument,
-    Other,
-    Boring,
-}
-
 impl fmt::Display for ConstraintCategory {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         // Must end with a space. Allows for empty names to be provided.
@@ -50,7 +36,14 @@ impl fmt::Display for ConstraintCategory {
             ConstraintCategory::Return => write!(f, "returning this value "),
             ConstraintCategory::Cast => write!(f, "cast "),
             ConstraintCategory::CallArgument => write!(f, "argument "),
-            _ => write!(f, ""),
+            ConstraintCategory::TypeAnnotation => write!(f, "type annotation "),
+            ConstraintCategory::ClosureBounds => write!(f, "closure body "),
+            ConstraintCategory::SizedBound => write!(f, "proving this value is `Sized` "),
+            ConstraintCategory::CopyBound => write!(f, "copying this value "),
+            ConstraintCategory::OpaqueType => write!(f, "opaque type "),
+            ConstraintCategory::Boring
+            | ConstraintCategory::BoringNoLocation
+            | ConstraintCategory::Internal => write!(f, ""),
         }
     }
 }
@@ -72,7 +65,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn best_blame_constraint(
         &self,
         mir: &Mir<'tcx>,
-        tcx: TyCtxt<'_, '_, 'tcx>,
         from_region: RegionVid,
         target_test: impl Fn(RegionVid) -> bool,
     ) -> (ConstraintCategory, Span, RegionVid) {
@@ -97,7 +89,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // Classify each of the constraints along the path.
         let mut categorized_path: Vec<(ConstraintCategory, Span)> = path
             .iter()
-            .map(|&index| self.classify_constraint(index, mir, tcx))
+            .map(|constraint| (constraint.category, constraint.locations.span(mir)))
             .collect();
         debug!(
             "best_blame_constraint: categorized_path={:#?}",
@@ -130,12 +122,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup);
 
             match categorized_path[i].0 {
-                ConstraintCategory::Boring => false,
-                ConstraintCategory::Other => {
-                    // other isn't interesting when the two lifetimes
-                    // are unified.
-                    constraint_sup_scc != self.constraint_sccs.scc(constraint.sub)
-                }
+                ConstraintCategory::OpaqueType
+                | ConstraintCategory::Boring
+                | ConstraintCategory::BoringNoLocation
+                | ConstraintCategory::Internal => false,
                 _ => constraint_sup_scc != target_scc,
             }
         });
@@ -221,106 +211,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         None
     }
 
-    /// This function will return true if a constraint is interesting and false if a constraint
-    /// is not. It is useful in filtering constraint paths to only interesting points.
-    fn constraint_is_interesting(&self, constraint: OutlivesConstraint) -> bool {
-        debug!(
-            "constraint_is_interesting: locations={:?} constraint={:?}",
-            constraint.locations, constraint
-        );
-
-        match constraint.locations {
-            Locations::Interesting(_) | Locations::All => true,
-            _ => false,
-        }
-    }
-
-    /// This function classifies a constraint from a location.
-    fn classify_constraint(
-        &self,
-        constraint: OutlivesConstraint,
-        mir: &Mir<'tcx>,
-        tcx: TyCtxt<'_, '_, 'tcx>,
-    ) -> (ConstraintCategory, Span) {
-        debug!("classify_constraint: constraint={:?}", constraint);
-        let span = constraint.locations.span(mir);
-        let location = constraint
-            .locations
-            .from_location()
-            .unwrap_or(Location::START);
-
-        if !self.constraint_is_interesting(constraint) {
-            return (ConstraintCategory::Boring, span);
-        }
-
-        let data = &mir[location.block];
-        debug!(
-            "classify_constraint: location={:?} data={:?}",
-            location, data
-        );
-        let category = if location.statement_index == data.statements.len() {
-            if let Some(ref terminator) = data.terminator {
-                debug!("classify_constraint: terminator.kind={:?}", terminator.kind);
-                match terminator.kind {
-                    TerminatorKind::DropAndReplace { .. } => ConstraintCategory::Assignment,
-                    // Classify calls differently depending on whether or not
-                    // the sub region appears in the destination type (so the
-                    // sup region is in the return type). If the return type
-                    // contains the sub-region, then this is either an
-                    // assignment or a return, depending on whether we are
-                    // writing to the RETURN_PLACE or not.
-                    //
-                    // The idea here is that the region is being propagated
-                    // from an input into the output place, so it's a kind of
-                    // assignment. Otherwise, if the sub-region only appears in
-                    // the argument types, then use the CallArgument
-                    // classification.
-                    TerminatorKind::Call { destination: Some((ref place, _)), .. } => {
-                        if tcx.any_free_region_meets(
-                            &place.ty(mir, tcx).to_ty(tcx),
-                            |region| self.to_region_vid(region) == constraint.sub,
-                        ) {
-                            match place {
-                                Place::Local(mir::RETURN_PLACE) => ConstraintCategory::Return,
-                                _ => ConstraintCategory::Assignment,
-                            }
-                        } else {
-                            ConstraintCategory::CallArgument
-                        }
-                    }
-                    TerminatorKind::Call { destination: None, .. } => {
-                        ConstraintCategory::CallArgument
-                    }
-                    _ => ConstraintCategory::Other,
-                }
-            } else {
-                ConstraintCategory::Other
-            }
-        } else {
-            let statement = &data.statements[location.statement_index];
-            debug!("classify_constraint: statement.kind={:?}", statement.kind);
-            match statement.kind {
-                StatementKind::Assign(ref place, ref rvalue) => {
-                    debug!("classify_constraint: place={:?} rvalue={:?}", place, rvalue);
-                    if *place == Place::Local(mir::RETURN_PLACE) {
-                        ConstraintCategory::Return
-                    } else {
-                        match rvalue {
-                            Rvalue::Cast(..) => ConstraintCategory::Cast,
-                            Rvalue::Use(..) | Rvalue::Aggregate(..) => {
-                                ConstraintCategory::Assignment
-                            }
-                            _ => ConstraintCategory::Other,
-                        }
-                    }
-                }
-                _ => ConstraintCategory::Other,
-            }
-        };
-
-        (category, span)
-    }
-
     /// Report an error because the universal region `fr` was required to outlive
     /// `outlived_fr` but it is not known to do so. For example:
     ///
@@ -342,7 +232,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         let (category, span, _) = self.best_blame_constraint(
             mir,
-            infcx.tcx,
             fr,
             |r| r == outlived_fr
         );
@@ -392,7 +281,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         let escapes_from = if infcx.tcx.is_closure(mir_def_id) { "closure" } else { "function" };
 
-        if fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none() {
+        // Revert to the normal error in these cases.
+        // Assignments aren't "escapes" in function items.
+        if (fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none())
+            || (category == ConstraintCategory::Assignment && escapes_from == "function")
+        {
             return self.report_general_error(mir, infcx, mir_def_id,
                                              fr, true, outlived_fr, false,
                                              category, span, errors_buffer);
@@ -572,11 +465,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     crate fn find_outlives_blame_span(
         &self,
         mir: &Mir<'tcx>,
-        tcx: TyCtxt<'_, '_, 'tcx>,
         fr1: RegionVid,
         fr2: RegionVid,
     ) -> Span {
-        let (_, span, _) = self.best_blame_constraint(mir, tcx, fr1, |r| r == fr2);
+        let (_, span, _) = self.best_blame_constraint(mir, fr1, |r| r == fr2);
         span
     }
 }
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
index 857f1dae7ab..f704ee61c88 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
@@ -452,16 +452,23 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     ty::Adt(_adt_def, substs),
                     hir::TyKind::Path(hir::QPath::Resolved(None, path)),
                 ) => {
-                    if let Some(last_segment) = path.segments.last() {
-                        if let Some(name) = self.match_adt_and_segment(
-                            substs,
-                            needle_fr,
-                            last_segment,
-                            counter,
-                            diag,
-                            search_stack,
-                        ) {
-                            return Some(name);
+                    match path.def {
+                        // Type parameters of the type alias have no reason to
+                        // be the same as those of the ADT.
+                        // FIXME: We should be able to do something similar to
+                        // match_adt_and_segment in this case.
+                        hir::def::Def::TyAlias(_) => (),
+                        _ => if let Some(last_segment) = path.segments.last() {
+                            if let Some(name) = self.match_adt_and_segment(
+                                substs,
+                                needle_fr,
+                                last_segment,
+                                counter,
+                                diag,
+                                search_stack,
+                            ) {
+                                return Some(name);
+                            }
                         }
                     }
                 }
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 d1713a520a7..75f14a6bbda 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -1062,7 +1062,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 longer_fr, shorter_fr,
             );
 
-            let blame_span = self.find_outlives_blame_span(mir, infcx.tcx, longer_fr, shorter_fr);
+            let blame_span = 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).
@@ -1147,7 +1147,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, infcx.tcx, 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/constraint_conversion.rs b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
index 64a61972a22..430c8d67392 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use borrow_check::location::LocationTable;
-use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
+use borrow_check::nll::constraints::{ConstraintCategory, ConstraintSet, OutlivesConstraint};
 use borrow_check::nll::facts::AllFacts;
 use borrow_check::nll::region_infer::{RegionTest, TypeTest};
 use borrow_check::nll::type_check::Locations;
@@ -30,6 +30,7 @@ crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> {
     implicit_region_bound: Option<ty::Region<'tcx>>,
     param_env: ty::ParamEnv<'tcx>,
     locations: Locations,
+    category: ConstraintCategory,
     outlives_constraints: &'a mut ConstraintSet,
     type_tests: &'a mut Vec<TypeTest<'tcx>>,
     all_facts: &'a mut Option<AllFacts>,
@@ -44,6 +45,7 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
         implicit_region_bound: Option<ty::Region<'tcx>>,
         param_env: ty::ParamEnv<'tcx>,
         locations: Locations,
+        category: ConstraintCategory,
         outlives_constraints: &'a mut ConstraintSet,
         type_tests: &'a mut Vec<TypeTest<'tcx>>,
         all_facts: &'a mut Option<AllFacts>,
@@ -56,6 +58,7 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
             implicit_region_bound,
             param_env,
             locations,
+            category,
             outlives_constraints,
             type_tests,
             all_facts,
@@ -183,6 +186,7 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
     fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
         self.outlives_constraints.push(OutlivesConstraint {
             locations: self.locations,
+            category: self.category,
             sub,
             sup,
         });
diff --git a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
index e21c490622c..61c612b3c01 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
@@ -14,6 +14,7 @@ use borrow_check::nll::type_check::constraint_conversion;
 use borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
 use borrow_check::nll::universal_regions::UniversalRegions;
 use borrow_check::nll::ToRegionVid;
+use borrow_check::nll::constraints::ConstraintCategory;
 use rustc::infer::canonical::QueryRegionConstraint;
 use rustc::infer::outlives::free_region_map::FreeRegionRelations;
 use rustc::infer::region_constraints::GenericKind;
@@ -23,6 +24,7 @@ use rustc::traits::query::type_op::{self, TypeOp};
 use rustc::ty::{self, RegionVid, Ty};
 use rustc_data_structures::transitive_relation::TransitiveRelation;
 use std::rc::Rc;
+use syntax_pos::DUMMY_SP;
 
 #[derive(Debug)]
 crate struct UniversalRegionRelations<'tcx> {
@@ -283,7 +285,8 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> {
                 &self.region_bound_pairs,
                 self.implicit_region_bound,
                 self.param_env,
-                Locations::All,
+                Locations::All(DUMMY_SP),
+                ConstraintCategory::Internal,
                 &mut self.constraints.outlives_constraints,
                 &mut self.constraints.type_tests,
                 &mut self.all_facts,
diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
index 265cd305eb9..6c7e2e9b72e 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
@@ -29,8 +29,9 @@ use rustc::ty::subst::Subst;
 use rustc::ty::Ty;
 
 use rustc_data_structures::indexed_vec::Idx;
+use syntax_pos::Span;
 
-use super::{Locations, TypeChecker};
+use super::{ConstraintCategory, Locations, TypeChecker};
 
 impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     pub(super) fn equate_inputs_and_outputs(
@@ -56,7 +57,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             );
 
             let mir_input_ty = mir.local_decls[local].ty;
-            self.equate_normalized_input_or_output(normalized_input_ty, mir_input_ty);
+            let mir_input_span = mir.local_decls[local].source_info.span;
+            self.equate_normalized_input_or_output(
+                normalized_input_ty,
+                mir_input_ty,
+                mir_input_span,
+            );
         }
 
         assert!(
@@ -65,16 +71,19 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         );
         if let Some(mir_yield_ty) = mir.yield_ty {
             let ur_yield_ty = universal_regions.yield_ty.unwrap();
-            self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty);
+            let yield_span = mir.local_decls[RETURN_PLACE].source_info.span;
+            self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
         }
 
         // Return types are a bit more complex. They may contain existential `impl Trait`
         // types.
         let param_env = self.param_env;
         let mir_output_ty = mir.local_decls[RETURN_PLACE].ty;
+        let output_span = mir.local_decls[RETURN_PLACE].source_info.span;
         let opaque_type_map =
             self.fully_perform_op(
-                Locations::All,
+                Locations::All(output_span),
+                ConstraintCategory::BoringNoLocation,
                 CustomTypeOp::new(
                     |infcx| {
                         let mut obligations = ObligationAccumulator::default();
@@ -152,26 +161,38 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         // prove that `T: Iterator` where `T` is the type we
         // instantiated it with).
         if let Some(opaque_type_map) = opaque_type_map {
-            self.fully_perform_op(
-                Locations::All,
-                CustomTypeOp::new(
-                    |_cx| {
-                        infcx.constrain_opaque_types(&opaque_type_map, universal_region_relations);
-                        Ok(InferOk {
-                            value: (),
-                            obligations: vec![],
-                        })
-                    },
-                    || "opaque_type_map".to_string(),
-                ),
-            ).unwrap();
+            for (opaque_def_id, opaque_decl) in opaque_type_map {
+                self.fully_perform_op(
+                    Locations::All(infcx.tcx.def_span(opaque_def_id)),
+                    ConstraintCategory::OpaqueType,
+                    CustomTypeOp::new(
+                        |_cx| {
+                            infcx.constrain_opaque_type(
+                                opaque_def_id,
+                                &opaque_decl,
+                                universal_region_relations
+                            );
+                            Ok(InferOk {
+                                value: (),
+                                obligations: vec![],
+                            })
+                        },
+                        || "opaque_type_map".to_string(),
+                    ),
+                ).unwrap();
+            }
         }
     }
 
-    fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
+    fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
         debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b);
 
-        if let Err(terr) = self.eq_types(a, b, Locations::All) {
+        if let Err(terr) = self.eq_types(
+            a,
+            b,
+            Locations::All(span),
+            ConstraintCategory::BoringNoLocation,
+        ) {
             span_mirbug!(
                 self,
                 Location::START,
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
index 47e6ce05cec..e706c1adadd 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
@@ -8,10 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use borrow_check::nll::constraints::ConstraintCategory;
 use borrow_check::nll::region_infer::values::{self, PointIndex, RegionValueElements};
 use borrow_check::nll::type_check::liveness::liveness_map::{LiveVar, NllLivenessMap};
 use borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap;
-use borrow_check::nll::type_check::AtLocation;
+use borrow_check::nll::type_check::NormalizeLocation;
 use borrow_check::nll::type_check::TypeChecker;
 use dataflow::move_paths::indexes::MovePathIndex;
 use dataflow::move_paths::MoveData;
@@ -487,7 +488,11 @@ impl LivenessContext<'_, '_, '_, '_, 'tcx> {
         if let Some(data) = &drop_data.region_constraint_data {
             for &drop_location in drop_locations {
                 self.typeck
-                    .push_region_constraints(drop_location.boring(), data);
+                    .push_region_constraints(
+                        drop_location.to_locations(),
+                        ConstraintCategory::Boring,
+                        data,
+                    );
             }
         }
 
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 1f12e9c747f..a20d7cc5619 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -13,7 +13,7 @@
 
 use borrow_check::borrow_set::BorrowSet;
 use borrow_check::location::LocationTable;
-use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
+use borrow_check::nll::constraints::{ConstraintCategory, ConstraintSet, OutlivesConstraint};
 use borrow_check::nll::facts::AllFacts;
 use borrow_check::nll::region_infer::values::{LivenessValues, RegionValueElements};
 use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest};
@@ -252,7 +252,8 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 constant.ty,
                 ty::Variance::Invariant,
                 user_ty,
-                location.boring(),
+                location.to_locations(),
+                ConstraintCategory::Boring,
             ) {
                 span_mirbug!(
                     self,
@@ -281,7 +282,8 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 local_decl.ty,
                 ty::Variance::Invariant,
                 user_ty,
-                Locations::All,
+                Locations::All(local_decl.source_info.span),
+                ConstraintCategory::TypeAnnotation,
             ) {
                 span_mirbug!(
                     self,
@@ -364,14 +366,19 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
             let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
             type_checker.normalize_and_prove_instantiated_predicates(
                 instantiated_predicates,
-                location.boring(),
+                location.to_locations(),
             );
         }
 
         debug!("sanitize_constant: expected_ty={:?}", constant.literal.ty);
 
         if let Err(terr) = self.cx
-            .eq_types(constant.literal.ty, constant.ty, location.boring())
+            .eq_types(
+                constant.literal.ty,
+                constant.ty,
+                location.to_locations(),
+                ConstraintCategory::Boring,
+            )
         {
             span_mirbug!(
                 self,
@@ -417,7 +424,12 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 let sty = self.sanitize_type(place, sty);
                 let ty = self.tcx().type_of(def_id);
                 let ty = self.cx.normalize(ty, location);
-                if let Err(terr) = self.cx.eq_types(ty, sty, location.boring()) {
+                if let Err(terr) = self.cx.eq_types(
+                    ty,
+                    sty,
+                    location.to_locations(),
+                    ConstraintCategory::Boring,
+                ) {
                     span_mirbug!(
                         self,
                         place,
@@ -461,7 +473,11 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
             // (e.g., #29149). Note that we decide to use Copy before knowing whether the bounds
             // fully apply: in effect, the rule is that if a value of some type could implement
             // Copy, then it must.
-            self.cx.prove_trait_ref(trait_ref, location.interesting());
+            self.cx.prove_trait_ref(
+                trait_ref,
+                location.to_locations(),
+                ConstraintCategory::CopyBound,
+            );
         }
         place_ty
     }
@@ -560,7 +576,12 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
             ProjectionElem::Field(field, fty) => {
                 let fty = self.sanitize_type(place, fty);
                 match self.field_ty(place, base, field, location) {
-                    Ok(ty) => if let Err(terr) = self.cx.eq_types(ty, fty, location.boring()) {
+                    Ok(ty) => if let Err(terr) = self.cx.eq_types(
+                        ty,
+                        fty,
+                        location.to_locations(),
+                        ConstraintCategory::Boring,
+                    ) {
                         span_mirbug!(
                             self,
                             place,
@@ -740,43 +761,32 @@ pub enum Locations {
     /// user-given type annotations; e.g., if the user wrote `let mut
     /// x: &'static u32 = ...`, we would ensure that all values
     /// assigned to `x` are of `'static` lifetime.
-    All,
-
-    /// A "boring" constraint (caused by the given location) is one that
-    /// the user probably doesn't want to see described in diagnostics,
-    /// because it is kind of an artifact of the type system setup.
     ///
-    /// Example: `x = Foo { field: y }` technically creates
-    /// intermediate regions representing the "type of `Foo { field: y
-    /// }`", and data flows from `y` into those variables, but they
-    /// are not very interesting. The assignment into `x` on the other
-    /// hand might be.
-    Boring(Location),
-
-    /// An *important* outlives constraint (caused by the given
-    /// location) is one that would be useful to highlight in
-    /// diagnostics, because it represents a point where references
-    /// flow from one spot to another (e.g., `x = y`)
-    Interesting(Location),
+    /// The span points to the place the constraint arose. For example,
+    /// it points to the type in a user-given type annotation. If
+    /// there's no sensible span then it's DUMMY_SP.
+    All(Span),
+
+    /// An outlives constraint that only has to hold at a single location,
+    /// usually it represents a point where references flow from one spot to
+    /// another (e.g., `x = y`)
+    Single(Location),
 }
 
 impl Locations {
     pub fn from_location(&self) -> Option<Location> {
         match self {
-            Locations::All => None,
-            Locations::Boring(from_location) | Locations::Interesting(from_location) => {
-                Some(*from_location)
-            }
+            Locations::All(_) => None,
+            Locations::Single(from_location) => Some(*from_location),
         }
     }
 
     /// Gets a span representing the location.
     pub fn span(&self, mir: &Mir<'_>) -> Span {
-        let span_location = match self {
-            Locations::All => Location::START,
-            Locations::Boring(l) | Locations::Interesting(l) => *l,
-        };
-        mir.source_info(span_location).span
+        match self {
+            Locations::All(span) => *span,
+            Locations::Single(l) => mir.source_info(*l).span,
+        }
     }
 }
 
@@ -816,12 +826,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     fn fully_perform_op<R>(
         &mut self,
         locations: Locations,
+        category: ConstraintCategory,
         op: impl type_op::TypeOp<'gcx, 'tcx, Output = R>,
     ) -> Fallible<R> {
         let (r, opt_data) = op.fully_perform(self.infcx)?;
 
         if let Some(data) = &opt_data {
-            self.push_region_constraints(locations, data);
+            self.push_region_constraints(locations, category, data);
         }
 
         Ok(r)
@@ -830,6 +841,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     fn push_region_constraints(
         &mut self,
         locations: Locations,
+        category: ConstraintCategory,
         data: &[QueryRegionConstraint<'tcx>],
     ) {
         debug!(
@@ -846,6 +858,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 self.implicit_region_bound,
                 self.param_env,
                 locations,
+                category,
                 &mut borrowck_context.constraints.outlives_constraints,
                 &mut borrowck_context.constraints.type_tests,
                 &mut borrowck_context.all_facts,
@@ -853,22 +866,36 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn sub_types(&mut self, sub: Ty<'tcx>, sup: Ty<'tcx>, locations: Locations) -> Fallible<()> {
+    fn sub_types(
+        &mut self,
+        sub: Ty<'tcx>,
+        sup: Ty<'tcx>,
+        locations: Locations,
+        category: ConstraintCategory,
+    ) -> Fallible<()> {
         relate_tys::sub_types(
             self.infcx,
             sub,
             sup,
             locations,
+            category,
             self.borrowck_context.as_mut().map(|x| &mut **x),
         )
     }
 
-    fn eq_types(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, locations: Locations) -> Fallible<()> {
+    fn eq_types(
+        &mut self,
+        a: Ty<'tcx>,
+        b: Ty<'tcx>,
+        locations: Locations,
+        category: ConstraintCategory,
+    ) -> Fallible<()> {
         relate_tys::eq_types(
             self.infcx,
             a,
             b,
             locations,
+            category,
             self.borrowck_context.as_mut().map(|x| &mut **x),
         )
     }
@@ -879,6 +906,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         v: ty::Variance,
         b: CanonicalTy<'tcx>,
         locations: Locations,
+        category: ConstraintCategory,
     ) -> Fallible<()> {
         relate_tys::relate_type_and_user_type(
             self.infcx,
@@ -886,6 +914,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             v,
             b,
             locations,
+            category,
             self.borrowck_context.as_mut().map(|x| &mut **x),
         )
     }
@@ -903,21 +932,22 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 // they are not caused by the user, but rather artifacts
                 // of lowering. Assignments to other sorts of places *are* interesting
                 // though.
-                let is_temp = if let Place::Local(l) = *place {
-                    l != RETURN_PLACE && !mir.local_decls[l].is_user_variable.is_some()
-                } else {
-                    false
-                };
-
-                let locations = if is_temp {
-                    location.boring()
-                } else {
-                    location.interesting()
+                let category = match *place {
+                    Place::Local(RETURN_PLACE) => ConstraintCategory::Return,
+                    Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
+                        ConstraintCategory::Boring
+                    }
+                    _ => ConstraintCategory::Assignment,
                 };
 
                 let place_ty = place.ty(mir, tcx).to_ty(tcx);
                 let rv_ty = rv.ty(mir, tcx);
-                if let Err(terr) = self.sub_types(rv_ty, place_ty, locations) {
+                if let Err(terr) = self.sub_types(
+                    rv_ty,
+                    place_ty,
+                    location.to_locations(),
+                    category,
+                ) {
                     span_mirbug!(
                         self,
                         stmt,
@@ -933,7 +963,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                         rv_ty,
                         ty::Variance::Invariant,
                         user_ty,
-                        location.boring(),
+                        location.to_locations(),
+                        ConstraintCategory::Boring,
                     ) {
                         span_mirbug!(
                             self,
@@ -952,7 +983,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                         def_id: tcx.lang_items().sized_trait().unwrap(),
                         substs: tcx.mk_substs_trait(place_ty, &[]),
                     };
-                    self.prove_trait_ref(trait_ref, location.interesting());
+                    self.prove_trait_ref(
+                        trait_ref,
+                        location.to_locations(),
+                    ConstraintCategory::SizedBound,
+                    );
                 }
             }
             StatementKind::SetDiscriminant {
@@ -983,7 +1018,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             StatementKind::AscribeUserType(ref place, variance, c_ty) => {
                 let place_ty = place.ty(mir, tcx).to_ty(tcx);
                 if let Err(terr) =
-                    self.relate_type_and_user_type(place_ty, variance, c_ty, Locations::All)
+                    self.relate_type_and_user_type(
+                        place_ty,
+                        variance,
+                        c_ty,
+                        Locations::All(stmt.source_info.span),
+                        ConstraintCategory::TypeAnnotation,
+                    )
                 {
                     span_mirbug!(
                         self,
@@ -1035,8 +1076,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 let place_ty = location.ty(mir, tcx).to_ty(tcx);
                 let rv_ty = value.ty(mir, tcx);
 
-                let locations = term_location.interesting();
-                if let Err(terr) = self.sub_types(rv_ty, place_ty, locations) {
+                let locations = term_location.to_locations();
+                if let Err(terr) = self.sub_types(
+                    rv_ty,
+                    place_ty,
+                    locations,
+                    ConstraintCategory::Assignment,
+                ) {
                     span_mirbug!(
                         self,
                         term,
@@ -1053,7 +1099,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 ..
             } => {
                 let discr_ty = discr.ty(mir, tcx);
-                if let Err(terr) = self.sub_types(discr_ty, switch_ty, term_location.boring()) {
+                if let Err(terr) = self.sub_types(
+                    discr_ty,
+                    switch_ty,
+                    term_location.to_locations(),
+                    ConstraintCategory::Assignment,
+                ) {
                     span_mirbug!(
                         self,
                         term,
@@ -1093,7 +1144,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
 
                 self.prove_predicates(
                     sig.inputs().iter().map(|ty| ty::Predicate::WellFormed(ty)),
-                    term_location.boring(),
+                    term_location.to_locations(),
+                    ConstraintCategory::Boring,
                 );
 
                 // The ordinary liveness rules will ensure that all
@@ -1139,7 +1191,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 match mir.yield_ty {
                     None => span_mirbug!(self, term, "yield in non-generator"),
                     Some(ty) => {
-                        if let Err(terr) = self.sub_types(value_ty, ty, term_location.interesting())
+                        if let Err(terr) = self.sub_types(
+                            value_ty,
+                            ty,
+                            term_location.to_locations(),
+                            ConstraintCategory::Return,
+                        )
                         {
                             span_mirbug!(
                                 self,
@@ -1168,19 +1225,22 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         match *destination {
             Some((ref dest, _target_block)) => {
                 let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
-                let is_temp = if let Place::Local(l) = *dest {
-                    l != RETURN_PLACE && !mir.local_decls[l].is_user_variable.is_some()
-                } else {
-                    false
+                let category = match *dest {
+                    Place::Local(RETURN_PLACE) => ConstraintCategory::Return,
+                    Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
+                        ConstraintCategory::Boring
+                    }
+                    _ => ConstraintCategory::Assignment,
                 };
 
-                let locations = if is_temp {
-                    term_location.boring()
-                } else {
-                    term_location.interesting()
-                };
+                let locations = term_location.to_locations();
 
-                if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations) {
+                if let Err(terr) = self.sub_types(
+                    sig.output(),
+                    dest_ty,
+                    locations,
+                    category,
+                ) {
                     span_mirbug!(
                         self,
                         term,
@@ -1221,7 +1281,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         }
         for (n, (fn_arg, op_arg)) in sig.inputs().iter().zip(args).enumerate() {
             let op_arg_ty = op_arg.ty(mir, self.tcx());
-            if let Err(terr) = self.sub_types(op_arg_ty, fn_arg, term_location.interesting()) {
+            if let Err(terr) = self.sub_types(
+                op_arg_ty,
+                fn_arg,
+                term_location.to_locations(),
+                ConstraintCategory::CallArgument,
+            ) {
                 span_mirbug!(
                     self,
                     term,
@@ -1470,7 +1535,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     substs: tcx.mk_substs_trait(operand_ty, &[]),
                 };
 
-                self.prove_trait_ref(trait_ref, location.interesting());
+                self.prove_trait_ref(
+                    trait_ref,
+                    location.to_locations(),
+                    ConstraintCategory::CopyBound,
+                );
             },
 
             Rvalue::NullaryOp(_, ty) => {
@@ -1485,24 +1554,34 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     substs: tcx.mk_substs_trait(ty, &[]),
                 };
 
-                self.prove_trait_ref(trait_ref, location.interesting());
+                self.prove_trait_ref(
+                    trait_ref,
+                    location.to_locations(),
+                    ConstraintCategory::SizedBound,
+                );
             }
 
-            Rvalue::Cast(cast_kind, op, ty) => match cast_kind {
-                CastKind::ReifyFnPointer => {
-                    let fn_sig = op.ty(mir, tcx).fn_sig(tcx);
+            Rvalue::Cast(cast_kind, op, ty) => {
+                match cast_kind {
+                    CastKind::ReifyFnPointer => {
+                        let fn_sig = op.ty(mir, tcx).fn_sig(tcx);
 
-                    // The type that we see in the fcx is like
-                    // `foo::<'a, 'b>`, where `foo` is the path to a
-                    // function definition. When we extract the
-                    // signature, it comes from the `fn_sig` query,
-                    // and hence may contain unnormalized results.
-                    let fn_sig = self.normalize(fn_sig, location);
+                        // The type that we see in the fcx is like
+                        // `foo::<'a, 'b>`, where `foo` is the path to a
+                        // function definition. When we extract the
+                        // signature, it comes from the `fn_sig` query,
+                        // and hence may contain unnormalized results.
+                        let fn_sig = self.normalize(fn_sig, location);
 
-                    let ty_fn_ptr_from = tcx.mk_fn_ptr(fn_sig);
+                        let ty_fn_ptr_from = tcx.mk_fn_ptr(fn_sig);
 
-                    if let Err(terr) = self.eq_types(ty_fn_ptr_from, ty, location.interesting()) {
-                        span_mirbug!(
+                        if let Err(terr) = self.eq_types(
+                            ty_fn_ptr_from,
+                            ty,
+                            location.to_locations(),
+                            ConstraintCategory::Cast,
+                        ) {
+                            span_mirbug!(
                             self,
                             rvalue,
                             "equating {:?} with {:?} yields {:?}",
@@ -1510,20 +1589,25 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                             ty,
                             terr
                         );
+                        }
                     }
-                }
 
-                CastKind::ClosureFnPointer => {
-                    let sig = match op.ty(mir, tcx).sty {
-                        ty::Closure(def_id, substs) => {
-                            substs.closure_sig_ty(def_id, tcx).fn_sig(tcx)
-                        }
-                        _ => bug!(),
-                    };
-                    let ty_fn_ptr_from = tcx.coerce_closure_fn_ty(sig);
+                    CastKind::ClosureFnPointer => {
+                        let sig = match op.ty(mir, tcx).sty {
+                            ty::Closure(def_id, substs) => {
+                                substs.closure_sig_ty(def_id, tcx).fn_sig(tcx)
+                            }
+                            _ => bug!(),
+                        };
+                        let ty_fn_ptr_from = tcx.coerce_closure_fn_ty(sig);
 
-                    if let Err(terr) = self.eq_types(ty_fn_ptr_from, ty, location.interesting()) {
-                        span_mirbug!(
+                        if let Err(terr) = self.eq_types(
+                            ty_fn_ptr_from,
+                            ty,
+                            location.to_locations(),
+                            ConstraintCategory::Cast,
+                        ) {
+                            span_mirbug!(
                             self,
                             rvalue,
                             "equating {:?} with {:?} yields {:?}",
@@ -1531,23 +1615,28 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                             ty,
                             terr
                         );
+                        }
                     }
-                }
 
-                CastKind::UnsafeFnPointer => {
-                    let fn_sig = op.ty(mir, tcx).fn_sig(tcx);
+                    CastKind::UnsafeFnPointer => {
+                        let fn_sig = op.ty(mir, tcx).fn_sig(tcx);
 
-                    // The type that we see in the fcx is like
-                    // `foo::<'a, 'b>`, where `foo` is the path to a
-                    // function definition. When we extract the
-                    // signature, it comes from the `fn_sig` query,
-                    // and hence may contain unnormalized results.
-                    let fn_sig = self.normalize(fn_sig, location);
+                        // The type that we see in the fcx is like
+                        // `foo::<'a, 'b>`, where `foo` is the path to a
+                        // function definition. When we extract the
+                        // signature, it comes from the `fn_sig` query,
+                        // and hence may contain unnormalized results.
+                        let fn_sig = self.normalize(fn_sig, location);
 
-                    let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig);
+                        let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig);
 
-                    if let Err(terr) = self.eq_types(ty_fn_ptr_from, ty, location.interesting()) {
-                        span_mirbug!(
+                        if let Err(terr) = self.eq_types(
+                            ty_fn_ptr_from,
+                            ty,
+                            location.to_locations(),
+                            ConstraintCategory::Cast,
+                        ) {
+                            span_mirbug!(
                             self,
                             rvalue,
                             "equating {:?} with {:?} yields {:?}",
@@ -1555,21 +1644,26 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                             ty,
                             terr
                         );
+                        }
                     }
-                }
 
-                CastKind::Unsize => {
-                    let &ty = ty;
-                    let trait_ref = ty::TraitRef {
-                        def_id: tcx.lang_items().coerce_unsized_trait().unwrap(),
-                        substs: tcx.mk_substs_trait(op.ty(mir, tcx), &[ty.into()]),
-                    };
+                    CastKind::Unsize => {
+                        let &ty = ty;
+                        let trait_ref = ty::TraitRef {
+                            def_id: tcx.lang_items().coerce_unsized_trait().unwrap(),
+                            substs: tcx.mk_substs_trait(op.ty(mir, tcx), &[ty.into()]),
+                        };
 
-                    self.prove_trait_ref(trait_ref, location.interesting());
-                }
+                        self.prove_trait_ref(
+                            trait_ref,
+                            location.to_locations(),
+                            ConstraintCategory::Cast,
+                        );
+                    }
 
-                CastKind::Misc => {}
-            },
+                    CastKind::Misc => {}
+                }
+            }
 
             Rvalue::Ref(region, _borrow_kind, borrowed_place) => {
                 self.add_reborrow_constraint(location, region, borrowed_place);
@@ -1644,7 +1738,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             };
             let operand_ty = operand.ty(mir, tcx);
 
-            if let Err(terr) = self.sub_types(operand_ty, field_ty, location.boring()) {
+            if let Err(terr) = self.sub_types(
+                operand_ty,
+                field_ty,
+                location.to_locations(),
+                ConstraintCategory::Boring,
+            ) {
                 span_mirbug!(
                     self,
                     rvalue,
@@ -1723,7 +1822,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                             constraints.outlives_constraints.push(OutlivesConstraint {
                                 sup: ref_region.to_region_vid(),
                                 sub: borrow_region.to_region_vid(),
-                                locations: location.boring(),
+                                locations: location.to_locations(),
+                                category: ConstraintCategory::Boring,
                             });
 
                             if let Some(all_facts) = all_facts {
@@ -1839,8 +1939,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                         *substs,
                     );
 
-                    // Hmm, are these constraints *really* boring?
-                    self.push_region_constraints(location.boring(), &closure_constraints);
+                    self.push_region_constraints(
+                        location.to_locations(),
+                        ConstraintCategory::ClosureBounds,
+                        &closure_constraints,
+                    );
                 }
 
                 tcx.predicates_of(*def_id).instantiate(tcx, substs.substs)
@@ -1855,16 +1958,22 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
 
         self.normalize_and_prove_instantiated_predicates(
             instantiated_predicates,
-            location.boring(),
+            location.to_locations(),
         );
     }
 
-    fn prove_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>, locations: Locations) {
+    fn prove_trait_ref(
+        &mut self,
+        trait_ref: ty::TraitRef<'tcx>,
+        locations: Locations,
+        category: ConstraintCategory,
+    ) {
         self.prove_predicates(
             Some(ty::Predicate::Trait(
                 trait_ref.to_poly_trait_ref().to_poly_trait_predicate(),
             )),
             locations,
+            category,
         );
     }
 
@@ -1875,7 +1984,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     ) {
         for predicate in instantiated_predicates.predicates {
             let predicate = self.normalize(predicate, locations);
-            self.prove_predicate(predicate, locations);
+            self.prove_predicate(predicate, locations, ConstraintCategory::Boring);
         }
     }
 
@@ -1883,6 +1992,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         &mut self,
         predicates: impl IntoIterator<Item = ty::Predicate<'tcx>>,
         locations: Locations,
+        category: ConstraintCategory,
     ) {
         for predicate in predicates {
             debug!(
@@ -1890,11 +2000,16 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 predicate, locations,
             );
 
-            self.prove_predicate(predicate, locations);
+            self.prove_predicate(predicate, locations, category);
         }
     }
 
-    fn prove_predicate(&mut self, predicate: ty::Predicate<'tcx>, locations: Locations) {
+    fn prove_predicate(
+        &mut self,
+        predicate: ty::Predicate<'tcx>,
+        locations: Locations,
+        category: ConstraintCategory,
+    ) {
         debug!(
             "prove_predicate(predicate={:?}, location={:?})",
             predicate, locations,
@@ -1903,6 +2018,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         let param_env = self.param_env;
         self.fully_perform_op(
             locations,
+            category,
             param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)),
         ).unwrap_or_else(|NoSolution| {
             span_mirbug!(self, NoSolution, "could not prove {:?}", predicate);
@@ -1943,6 +2059,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         let param_env = self.param_env;
         self.fully_perform_op(
             location.to_locations(),
+            ConstraintCategory::Boring,
             param_env.and(type_op::normalize::Normalize::new(value)),
         ).unwrap_or_else(|NoSolution| {
             span_mirbug!(self, NoSolution, "failed to normalize `{:?}`", value);
@@ -1996,26 +2113,6 @@ impl MirPass for TypeckMir {
     }
 }
 
-pub trait AtLocation {
-    /// Indicates a "boring" constraint that the user probably
-    /// woudln't want to see highlights.
-    fn boring(self) -> Locations;
-
-    /// Indicates an "interesting" edge, which is of significance only
-    /// for diagnostics.
-    fn interesting(self) -> Locations;
-}
-
-impl AtLocation for Location {
-    fn boring(self) -> Locations {
-        Locations::Boring(self)
-    }
-
-    fn interesting(self) -> Locations {
-        Locations::Interesting(self)
-    }
-}
-
 trait NormalizeLocation: fmt::Debug + Copy {
     fn to_locations(self) -> Locations;
 }
@@ -2028,6 +2125,6 @@ impl NormalizeLocation for Locations {
 
 impl NormalizeLocation for Location {
     fn to_locations(self) -> Locations {
-        self.boring()
+        Locations::Single(self)
     }
 }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
index 06cb44ac971..130b4b31d08 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use borrow_check::nll::constraints::OutlivesConstraint;
+use borrow_check::nll::constraints::{ConstraintCategory, OutlivesConstraint};
 use borrow_check::nll::type_check::{BorrowCheckContext, Locations};
 use borrow_check::nll::universal_regions::UniversalRegions;
 use borrow_check::nll::ToRegionVid;
@@ -28,6 +28,7 @@ pub(super) fn sub_types<'tcx>(
     a: Ty<'tcx>,
     b: Ty<'tcx>,
     locations: Locations,
+    category: ConstraintCategory,
     borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
 ) -> Fallible<()> {
     debug!("sub_types(a={:?}, b={:?}, locations={:?})", a, b, locations);
@@ -35,6 +36,7 @@ pub(super) fn sub_types<'tcx>(
         infcx,
         ty::Variance::Covariant,
         locations,
+        category,
         borrowck_context,
         ty::List::empty(),
     ).relate(&a, &b)?;
@@ -47,6 +49,7 @@ pub(super) fn eq_types<'tcx>(
     a: Ty<'tcx>,
     b: Ty<'tcx>,
     locations: Locations,
+    category: ConstraintCategory,
     borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
 ) -> Fallible<()> {
     debug!("eq_types(a={:?}, b={:?}, locations={:?})", a, b, locations);
@@ -54,6 +57,7 @@ pub(super) fn eq_types<'tcx>(
         infcx,
         ty::Variance::Invariant,
         locations,
+        category,
         borrowck_context,
         ty::List::empty(),
     ).relate(&a, &b)?;
@@ -69,6 +73,7 @@ pub(super) fn relate_type_and_user_type<'tcx>(
     v: ty::Variance,
     b: CanonicalTy<'tcx>,
     locations: Locations,
+    category: ConstraintCategory,
     borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
 ) -> Fallible<()> {
     debug!(
@@ -89,6 +94,7 @@ pub(super) fn relate_type_and_user_type<'tcx>(
         infcx,
         v1,
         locations,
+        category,
         borrowck_context,
         b_variables,
     ).relate(&b_value, &a)?;
@@ -124,6 +130,8 @@ struct TypeRelating<'cx, 'bccx: 'cx, 'gcx: 'tcx, 'tcx: 'bccx> {
     /// Where (and why) is this relation taking place?
     locations: Locations,
 
+    category: ConstraintCategory,
+
     /// This will be `Some` when we are running the type check as part
     /// of NLL, and `None` if we are running a "sanity check".
     borrowck_context: Option<&'cx mut BorrowCheckContext<'bccx, 'tcx>>,
@@ -161,6 +169,7 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelating<'cx, 'bccx, 'gcx, 'tcx> {
         infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
         ambient_variance: ty::Variance,
         locations: Locations,
+        category: ConstraintCategory,
         borrowck_context: Option<&'cx mut BorrowCheckContext<'bccx, 'tcx>>,
         canonical_var_infos: CanonicalVarInfos<'tcx>,
     ) -> Self {
@@ -171,6 +180,7 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelating<'cx, 'bccx, 'gcx, 'tcx> {
             borrowck_context,
             locations,
             canonical_var_values,
+            category,
             a_scopes: vec![],
             b_scopes: vec![],
         }
@@ -264,6 +274,7 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelating<'cx, 'bccx, 'gcx, 'tcx> {
                     sup,
                     sub,
                     locations: self.locations,
+                    category: self.category,
                 });
 
             // FIXME all facts!
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index d2061d8eecf..f75ce7b0816 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -40,16 +40,44 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
     let id = tcx.hir.as_local_node_id(def_id).unwrap();
 
     // Figure out what primary body this item has.
-    let body_id = match tcx.hir.get(id) {
+    let (body_id, return_ty_span) = match tcx.hir.get(id) {
         Node::Variant(variant) =>
             return create_constructor_shim(tcx, id, &variant.node.data),
         Node::StructCtor(ctor) =>
             return create_constructor_shim(tcx, id, ctor),
 
-        _ => match tcx.hir.maybe_body_owned_by(id) {
-            Some(body) => body,
-            None => span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id),
-        },
+        Node::Expr(hir::Expr { node: hir::ExprKind::Closure(_, decl, body_id, _, _), .. })
+        | Node::Item(hir::Item { node: hir::ItemKind::Fn(decl, _, _, body_id), .. })
+        | Node::ImplItem(
+            hir::ImplItem {
+                node: hir::ImplItemKind::Method(hir::MethodSig { decl, .. }, body_id),
+                ..
+            }
+        )
+        | Node::TraitItem(
+            hir::TraitItem {
+                node: hir::TraitItemKind::Method(
+                    hir::MethodSig { decl, .. },
+                    hir::TraitMethod::Provided(body_id),
+                ),
+                ..
+            }
+        ) => {
+            (*body_id, decl.output.span())
+        }
+        Node::Item(hir::Item { node: hir::ItemKind::Static(ty, _, body_id), .. })
+        | Node::Item(hir::Item { node: hir::ItemKind::Const(ty, body_id), .. })
+        | Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Const(ty, body_id), .. })
+        | Node::TraitItem(
+            hir::TraitItem { node: hir::TraitItemKind::Const(ty, Some(body_id)), .. }
+        ) => {
+            (*body_id, ty.span)
+        }
+        Node::AnonConst(hir::AnonConst { body, id, .. }) => {
+            (*body, tcx.hir.span(*id))
+        }
+
+        _ => span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id),
     };
 
     tcx.infer_ctxt().enter(|infcx| {
@@ -124,9 +152,9 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
             };
 
             build::construct_fn(cx, id, arguments, safety, abi,
-                                return_ty, yield_ty, body)
+                                return_ty, yield_ty, return_ty_span, body)
         } else {
-            build::construct_const(cx, body_id)
+            build::construct_const(cx, body_id, return_ty_span)
         };
 
         // Convert the Mir to global types.
@@ -494,6 +522,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
                                    abi: Abi,
                                    return_ty: Ty<'gcx>,
                                    yield_ty: Option<Ty<'gcx>>,
+                                   return_ty_span: Span,
                                    body: &'gcx hir::Body)
                                    -> Mir<'tcx>
     where A: Iterator<Item=ArgInfo<'gcx>>
@@ -547,6 +576,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
         arguments.len(),
         safety,
         return_ty,
+        return_ty_span,
         upvar_decls);
 
     let fn_def_id = tcx.hir.local_def_id(fn_id);
@@ -601,15 +631,17 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
     mir
 }
 
-fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
-                                   body_id: hir::BodyId)
-                                   -> Mir<'tcx> {
+fn construct_const<'a, 'gcx, 'tcx>(
+    hir: Cx<'a, 'gcx, 'tcx>,
+    body_id: hir::BodyId,
+    ty_span: Span,
+) -> Mir<'tcx> {
     let tcx = hir.tcx();
     let ast_expr = &tcx.hir.body(body_id).value;
     let ty = hir.tables().expr_ty_adjusted(ast_expr);
     let owner_id = tcx.hir.body_owner(body_id);
     let span = tcx.hir.span(owner_id);
-    let mut builder = Builder::new(hir.clone(), span, 0, Safety::Safe, ty, vec![]);
+    let mut builder = Builder::new(hir.clone(), span, 0, Safety::Safe, ty, ty_span,vec![]);
 
     let mut block = START_BLOCK;
     let expr = builder.hir.mirror(ast_expr);
@@ -637,7 +669,7 @@ fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
     let owner_id = hir.tcx().hir.body_owner(body_id);
     let span = hir.tcx().hir.span(owner_id);
     let ty = hir.tcx().types.err;
-    let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, vec![]);
+    let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, vec![]);
     let source_info = builder.source_info(span);
     builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
     builder.finish(None)
@@ -649,6 +681,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
            arg_count: usize,
            safety: Safety,
            return_ty: Ty<'tcx>,
+           return_span: Span,
            upvar_decls: Vec<UpvarDecl>)
            -> Builder<'a, 'gcx, 'tcx> {
         let lint_level = LintLevel::Explicit(hir.root_lint_level);
@@ -665,8 +698,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             push_unsafe_count: 0,
             unpushed_unsafe: safety,
             breakable_scopes: vec![],
-            local_decls: IndexVec::from_elem_n(LocalDecl::new_return_place(return_ty,
-                                                                             span), 1),
+            local_decls: IndexVec::from_elem_n(
+                LocalDecl::new_return_place(return_ty, return_span),
+                1,
+            ),
             upvar_decls,
             var_indices: NodeMap(),
             unit_temp: None,
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr
index b61ea27ebe1..044a3f70b4a 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr
@@ -1,23 +1,24 @@
 error: unsatisfied lifetime constraints
-  --> $DIR/project-fn-ret-contravariant.rs:53:12
+  --> $DIR/project-fn-ret-contravariant.rs:55:4
    |
 LL | fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
    |              -- -- lifetime `'b` defined here
    |              |
    |              lifetime `'a` defined here
-LL |    let a = bar(foo, y);
-   |            ^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
+...
+LL |    (a, b) //[krisskross]~ ERROR 55:5: 55:6: lifetime mismatch [E0623]
+   |    ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
 
 error: unsatisfied lifetime constraints
-  --> $DIR/project-fn-ret-contravariant.rs:54:12
+  --> $DIR/project-fn-ret-contravariant.rs:55:4
    |
 LL | fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
    |              -- -- lifetime `'b` defined here
    |              |
    |              lifetime `'a` defined here
-LL |    let a = bar(foo, y);
-LL |    let b = bar(foo, x);
-   |            ^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
+...
+LL |    (a, b) //[krisskross]~ ERROR 55:5: 55:6: lifetime mismatch [E0623]
+   |    ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr
index 2f632fec17e..10f70b525e0 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr
@@ -14,7 +14,7 @@ LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
    |        |
    |        lifetime `'a` defined here
 LL |    bar(foo, x) //[transmute]~ ERROR E0495
-   |    ^^^^^^^^^^^ requires that `'a` must outlive `'b`
+   |    ^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr
index 971448997e3..1cb68785694 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr
@@ -1,23 +1,24 @@
 error: unsatisfied lifetime constraints
-  --> $DIR/project-fn-ret-invariant.rs:63:12
+  --> $DIR/project-fn-ret-invariant.rs:65:4
    |
 LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
    |              -- -- lifetime `'b` defined here
    |              |
    |              lifetime `'a` defined here
-LL |    let a = bar(foo, y); //[krisskross]~ ERROR E0623
-   |            ^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
+...
+LL |    (a, b) //[krisskross]~ ERROR E0623
+   |    ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
 
 error: unsatisfied lifetime constraints
-  --> $DIR/project-fn-ret-invariant.rs:64:12
+  --> $DIR/project-fn-ret-invariant.rs:65:4
    |
 LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
    |              -- -- lifetime `'b` defined here
    |              |
    |              lifetime `'a` defined here
-LL |    let a = bar(foo, y); //[krisskross]~ ERROR E0623
-LL |    let b = bar(foo, x);
-   |            ^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
+...
+LL |    (a, b) //[krisskross]~ ERROR E0623
+   |    ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr
index 63e1f665005..2329adb5dea 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr
@@ -8,7 +8,7 @@ LL |    bar(foo, x) //[transmute]~ ERROR E0495
    |    ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
 
 error: unsatisfied lifetime constraints
-  --> $DIR/project-fn-ret-invariant.rs:58:13
+  --> $DIR/project-fn-ret-invariant.rs:58:4
    |
 LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> {
    |        -- -- lifetime `'b` defined here
@@ -16,7 +16,7 @@ LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> {
    |        lifetime `'a` defined here
 ...
 LL |    bar(foo, x) //[transmute]~ ERROR E0495
-   |             ^ requires that `'a` must outlive `'b`
+   |    ^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
index b156e5a9731..5803b5e355a 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
@@ -5,10 +5,10 @@ LL |     const fn into_inner(self) -> T { self.0 } //~ destructors cannot be eva
    |                         ^^^^ constant functions cannot evaluate destructors
 
 error: mutable references in const fn are unstable
-  --> $DIR/min_const_fn.rs:51:5
+  --> $DIR/min_const_fn.rs:51:36
    |
 LL |     const fn get_mut(&mut self) -> &mut T { &mut self.0 }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                    ^^^^^^
 
 error[E0493]: destructors cannot be evaluated at compile-time
   --> $DIR/min_const_fn.rs:56:28
@@ -17,10 +17,10 @@ LL |     const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be
    |                            ^^^^ constant functions cannot evaluate destructors
 
 error: mutable references in const fn are unstable
-  --> $DIR/min_const_fn.rs:58:5
+  --> $DIR/min_const_fn.rs:58:42
    |
 LL |     const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                          ^^^^^^
 
 error[E0493]: destructors cannot be evaluated at compile-time
   --> $DIR/min_const_fn.rs:63:27
@@ -29,16 +29,16 @@ LL |     const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors
    |                           ^^^^ constant functions cannot evaluate destructors
 
 error: mutable references in const fn are unstable
-  --> $DIR/min_const_fn.rs:65:5
+  --> $DIR/min_const_fn.rs:65:38
    |
 LL |     const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                      ^^^^^^
 
 error: mutable references in const fn are unstable
-  --> $DIR/min_const_fn.rs:70:5
+  --> $DIR/min_const_fn.rs:70:39
    |
 LL |     const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                       ^^^^^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:88:16
@@ -155,10 +155,10 @@ LL | impl<T: Sync + Sized> Foo<T> {
    |      ^
 
 error: `impl Trait` in const fn is unstable
-  --> $DIR/min_const_fn.rs:137:1
+  --> $DIR/min_const_fn.rs:137:24
    |
 LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:139:34
@@ -173,10 +173,10 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other
    |                      ^^^^^^^^^^^^^^^^^^^^
 
 error: `impl Trait` in const fn is unstable
-  --> $DIR/min_const_fn.rs:142:1
+  --> $DIR/min_const_fn.rs:142:23
    |
 LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:143:23
@@ -185,10 +185,10 @@ LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds o
    |                       ^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:144:1
+  --> $DIR/min_const_fn.rs:144:32
    |
 LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0597]: borrowed value does not live long enough
   --> $DIR/min_const_fn.rs:144:64
@@ -213,10 +213,10 @@ LL | const fn no_fn_ptrs(_x: fn()) {}
    |                     ^^
 
 error: function pointers in const fn are unstable
-  --> $DIR/min_const_fn.rs:154:1
+  --> $DIR/min_const_fn.rs:154:27
    |
 LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                           ^^^^
 
 error: aborting due to 36 previous errors
 
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
index 019948c31b1..6779b8a7614 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
@@ -5,10 +5,10 @@ LL |     const fn into_inner(self) -> T { self.0 } //~ destructors cannot be eva
    |                         ^^^^ constant functions cannot evaluate destructors
 
 error: mutable references in const fn are unstable
-  --> $DIR/min_const_fn.rs:51:5
+  --> $DIR/min_const_fn.rs:51:36
    |
 LL |     const fn get_mut(&mut self) -> &mut T { &mut self.0 }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                    ^^^^^^
 
 error[E0493]: destructors cannot be evaluated at compile-time
   --> $DIR/min_const_fn.rs:56:28
@@ -17,10 +17,10 @@ LL |     const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be
    |                            ^^^^ constant functions cannot evaluate destructors
 
 error: mutable references in const fn are unstable
-  --> $DIR/min_const_fn.rs:58:5
+  --> $DIR/min_const_fn.rs:58:42
    |
 LL |     const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                          ^^^^^^
 
 error[E0493]: destructors cannot be evaluated at compile-time
   --> $DIR/min_const_fn.rs:63:27
@@ -29,16 +29,16 @@ LL |     const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors
    |                           ^^^^ constant functions cannot evaluate destructors
 
 error: mutable references in const fn are unstable
-  --> $DIR/min_const_fn.rs:65:5
+  --> $DIR/min_const_fn.rs:65:38
    |
 LL |     const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                      ^^^^^^
 
 error: mutable references in const fn are unstable
-  --> $DIR/min_const_fn.rs:70:5
+  --> $DIR/min_const_fn.rs:70:39
    |
 LL |     const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                       ^^^^^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:88:16
@@ -155,10 +155,10 @@ LL | impl<T: Sync + Sized> Foo<T> {
    |      ^
 
 error: `impl Trait` in const fn is unstable
-  --> $DIR/min_const_fn.rs:137:1
+  --> $DIR/min_const_fn.rs:137:24
    |
 LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:139:34
@@ -173,10 +173,10 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other
    |                      ^^^^^^^^^^^^^^^^^^^^
 
 error: `impl Trait` in const fn is unstable
-  --> $DIR/min_const_fn.rs:142:1
+  --> $DIR/min_const_fn.rs:142:23
    |
 LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:143:23
@@ -185,10 +185,10 @@ LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds o
    |                       ^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:144:1
+  --> $DIR/min_const_fn.rs:144:32
    |
 LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:149:41
@@ -203,10 +203,10 @@ LL | const fn no_fn_ptrs(_x: fn()) {}
    |                     ^^
 
 error: function pointers in const fn are unstable
-  --> $DIR/min_const_fn.rs:154:1
+  --> $DIR/min_const_fn.rs:154:27
    |
 LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                           ^^^^
 
 error: aborting due to 35 previous errors
 
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
index 3019e3aa1f7..485d3566244 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
@@ -36,10 +36,10 @@ LL |     move |_| println!("{}", y)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:34:5
+  --> $DIR/must_outlive_least_region_or_bound.rs:32:51
    |
-LL |     x
-   |     ^
+LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
+   |                                                   ^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `T: 'static`...
 
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr
index 4bc8876c232..7e9aa90c6c5 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr
@@ -4,7 +4,7 @@ error: unsatisfied lifetime constraints
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
    |                         - let's call the lifetime of this reference `'1`
 LL |         self.x.iter().map(|a| a.0)
-   |         ^^^^^^ cast requires that `'1` must outlive `'static`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
 help: to allow this impl Trait to capture borrowed data with lifetime `'1`, add `'_` as a constraint
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
@@ -16,7 +16,7 @@ error: unsatisfied lifetime constraints
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
    |                    -- lifetime `'a` defined here
 LL |         self.x.iter().map(|a| a.0)
-   |         ^^^^^^ cast requires that `'a` must outlive `'static`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
 help: to allow this impl Trait to capture borrowed data with lifetime `'a`, add `'a` as a constraint
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
diff --git a/src/test/ui/impl-trait/type_parameters_captured.nll.stderr b/src/test/ui/impl-trait/type_parameters_captured.nll.stderr
index 3c2c86fffde..18258ef1f9d 100644
--- a/src/test/ui/impl-trait/type_parameters_captured.nll.stderr
+++ b/src/test/ui/impl-trait/type_parameters_captured.nll.stderr
@@ -1,8 +1,8 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/type_parameters_captured.rs:19:5
+  --> $DIR/type_parameters_captured.rs:17:20
    |
-LL |     x
-   |     ^
+LL | fn foo<T>(x: T) -> impl Any + 'static {
+   |                    ^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `T: 'static`...
 
diff --git a/src/test/ui/issues/issue-10291.nll.stderr b/src/test/ui/issues/issue-10291.nll.stderr
index d19c4d880c7..201a3b3d54a 100644
--- a/src/test/ui/issues/issue-10291.nll.stderr
+++ b/src/test/ui/issues/issue-10291.nll.stderr
@@ -1,10 +1,13 @@
 error: unsatisfied lifetime constraints
-  --> $DIR/issue-10291.rs:12:5
+  --> $DIR/issue-10291.rs:12:65
    |
-LL | fn test<'x>(x: &'x isize) {
-   |         -- lifetime `'x` defined here
-LL |     drop::<Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
+LL | |     }));
+   | |_____^ closure body requires that `'x` must outlive `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr
index 017c3e97747..e4aafd7b66e 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr
@@ -6,7 +6,7 @@ LL | fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) {
    |                                   |
    |                                   let's call the lifetime of this reference `'2`
 LL |     *v = x; //~ ERROR lifetime mismatch
-   |     ^^^^^^ requires that `'1` must outlive `'2`
+   |     ^^^^^^ assignment requires that `'1` must outlive `'2`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr
index b8e1b483081..934cdcd2ef2 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr
@@ -6,7 +6,7 @@ LL | fn foo(mut x: Ref, y: Ref) {
    |        |
    |        has type `Ref<'_, '2>`
 LL |     x.b = y.b; //~ ERROR lifetime mismatch
-   |     ^^^^^^^^^ requires that `'1` must outlive `'2`
+   |     ^^^^^^^^^ assignment requires that `'1` must outlive `'2`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr
index 4b7352fe224..cbfd9d47809 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr
@@ -7,7 +7,7 @@ LL | fn foo(mut x: Ref) {
    |        has type `Ref<'_, '1>`
    |        has type `Ref<'2, '_>`
 LL |     x.a = x.b; //~ ERROR lifetime mismatch
-   |     ^^^^^^^^^ requires that `'1` must outlive `'2`
+   |     ^^^^^^^^^ assignment requires that `'1` must outlive `'2`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr
index 53a2fef4806..4f0efe24cf7 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr
@@ -7,7 +7,7 @@ LL | fn foo(mut x: Ref) {
    |        has type `Ref<'_, '1>`
    |        has type `Ref<'2, '_>`
 LL |     x.a = x.b; //~ ERROR lifetime mismatch
-   |     ^^^^^^^^^ requires that `'1` must outlive `'2`
+   |     ^^^^^^^^^ assignment requires that `'1` must outlive `'2`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr
index 1a5f788e143..fc1fab7aab5 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr
@@ -6,7 +6,7 @@ LL | fn foo(mut x: Ref, y: &u32) {
    |        |
    |        has type `Ref<'_, '1>`
 LL |     y = x.b; //~ ERROR lifetime mismatch
-   |     ^^^^^^^ requires that `'1` must outlive `'2`
+   |     ^^^^^^^ assignment requires that `'1` must outlive `'2`
 
 error[E0384]: cannot assign to immutable argument `y`
   --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:5
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr
index d098354d983..8100fa89c2d 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr
@@ -6,7 +6,7 @@ LL | fn foo(mut y: Ref, x: &u32) {
    |        |
    |        has type `Ref<'_, '2>`
 LL |     y.b = x; //~ ERROR lifetime mismatch
-   |     ^^^^^^^ requires that `'1` must outlive `'2`
+   |     ^^^^^^^ assignment requires that `'1` must outlive `'2`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr
index 17a70aa85be..1c4a8b66589 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr
@@ -6,7 +6,7 @@ LL | fn foo(mut y: Ref, x: &u32) {
    |        |
    |        has type `Ref<'_, '2>`
 LL |     y.b = x; //~ ERROR lifetime mismatch
-   |     ^^^^^^^ requires that `'1` must outlive `'2`
+   |     ^^^^^^^ assignment requires that `'1` must outlive `'2`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr
index 2ebdedddc50..2a4c5a685f1 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr
@@ -6,7 +6,7 @@ LL | fn foo(mut x: Ref, y: &u32) {
    |        |
    |        has type `Ref<'_, '2>`
 LL |     x.b = y; //~ ERROR lifetime mismatch
-   |     ^^^^^^^ requires that `'1` must outlive `'2`
+   |     ^^^^^^^ assignment requires that `'1` must outlive `'2`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
index 72b60188c4c..1f9cb6d050f 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -13,7 +13,7 @@ error: unsatisfied lifetime constraints
   --> $DIR/escape-argument-callee.rs:36:45
    |
 LL |         let mut closure = expect_sig(|p, y| *p = y);
-   |                                       -  -  ^^^^^^ requires that `'1` must outlive `'2`
+   |                                       -  -  ^^^^^^ assignment requires that `'1` must outlive `'2`
    |                                       |  |
    |                                       |  has type `&'1 i32`
    |                                       has type `&mut &'2 i32`
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 1af96b97e73..2e1249a5e81 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -34,19 +34,20 @@ 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:5
+  --> $DIR/propagate-approximated-ref.rs:53:47
    |
 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 |       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 | |     });
-   | |______^ argument requires that `'a` must outlive `'b`
+   | |_____^ closure body 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.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
index 9de9e21ba43..9f1d9d21d11 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
@@ -49,14 +49,21 @@ LL | |     });
    | |______^ `cell_a` escapes the function body here
 
 error: unsatisfied lifetime constraints
-  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:29
+  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:47
    |
-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| {
-   |                             ^^^^^^^ 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 |       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`
 
 error: aborting due to 2 previous errors
 
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 6acb6750055..4e72fe4bb28 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
@@ -47,14 +47,20 @@ LL | |     });
    | |______^ `cell_a` escapes the function body here
 
 error: unsatisfied lifetime constraints
-  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:29
+  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:47
    |
-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| {
-   |                             ^^^^^^^ 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 |       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`
 
 error: aborting due to 2 previous errors
 
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 e0902ca1ddb..de60b23ef6b 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -34,19 +34,20 @@ 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:5
+  --> $DIR/propagate-approximated-val.rs:46:45
    |
 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 |       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 | |     });
-   | |______^ argument requires that `'a` must outlive `'b`
+   | |_____^ closure body requires that `'a` must outlive `'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/issue-50716.stderr b/src/test/ui/nll/issue-50716.stderr
index f12ab9b4f96..eddad056995 100644
--- a/src/test/ui/nll/issue-50716.stderr
+++ b/src/test/ui/nll/issue-50716.stderr
@@ -1,11 +1,11 @@
-error: borrowed data escapes outside of function
+error: unsatisfied lifetime constraints
   --> $DIR/issue-50716.rs:25:14
    |
 LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>)
-   |                        - `s` is a reference that is only valid in the function body
+   |        -- lifetime `'a` defined here
 ...
 LL |     let _x = *s; //~ ERROR
-   |              ^^ `s` escapes the function body here
+   |              ^^ proving this value is `Sized` requires that `'a` must outlive `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/issue-52113.rs b/src/test/ui/nll/issue-52113.rs
index e484c249d84..af577e8499b 100644
--- a/src/test/ui/nll/issue-52113.rs
+++ b/src/test/ui/nll/issue-52113.rs
@@ -40,11 +40,11 @@ fn produce3<'a, 'b: 'a>(data: &'a mut Vec<&'a u32>, value: &'b u32) -> impl Bazi
 }
 
 fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
-    let x = move || { //~ ERROR unsatisfied lifetime constraints
+    let x = move || {
         let value: &'a u32 = value;
         data.push(value);
     };
-    x
+    x   //~ ERROR unsatisfied lifetime constraints
 }
 
 fn main() { }
diff --git a/src/test/ui/nll/issue-52113.stderr b/src/test/ui/nll/issue-52113.stderr
index b21539361e6..45a192de454 100644
--- a/src/test/ui/nll/issue-52113.stderr
+++ b/src/test/ui/nll/issue-52113.stderr
@@ -1,12 +1,13 @@
 error: unsatisfied lifetime constraints
-  --> $DIR/issue-52113.rs:43:9
+  --> $DIR/issue-52113.rs:47:5
    |
 LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
    |                --  -- lifetime `'b` defined here
    |                |
    |                lifetime `'a` defined here
-LL |     let x = move || { //~ ERROR unsatisfied lifetime constraints
-   |         ^ requires that `'a` must outlive `'b`
+...
+LL |     x   //~ ERROR unsatisfied lifetime constraints
+   |     ^ returning this value requires that `'a` must outlive `'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/issue-52742.stderr b/src/test/ui/nll/issue-52742.stderr
index 515ba55cf6f..83a594941c0 100644
--- a/src/test/ui/nll/issue-52742.stderr
+++ b/src/test/ui/nll/issue-52742.stderr
@@ -6,7 +6,7 @@ LL |     fn take_bar(&mut self, b: Bar<'_>) {
    |                 |
    |                 has type `&mut Foo<'_, '2>`
 LL |         self.y = b.z
-   |         ^^^^^^^^^^^^ requires that `'1` must outlive `'2`
+   |         ^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/mir_check_cast_reify.rs b/src/test/ui/nll/mir_check_cast_reify.rs
index 332ec7a7da2..c878be9e2a2 100644
--- a/src/test/ui/nll/mir_check_cast_reify.rs
+++ b/src/test/ui/nll/mir_check_cast_reify.rs
@@ -44,8 +44,8 @@ fn bar<'a>(x: &'a u32) -> &'static u32 {
     // The MIR type checker must therefore relate `'?0` to `'?1` and `'?2`
     // as part of checking the `ReifyFnPointer`.
     let f: fn(_) -> _ = foo;
-    //~^ ERROR unsatisfied lifetime constraints
     f(x)
+    //~^ ERROR unsatisfied lifetime constraints
 }
 
 fn main() {}
diff --git a/src/test/ui/nll/mir_check_cast_reify.stderr b/src/test/ui/nll/mir_check_cast_reify.stderr
index fa5c4100c91..fdb71b17287 100644
--- a/src/test/ui/nll/mir_check_cast_reify.stderr
+++ b/src/test/ui/nll/mir_check_cast_reify.stderr
@@ -1,11 +1,11 @@
 error: unsatisfied lifetime constraints
-  --> $DIR/mir_check_cast_reify.rs:46:25
+  --> $DIR/mir_check_cast_reify.rs:47:5
    |
 LL | fn bar<'a>(x: &'a u32) -> &'static u32 {
    |        -- lifetime `'a` defined here
 ...
-LL |     let f: fn(_) -> _ = foo;
-   |                         ^^^ cast requires that `'a` must outlive `'static`
+LL |     f(x)
+   |     ^^^^ returning this value requires that `'a` must outlive `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/mir_check_cast_unsafe_fn.rs b/src/test/ui/nll/mir_check_cast_unsafe_fn.rs
index 937ab31c315..be91a946857 100644
--- a/src/test/ui/nll/mir_check_cast_unsafe_fn.rs
+++ b/src/test/ui/nll/mir_check_cast_unsafe_fn.rs
@@ -16,8 +16,8 @@ fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 {
     // Here the NLL checker must relate the types in `f` to the types
     // in `g`. These are related via the `UnsafeFnPointer` cast.
     let g: unsafe fn(_) -> _ = f;
-    //~^ ERROR unsatisfied lifetime constraints
     unsafe { g(input) }
+    //~^ ERROR unsatisfied lifetime constraints
 }
 
 fn main() {}
diff --git a/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr
index 82ff71c0551..c14fb93a525 100644
--- a/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr
+++ b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr
@@ -1,11 +1,11 @@
 error: unsatisfied lifetime constraints
-  --> $DIR/mir_check_cast_unsafe_fn.rs:18:32
+  --> $DIR/mir_check_cast_unsafe_fn.rs:19:14
    |
 LL | fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 {
    |        -- lifetime `'a` defined here
 ...
-LL |     let g: unsafe fn(_) -> _ = f;
-   |                                ^ cast requires that `'a` must outlive `'static`
+LL |     unsafe { g(input) }
+   |              ^^^^^^^^ returning this value requires that `'a` must outlive `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/mir_check_cast_unsize.stderr b/src/test/ui/nll/mir_check_cast_unsize.stderr
index 77a2e8311f0..526dfb60133 100644
--- a/src/test/ui/nll/mir_check_cast_unsize.stderr
+++ b/src/test/ui/nll/mir_check_cast_unsize.stderr
@@ -4,7 +4,7 @@ error: unsatisfied lifetime constraints
 LL | fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
    |        -- lifetime `'a` defined here
 LL |     x
-   |     ^ cast requires that `'a` must outlive `'static`
+   |     ^ returning this value requires that `'a` must outlive `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr
index c9195395b87..9a83872b965 100644
--- a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr
+++ b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr
@@ -5,10 +5,10 @@ LL |     let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
    |                                                          ^^^^^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/hr-fn-aaa-as-aba.rs:32:58
+  --> $DIR/hr-fn-aaa-as-aba.rs:32:9
    |
 LL |     let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
-   |                                                          ^^^^^^^^^
+   |         ^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs
index 43666365892..64eb7353638 100644
--- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs
+++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs
@@ -15,11 +15,11 @@
 use std::fmt::Debug;
 
 fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
+    //~^ ERROR the parameter type `T` may not live long enough [E0309]
 where
     T: Debug,
 {
     x
-    //~^ ERROR the parameter type `T` may not live long enough [E0309]
 }
 
 fn correct_region<'a, T>(x: Box<T>) -> impl Debug + 'a
@@ -30,11 +30,11 @@ where
 }
 
 fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
+    //~^ ERROR the parameter type `T` may not live long enough [E0309]
 where
     T: 'b + Debug,
 {
     x
-    //~^ ERROR the parameter type `T` may not live long enough [E0309]
 }
 
 fn outlives_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr
index 05b674f8a9d..61d2d2d6d82 100644
--- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr
+++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr
@@ -1,16 +1,16 @@
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/impl-trait-outlives.rs:21:5
+  --> $DIR/impl-trait-outlives.rs:17:35
    |
-LL |     x
-   |     ^
+LL | fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
+   |                                   ^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/impl-trait-outlives.rs:36:5
+  --> $DIR/impl-trait-outlives.rs:32:42
    |
-LL |     x
-   |     ^
+LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
+   |                                          ^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
 
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 a91761f3ece..4bd96ab4e71 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
@@ -32,8 +32,16 @@ LL | | }
                T
            ]
 
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/projection-one-region-closure.rs:55:29
+   |
+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:5
+  --> $DIR/projection-one-region-closure.rs:55:29
    |
 LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                          --  -- lifetime `'b` defined here
@@ -41,15 +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));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
-
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:55:29
-   |
-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))`...
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
 
 note: External requirements
   --> $DIR/projection-one-region-closure.rs:66:29
@@ -86,8 +86,16 @@ LL | | }
                T
            ]
 
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/projection-one-region-closure.rs:66:29
+   |
+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:5
+  --> $DIR/projection-one-region-closure.rs:66:29
    |
 LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                           --  -- lifetime `'b` defined here
@@ -95,15 +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));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
-
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:66:29
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
 
 note: External requirements
   --> $DIR/projection-one-region-closure.rs:87:29
@@ -140,8 +140,16 @@ LL | | }
                T
            ]
 
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/projection-one-region-closure.rs:87:29
+   |
+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:87:5
+  --> $DIR/projection-one-region-closure.rs:87:29
    |
 LL | fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                        --  -- lifetime `'b` defined here
@@ -149,15 +157,7 @@ LL | fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                        lifetime `'a` defined here
 ...
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
-
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:87:29
-   |
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
 
 note: External requirements
   --> $DIR/projection-one-region-closure.rs:99: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 0064393f271..ccf70a77bff 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:5
+  --> $DIR/projection-one-region-trait-bound-closure.rs:47:29
    |
 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));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body 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:5
+  --> $DIR/projection-one-region-trait-bound-closure.rs:57:29
    |
 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));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
 
 note: External requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:77:29
@@ -122,7 +122,7 @@ LL | | }
            ]
 
 error: unsatisfied lifetime constraints
-  --> $DIR/projection-one-region-trait-bound-closure.rs:77:5
+  --> $DIR/projection-one-region-trait-bound-closure.rs:77:29
    |
 LL | fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                        --  -- lifetime `'b` defined here
@@ -130,7 +130,7 @@ LL | fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                        lifetime `'a` defined here
 ...
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
 
 note: External requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:87:29
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 19dcb5f93da..372b803082f 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
@@ -235,7 +235,7 @@ LL | | }
            ]
 
 error: unsatisfied lifetime constraints
-  --> $DIR/projection-two-region-trait-bound-closure.rs:105:5
+  --> $DIR/projection-two-region-trait-bound-closure.rs:105:29
    |
 LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                --  -- lifetime `'b` defined here
@@ -243,7 +243,7 @@ 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));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
 
 note: External requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:115:29
diff --git a/src/test/ui/nll/type-alias-free-regions.rs b/src/test/ui/nll/type-alias-free-regions.rs
new file mode 100644
index 00000000000..6e480dcaac0
--- /dev/null
+++ b/src/test/ui/nll/type-alias-free-regions.rs
@@ -0,0 +1,33 @@
+// Test that we don't assume that type aliases have the same type parameters
+// as the type they alias and then panic when we see this.
+
+#![feature(nll)]
+
+type a<'a> = &'a isize;
+type b<'a> = Box<a<'a>>;
+
+struct c<'a> {
+    f: Box<b<'a>>
+}
+
+trait FromBox<'a> {
+    fn from_box(b: Box<b>) -> Self;
+}
+
+impl<'a> FromBox<'a> for c<'a> {
+    fn from_box(b: Box<b>) -> Self {
+        c { f: b } //~ ERROR
+    }
+}
+
+trait FromTuple<'a> {
+    fn from_tuple( b: (b,)) -> Self;
+}
+
+impl<'a> FromTuple<'a> for c<'a> {
+    fn from_tuple(b: (b,)) -> Self {
+        c { f: Box::new(b.0) } //~ ERROR
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/type-alias-free-regions.stderr b/src/test/ui/nll/type-alias-free-regions.stderr
new file mode 100644
index 00000000000..05f2c930944
--- /dev/null
+++ b/src/test/ui/nll/type-alias-free-regions.stderr
@@ -0,0 +1,22 @@
+error: unsatisfied lifetime constraints
+  --> $DIR/type-alias-free-regions.rs:19:9
+   |
+LL | impl<'a> FromBox<'a> for c<'a> {
+   |      -- lifetime `'a` defined here
+LL |     fn from_box(b: Box<b>) -> Self {
+   |                 - has type `std::boxed::Box<std::boxed::Box<&'1 isize>>`
+LL |         c { f: b } //~ ERROR
+   |         ^^^^^^^^^^ returning this value requires that `'1` must outlive `'a`
+
+error: unsatisfied lifetime constraints
+  --> $DIR/type-alias-free-regions.rs:29:9
+   |
+LL | impl<'a> FromTuple<'a> for c<'a> {
+   |      -- lifetime `'a` defined here
+LL |     fn from_tuple(b: (b,)) -> Self {
+   |                   - has type `(std::boxed::Box<&'1 isize>,)`
+LL |         c { f: Box::new(b.0) } //~ ERROR
+   |         ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'a`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/nll/user-annotations/patterns.stderr b/src/test/ui/nll/user-annotations/patterns.stderr
index 563de1a9e02..f359608462d 100644
--- a/src/test/ui/nll/user-annotations/patterns.stderr
+++ b/src/test/ui/nll/user-annotations/patterns.stderr
@@ -131,12 +131,12 @@ LL |     y //~ ERROR
    |     ^ returning this value requires that `'a` must outlive `'static`
 
 error: unsatisfied lifetime constraints
-  --> $DIR/patterns.rs:117:40
+  --> $DIR/patterns.rs:117:9
    |
 LL | fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 {
    |                            -- lifetime `'a` defined here
 LL |     let (y, _z): (&'static u32, u32) = (x, 44); //~ ERROR
-   |                                        ^^^^^^^ requires that `'a` must outlive `'static`
+   |         ^^^^^^^ type annotation requires that `'a` must outlive `'static`
 
 error: aborting due to 14 previous errors
 
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr
index e62b9b07021..a6bfcf1d369 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr
@@ -1,10 +1,10 @@
-error: borrowed data escapes outside of function
+error: unsatisfied lifetime constraints
   --> $DIR/object-lifetime-default-from-rptr-box-error.rs:25:5
    |
 LL | fn c<'a>(t: &'a Box<Test+'a>, mut ss: SomeStruct<'a>) {
-   |          - `t` is a reference that is only valid in the function body
+   |      -- lifetime `'a` defined here
 LL |     ss.t = t; //~ ERROR mismatched types
-   |     ^^^^^^^^ `t` escapes the function body here
+   |     ^^^^^^^^ assignment requires that `'a` must outlive `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr
index 803f9d3fd7e..396ff1302b1 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr
@@ -1,10 +1,10 @@
-error: borrowed data escapes outside of function
+error: unsatisfied lifetime constraints
   --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:31:5
    |
 LL | fn c<'a>(t: &'a MyBox<Test+'a>, mut ss: SomeStruct<'a>) {
-   |          - `t` is a reference that is only valid in the function body
+   |      -- lifetime `'a` defined here
 LL |     ss.t = t; //~ ERROR mismatched types
-   |     ^^^^^^^^ `t` escapes the function body here
+   |     ^^^^^^^^ assignment requires that `'a` must outlive `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
index e8c1d7e74a0..53d3b2d5323 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
@@ -1,10 +1,10 @@
 error[E0621]: explicit lifetime required in the type of `v`
-  --> $DIR/region-object-lifetime-in-coercion.rs:18:33
+  --> $DIR/region-object-lifetime-in-coercion.rs:18:9
    |
 LL | fn a(v: &[u8]) -> Box<Foo + 'static> {
    |         ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
 LL |     let x: Box<Foo + 'static> = Box::new(v);
-   |                                 ^^^^^^^^^^^ lifetime `'static` required
+   |         ^ lifetime `'static` required
 
 error[E0621]: explicit lifetime required in the type of `v`
   --> $DIR/region-object-lifetime-in-coercion.rs:24:5
diff --git a/src/test/ui/regions/regions-addr-of-self.nll.stderr b/src/test/ui/regions/regions-addr-of-self.nll.stderr
index a85822e48fa..0e38abef668 100644
--- a/src/test/ui/regions/regions-addr-of-self.nll.stderr
+++ b/src/test/ui/regions/regions-addr-of-self.nll.stderr
@@ -4,7 +4,7 @@ error: unsatisfied lifetime constraints
 LL |     pub fn chase_cat(&mut self) {
    |                      - let's call the lifetime of this reference `'1`
 LL |         let p: &'static mut usize = &mut self.cats_chased; //~ ERROR cannot infer
-   |             ^ requires that `'1` must outlive `'static`
+   |             ^ type annotation requires that `'1` must outlive `'static`
 
 error: aborting due to previous error
 
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 9d6301af0fb..6e4bf26047e 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
@@ -4,7 +4,7 @@ error: unsatisfied lifetime constraints
 LL |         let _f = || {
    |                  -- lifetime `'1` represents this closure's body
 LL |             let p: &'static mut usize = &mut self.food; //~ ERROR cannot infer
-   |                 ^ requires that `'1` must outlive `'static`
+   |                 ^ type annotation requires that `'1` must outlive `'static`
    |
    = note: closure implements `FnMut`, so references to captured variables can't escape the closure
 
@@ -16,17 +16,21 @@ LL |     pub fn chase_cat(&mut self) {
 LL |         let _f = || {
    |                  -- lifetime `'1` represents this closure's body
 LL |             let p: &'static mut usize = &mut self.food; //~ ERROR cannot infer
-   |                 ^ requires that `'1` must outlive `'2`
+   |                 ^ type annotation requires that `'1` must outlive `'2`
    |
    = 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:13
+  --> $DIR/regions-addr-of-upvar-self.rs:19:18
    |
-LL |     pub fn chase_cat(&mut self) {
-   |                      - let's call the lifetime of this reference `'1`
-LL |         let _f = || {
-   |             ^^ 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
+LL | |             *p = 3;
+LL | |         };
+   | |_________^ closure body 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-close-object-into-object-2.nll.stderr b/src/test/ui/regions/regions-close-object-into-object-2.nll.stderr
index e619431ddbb..c073e3728e7 100644
--- a/src/test/ui/regions/regions-close-object-into-object-2.nll.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-2.nll.stderr
@@ -1,10 +1,10 @@
 error: unsatisfied lifetime constraints
-  --> $DIR/regions-close-object-into-object-2.rs:20:11
+  --> $DIR/regions-close-object-into-object-2.rs:20:5
    |
 LL | fn g<'a, T: 'static>(v: Box<A<T>+'a>) -> Box<X+'static> {
    |      -- lifetime `'a` defined here
 LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
-   |           ^^^ cast requires that `'a` must outlive `'static`
+   |     ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
 
 error[E0597]: `*v` does not live long enough
   --> $DIR/regions-close-object-into-object-2.rs:20:11
diff --git a/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr b/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr
index 1de1cdc9807..4b47b951d77 100644
--- a/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr
@@ -6,6 +6,14 @@ LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
    |
    = help: consider adding an explicit lifetime bound `U: 'static`...
 
+error: unsatisfied lifetime constraints
+  --> $DIR/regions-close-object-into-object-4.rs:20:5
+   |
+LL | fn i<'a, T, U>(v: Box<A<U>+'a>) -> Box<X+'static> {
+   |      -- lifetime `'a` defined here
+LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
+   |     ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+
 error[E0310]: the parameter type `U` may not live long enough
   --> $DIR/regions-close-object-into-object-4.rs:20:9
    |
@@ -14,14 +22,6 @@ LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
    |
    = help: consider adding an explicit lifetime bound `U: 'static`...
 
-error: unsatisfied lifetime constraints
-  --> $DIR/regions-close-object-into-object-4.rs:20:11
-   |
-LL | fn i<'a, T, U>(v: Box<A<U>+'a>) -> Box<X+'static> {
-   |      -- lifetime `'a` defined here
-LL |     box B(&*v) as Box<X> //~ ERROR cannot infer
-   |           ^^^ cast requires that `'a` must outlive `'static`
-
 error[E0597]: `*v` does not live long enough
   --> $DIR/regions-close-object-into-object-4.rs:20:11
    |
diff --git a/src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr
index 98a4dc29ae7..d0606295713 100644
--- a/src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr
+++ b/src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr
@@ -18,7 +18,7 @@ LL | fn ordering3<'a, 'b>(x: &'a usize, y: &'b usize) -> &'a &'b usize {
    |              lifetime `'a` defined here
 LL |     // Do not infer an ordering from the return value.
 LL |     let z: &'b usize = &*x;
-   |                        ^^^ requires that `'a` must outlive `'b`
+   |                        ^^^ assignment requires that `'a` must outlive `'b`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/regions/regions-infer-paramd-indirect.nll.stderr b/src/test/ui/regions/regions-infer-paramd-indirect.nll.stderr
index 8e29e77713b..7558c5caa0e 100644
--- a/src/test/ui/regions/regions-infer-paramd-indirect.nll.stderr
+++ b/src/test/ui/regions/regions-infer-paramd-indirect.nll.stderr
@@ -1,12 +1,13 @@
-error: borrowed data escapes outside of function
+error: unsatisfied lifetime constraints
   --> $DIR/regions-infer-paramd-indirect.rs:33:9
    |
+LL | impl<'a> set_f<'a> for c<'a> {
+   |      -- lifetime `'a` defined here
+...
 LL |     fn set_f_bad(&mut self, b: Box<b>) {
-   |                  ---------  - `b` is a reference that is only valid in the function body
-   |                  |
-   |                  `self` is declared here, outside of the function body
+   |                             - has type `std::boxed::Box<std::boxed::Box<&'1 isize>>`
 LL |         self.f = b;
-   |         ^^^^^^ `b` escapes the function body here
+   |         ^^^^^^ assignment requires that `'1` must outlive `'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-nested-fns.nll.stderr b/src/test/ui/regions/regions-nested-fns.nll.stderr
index 9e6c57f6733..4bb602d572f 100644
--- a/src/test/ui/regions/regions-nested-fns.nll.stderr
+++ b/src/test/ui/regions/regions-nested-fns.nll.stderr
@@ -1,22 +1,14 @@
-error: unsatisfied lifetime constraints
+error: borrowed data escapes outside of closure
   --> $DIR/regions-nested-fns.rs:20:9
    |
 LL |     let mut ay = &y; //~ ERROR E0495
-   |         ------ lifetime `'2` appears in the type of `ay`
+   |         ------ `ay` is declared here, outside of the closure body
 LL | 
 LL |     ignore::<Box<for<'z> FnMut(&'z isize)>>(Box::new(|z| {
-   |                                                       - has type `&'1 isize`
+   |                                                       - `z` is a reference that is only valid in the closure body
 ...
 LL |         ay = z;
-   |         ^^^^^^ requires that `'1` must outlive `'2`
-
-error: unsatisfied lifetime constraints
-  --> $DIR/regions-nested-fns.rs:14:9
-   |
-LL | fn nested<'x>(x: &'x isize) {
-   |           -- lifetime `'x` defined here
-LL |     let y = 3;
-   |         ^ requires that `'x` must outlive `'static`
+   |         ^^^^^^ `z` escapes the closure body here
 
 error[E0597]: `y` does not live long enough
   --> $DIR/regions-nested-fns.rs:15:18
@@ -43,6 +35,20 @@ LL | }
    |
    = note: borrowed value must be valid for the static lifetime...
 
+error: unsatisfied lifetime constraints
+  --> $DIR/regions-nested-fns.rs:23:68
+   |
+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`
+
 error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr b/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr
index d4140242c01..0a9bcee1ce2 100644
--- a/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr
+++ b/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr
@@ -7,7 +7,7 @@ LL | fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
    |         lifetime `'a` defined here
 LL |     // Without knowing 'a:'b, we can't coerce
 LL |     x //~ ERROR lifetime bound not satisfied
-   |     ^ returning this value requires that `'a` must outlive `'b`
+   |     ^ cast requires that `'a` must outlive `'b`
 
 error: unsatisfied lifetime constraints
   --> $DIR/regions-trait-object-subtyping.rs:32:5
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr
index 745c65c54df..7adb195b7d0 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr
@@ -5,7 +5,7 @@ LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
    |                - let's call the lifetime of this reference `'1`
 LL |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
-   |     ^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static`
+   |     ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr b/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr
index 4ef45edc242..a30720dc6ba 100644
--- a/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr
+++ b/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr
@@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
    |                     lifetime `'min` defined here
 ...
 LL |     v //~ ERROR mismatched types
-   |     ^ cast requires that `'min` must outlive `'max`
+   |     ^ returning this value requires that `'min` must outlive `'max`
 
 error: unsatisfied lifetime constraints
   --> $DIR/variance-contravariant-arg-object.rs:32:5
@@ -18,7 +18,7 @@ LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
    |                     lifetime `'min` defined here
 ...
 LL |     v //~ ERROR mismatched types
-   |     ^ cast requires that `'min` must outlive `'max`
+   |     ^ returning this value requires that `'min` must outlive `'max`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/variance/variance-covariant-arg-object.nll.stderr b/src/test/ui/variance/variance-covariant-arg-object.nll.stderr
index 3105ebaf031..26699a537e8 100644
--- a/src/test/ui/variance/variance-covariant-arg-object.nll.stderr
+++ b/src/test/ui/variance/variance-covariant-arg-object.nll.stderr
@@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
    |                     lifetime `'min` defined here
 ...
 LL |     v //~ ERROR mismatched types
-   |     ^ cast requires that `'min` must outlive `'max`
+   |     ^ returning this value requires that `'min` must outlive `'max`
 
 error: unsatisfied lifetime constraints
   --> $DIR/variance-covariant-arg-object.rs:32:5
@@ -18,7 +18,7 @@ LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
    |                     lifetime `'min` defined here
 ...
 LL |     v //~ ERROR mismatched types
-   |     ^ cast requires that `'min` must outlive `'max`
+   |     ^ returning this value requires that `'min` must outlive `'max`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/variance/variance-invariant-arg-object.nll.stderr b/src/test/ui/variance/variance-invariant-arg-object.nll.stderr
index 54ad4f4c5fb..20ab6485986 100644
--- a/src/test/ui/variance/variance-invariant-arg-object.nll.stderr
+++ b/src/test/ui/variance/variance-invariant-arg-object.nll.stderr
@@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
    |                     lifetime `'min` defined here
 ...
 LL |     v //~ ERROR mismatched types
-   |     ^ cast requires that `'min` must outlive `'max`
+   |     ^ returning this value requires that `'min` must outlive `'max`
 
 error: unsatisfied lifetime constraints
   --> $DIR/variance-invariant-arg-object.rs:28:5
@@ -18,7 +18,7 @@ LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
    |                     lifetime `'min` defined here
 ...
 LL |     v //~ ERROR mismatched types
-   |     ^ cast requires that `'min` must outlive `'max`
+   |     ^ returning this value requires that `'min` must outlive `'max`
 
 error: aborting due to 2 previous errors