about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-01-08 12:37:54 +0000
committerbors <bors@rust-lang.org>2025-01-08 12:37:54 +0000
commit6afee111c2faf86ba884ea748967130abad37b52 (patch)
tree12ea9f1e83042d3518631dc41426f32289baa79f
parent9c87288a7d2f03625a813df6d3bfe43c09ad4f5a (diff)
parentfe8b12f8cfd27984a6102c441b49023d5bce0b02 (diff)
downloadrust-6afee111c2faf86ba884ea748967130abad37b52.tar.gz
rust-6afee111c2faf86ba884ea748967130abad37b52.zip
Auto merge of #133858 - dianne:better-blame-constraints-for-static, r=lcnr
`best_blame_constraint`: Blame better constraints when the region graph has cycles from invariance or `'static`

This fixes #132749 by changing which constraint is blamed for region errors in several cases. `best_blame_constraint` had a heuristic that tried to pinpoint the constraint causing an error by filtering out any constraints where the outliving region is unified with the ultimate target region being outlived. However, it used the SCCs of the region graph to do this, which is unreliable; in particular, if the target region is `'static`, or if there are cycles from the presence of invariant types, it was skipping over the constraints it should be blaming. As is the case in that issue, this could lead to confusing diagnostics. The simplest fix seems to work decently, judging by test stderr: this makes `best_blame_constraint` no longer filter constraints by their outliving region's SCC.

There are admittedly some quirks in the test output. In many cases, subdiagnostics that depend on the particular constraint being blamed have either started or stopped being emitted. After starting at this for quite a while, I think anything too fickle about whether it outputs based on the particular constraint being blamed should instead be looking at the constraint path as a whole, similar to what's done for [the placeholder-from-predicate note](https://github.com/rust-lang/rust/compare/master...dianne:rust:better-blame-constraints-for-static#diff-3c0de6462469af483c9ecdf2c4b00cb26192218ef2d5c62a0fde75107a74caaeR506).

Very many tests involving invariant types gained a note pointing out the types' invariance, but in a few cases it was lost. A particularly illustrative example is [tests/ui/lifetimes/copy_modulo_regions.stderr](https://github.com/rust-lang/rust/compare/master...dianne:rust:better-blame-constraints-for-static?expand=1#diff-96e1f8b29789b3c4ce2f77a5e0fba248829b97ef9d1ce39e7d2b4aa57b2cf4f0); I'd argue the new constraint is a better one to blame, but it lacks the variance diagnostic information that's elsewhere in the constraint path. If desired, I can try making that note check the whole path rather than just the blamed constraint.

The subdiagnostic [`BorrowExplanation::add_object_lifetime_default_note`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/diagnostics/explain_borrow/enum.BorrowExplanation.html#method.add_object_lifetime_default_note) depends on a `Cast` being blamed, so [a special case](https://github.com/rust-lang/rust/pull/133858/commits/364ca7f99c12fb5220e6b568ac391979317ce878) was necessary to keep it from disappearing from tests specifically testing for it. However, see the FIXME comment in that commit; I think the special case should be removed once that subdiagnostic works properly, but it's nontrivial enough to warrant a separate PR. Incidentally, this removes the note from a test where it was being added erroneously: in [tests/ui/borrowck/two-phase-surprise-no-conflict.stderr](https://github.com/rust-lang/rust/compare/master...dianne:rust:better-blame-constraints-for-static?expand=1#diff-8cf085af8203677de6575a45458c9e6b03412a927df879412adec7e4f7ff5e14), the object lifetime is explicitly provided and it's not `'static`.
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs75
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs38
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs58
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs24
-rw-r--r--compiler/rustc_borrowck/src/lib.rs1
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs233
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs28
-rw-r--r--compiler/rustc_middle/Cargo.toml1
-rw-r--r--compiler/rustc_middle/src/mir/query.rs23
-rw-r--r--tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr8
-rw-r--r--tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr8
-rw-r--r--tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr48
-rw-r--r--tests/ui/async-await/issues/issue-63388-1.rs2
-rw-r--r--tests/ui/async-await/issues/issue-63388-1.stderr15
-rw-r--r--tests/ui/async-await/issues/issue-63388-2.rs2
-rw-r--r--tests/ui/async-await/issues/issue-63388-2.stderr15
-rw-r--r--tests/ui/borrowck/fn-item-check-type-params.stderr4
-rw-r--r--tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr8
-rw-r--r--tests/ui/borrowck/issue-7573.rs2
-rw-r--r--tests/ui/borrowck/issue-7573.stderr4
-rw-r--r--tests/ui/borrowck/two-phase-surprise-no-conflict.stderr22
-rw-r--r--tests/ui/c-variadic/variadic-ffi-4.stderr6
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs2
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr18
-rw-r--r--tests/ui/coroutine/resume-arg-outlives-2.rs2
-rw-r--r--tests/ui/coroutine/resume-arg-outlives-2.stderr24
-rw-r--r--tests/ui/fn/fn_def_coercion.rs4
-rw-r--r--tests/ui/fn/fn_def_coercion.stderr41
-rw-r--r--tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr2
-rw-r--r--tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr3
-rw-r--r--tests/ui/impl-trait/precise-capturing/migration-note.rs4
-rw-r--r--tests/ui/impl-trait/precise-capturing/migration-note.stderr16
-rw-r--r--tests/ui/inline-const/const-expr-lifetime-err.stderr7
-rw-r--r--tests/ui/inline-const/const-match-pat-lifetime-err.stderr2
-rw-r--r--tests/ui/kindck/kindck-impl-type-params.stderr4
-rw-r--r--tests/ui/lifetimes/copy_modulo_regions.stderr5
-rw-r--r--tests/ui/lifetimes/issue-90170-elision-mismatch.stderr9
-rw-r--r--tests/ui/lifetimes/issue-90600-expected-return-static-indirect.rs2
-rw-r--r--tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr28
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr3
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr3
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs2
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr10
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs2
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr10
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr6
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr3
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr3
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr3
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr3
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr3
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr3
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr3
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr3
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr4
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-ref.rs3
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr20
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr12
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs3
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr27
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs3
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr27
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-val.rs3
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-val.stderr20
-rw-r--r--tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr4
-rw-r--r--tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr4
-rw-r--r--tests/ui/nll/issue-54779-anon-static-lifetime.rs2
-rw-r--r--tests/ui/nll/issue-54779-anon-static-lifetime.stderr14
-rw-r--r--tests/ui/nll/issue-62007-assign-const-index.stderr7
-rw-r--r--tests/ui/nll/issue-62007-assign-differing-fields.stderr7
-rw-r--r--tests/ui/nll/issue-67007-escaping-data.rs4
-rw-r--r--tests/ui/nll/issue-67007-escaping-data.stderr8
-rw-r--r--tests/ui/nll/issue-95272.rs2
-rw-r--r--tests/ui/nll/issue-95272.stderr9
-rw-r--r--tests/ui/nll/issue-98589-closures-relate-named-regions.stderr4
-rw-r--r--tests/ui/nll/outlives-suggestion-simple.stderr4
-rw-r--r--tests/ui/nll/polonius/assignment-to-differing-field.stderr16
-rw-r--r--tests/ui/nll/relate_tys/var-appears-twice.stderr7
-rw-r--r--tests/ui/nll/ty-outlives/projection-one-region-closure.stderr58
-rw-r--r--tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr14
-rw-r--r--tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr2
-rw-r--r--tests/ui/nll/type-check-pointer-comparisons.stderr18
-rw-r--r--tests/ui/nll/user-annotations/adt-nullary-enums.stderr73
-rw-r--r--tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr18
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-1.stderr7
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-2.stderr7
-rw-r--r--tests/ui/nll/where_clauses_in_structs.stderr4
-rw-r--r--tests/ui/regions/better-blame-constraint-for-outlives-static.rs13
-rw-r--r--tests/ui/regions/better-blame-constraint-for-outlives-static.stderr11
-rw-r--r--tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.stderr4
-rw-r--r--tests/ui/regions/region-invariant-static-error-reporting.rs6
-rw-r--r--tests/ui/regions/region-invariant-static-error-reporting.stderr18
-rw-r--r--tests/ui/traits/coercion-generic-regions.stderr6
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-3.stderr4
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-4.stderr4
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr4
-rw-r--r--tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr3
-rw-r--r--tests/ui/variance/variance-associated-types2.stderr4
99 files changed, 731 insertions, 620 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 51166a06d2e..26971e8a120 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4115,7 +4115,6 @@ name = "rustc_middle"
 version = "0.0.0"
 dependencies = [
  "bitflags",
- "derive-where",
  "either",
  "field-offset",
  "gsgdt",
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 8e5944d6cf4..2d993a3fd16 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1516,15 +1516,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         });
 
         self.explain_why_borrow_contains_point(location, borrow, None)
-            .add_explanation_to_diagnostic(
-                self.infcx.tcx,
-                self.body,
-                &self.local_names,
-                &mut err,
-                "",
-                Some(borrow_span),
-                None,
-            );
+            .add_explanation_to_diagnostic(&self, &mut err, "", Some(borrow_span), None);
         self.suggest_copy_for_type_in_cloned_ref(&mut err, place);
         let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
         if let Some(expr) = self.find_expr(borrow_span) {
@@ -1591,15 +1583,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         });
 
         self.explain_why_borrow_contains_point(location, borrow, None)
-            .add_explanation_to_diagnostic(
-                self.infcx.tcx,
-                self.body,
-                &self.local_names,
-                &mut err,
-                "",
-                None,
-                None,
-            );
+            .add_explanation_to_diagnostic(&self, &mut err, "", None, None);
         err
     }
 
@@ -1886,9 +1870,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         }
 
         explanation.add_explanation_to_diagnostic(
-            self.infcx.tcx,
-            self.body,
-            &self.local_names,
+            &self,
             &mut err,
             first_borrow_desc,
             None,
@@ -3046,15 +3028,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
             if let BorrowExplanation::MustBeValidFor { .. } = explanation {
             } else {
-                explanation.add_explanation_to_diagnostic(
-                    self.infcx.tcx,
-                    self.body,
-                    &self.local_names,
-                    &mut err,
-                    "",
-                    None,
-                    None,
-                );
+                explanation.add_explanation_to_diagnostic(&self, &mut err, "", None, None);
             }
         } else {
             err.span_label(borrow_span, "borrowed value does not live long enough");
@@ -3067,15 +3041,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 }
             });
 
-            explanation.add_explanation_to_diagnostic(
-                self.infcx.tcx,
-                self.body,
-                &self.local_names,
-                &mut err,
-                "",
-                Some(borrow_span),
-                None,
-            );
+            explanation.add_explanation_to_diagnostic(&self, &mut err, "", Some(borrow_span), None);
         }
 
         err
@@ -3128,15 +3094,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             _ => {}
         }
 
-        explanation.add_explanation_to_diagnostic(
-            self.infcx.tcx,
-            self.body,
-            &self.local_names,
-            &mut err,
-            "",
-            None,
-            None,
-        );
+        explanation.add_explanation_to_diagnostic(&self, &mut err, "", None, None);
 
         self.buffer_error(err);
     }
@@ -3309,15 +3267,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             }
             _ => {}
         }
-        explanation.add_explanation_to_diagnostic(
-            self.infcx.tcx,
-            self.body,
-            &self.local_names,
-            &mut err,
-            "",
-            None,
-            None,
-        );
+        explanation.add_explanation_to_diagnostic(&self, &mut err, "", None, None);
 
         borrow_spans.args_subdiag(&mut err, |args_span| {
             crate::session_diagnostics::CaptureArgLabel::Capture {
@@ -3808,15 +3758,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             }
         });
 
-        self.explain_why_borrow_contains_point(location, loan, None).add_explanation_to_diagnostic(
-            self.infcx.tcx,
-            self.body,
-            &self.local_names,
-            &mut err,
-            "",
-            None,
-            None,
-        );
+        self.explain_why_borrow_contains_point(location, loan, None)
+            .add_explanation_to_diagnostic(&self, &mut err, "", None, None);
 
         self.explain_deref_coercion(loan, &mut err);
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 87017460e8e..48f28f3f1de 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -8,7 +8,6 @@ use std::assert_matches::assert_matches;
 use rustc_errors::{Applicability, Diag};
 use rustc_hir as hir;
 use rustc_hir::intravisit::Visitor;
-use rustc_index::IndexSlice;
 use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
 use rustc_middle::mir::{
@@ -18,14 +17,15 @@ use rustc_middle::mir::{
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
 use rustc_middle::util::CallKind;
-use rustc_span::{DesugaringKind, Span, Symbol, kw, sym};
+use rustc_span::{DesugaringKind, Span, kw, sym};
 use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
 use tracing::{debug, instrument};
 
 use super::{RegionName, UseSpans, find_use};
 use crate::borrow_set::BorrowData;
+use crate::constraints::OutlivesConstraint;
 use crate::nll::ConstraintDescription;
-use crate::region_infer::{BlameConstraint, Cause, ExtraConstraintInfo};
+use crate::region_infer::{BlameConstraint, Cause};
 use crate::{MirBorrowckCtxt, WriteKind};
 
 #[derive(Debug)]
@@ -43,7 +43,7 @@ pub(crate) enum BorrowExplanation<'tcx> {
         span: Span,
         region_name: RegionName,
         opt_place_desc: Option<String>,
-        extra_info: Vec<ExtraConstraintInfo>,
+        path: Vec<OutlivesConstraint<'tcx>>,
     },
     Unexplained,
 }
@@ -63,14 +63,16 @@ impl<'tcx> BorrowExplanation<'tcx> {
     }
     pub(crate) fn add_explanation_to_diagnostic(
         &self,
-        tcx: TyCtxt<'tcx>,
-        body: &Body<'tcx>,
-        local_names: &IndexSlice<Local, Option<Symbol>>,
+        cx: &MirBorrowckCtxt<'_, '_, 'tcx>,
         err: &mut Diag<'_>,
         borrow_desc: &str,
         borrow_span: Option<Span>,
         multiple_borrow_span: Option<(Span, Span)>,
     ) {
+        let tcx = cx.infcx.tcx;
+        let body = cx.body;
+        let local_names = &cx.local_names;
+
         if let Some(span) = borrow_span {
             let def_id = body.source.def_id();
             if let Some(node) = tcx.hir().get_if_local(def_id)
@@ -306,7 +308,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
                 ref region_name,
                 ref opt_place_desc,
                 from_closure: _,
-                ref extra_info,
+                ref path,
             } => {
                 region_name.highlight_region_name(err);
 
@@ -328,13 +330,8 @@ impl<'tcx> BorrowExplanation<'tcx> {
                     );
                 };
 
-                for extra in extra_info {
-                    match extra {
-                        ExtraConstraintInfo::PlaceholderFromPredicate(span) => {
-                            err.span_note(*span, "due to current limitations in the borrow checker, this implies a `'static` lifetime");
-                        }
-                    }
-                }
+                cx.add_placeholder_from_predicate_note(err, &path);
+                cx.add_sized_or_copy_bound_info(err, category, &path);
 
                 if let ConstraintCategory::Cast {
                     is_implicit_coercion: true,
@@ -487,8 +484,9 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
         &self,
         borrow_region: RegionVid,
         outlived_region: RegionVid,
-    ) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>, Vec<ExtraConstraintInfo>) {
-        let (blame_constraint, extra_info) = self.regioncx.best_blame_constraint(
+    ) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>, Vec<OutlivesConstraint<'tcx>>)
+    {
+        let (blame_constraint, path) = self.regioncx.best_blame_constraint(
             borrow_region,
             NllRegionVariableOrigin::FreeRegion,
             |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region),
@@ -497,7 +495,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
 
         let outlived_fr_name = self.give_region_a_name(outlived_region);
 
-        (category, from_closure, cause.span, outlived_fr_name, extra_info)
+        (category, from_closure, cause.span, outlived_fr_name, path)
     }
 
     /// Returns structured explanation for *why* the borrow contains the
@@ -596,7 +594,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
 
             None => {
                 if let Some(region) = self.to_error_region_vid(borrow_region_vid) {
-                    let (category, from_closure, span, region_name, extra_info) =
+                    let (category, from_closure, span, region_name, path) =
                         self.free_region_constraint_info(borrow_region_vid, region);
                     if let Some(region_name) = region_name {
                         let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref());
@@ -606,7 +604,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
                             span,
                             region_name,
                             opt_place_desc,
-                            extra_info,
+                            path,
                         }
                     } else {
                         debug!("Could not generate a region name");
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index ebbdfea302c..0286ea6cd9d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -8,14 +8,16 @@ use rustc_errors::{Applicability, Diag, MultiSpan};
 use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::{self as hir, CoroutineKind, LangItem};
 use rustc_index::IndexSlice;
-use rustc_infer::infer::BoundRegionConversionTime;
+use rustc_infer::infer::{
+    BoundRegionConversionTime, NllRegionVariableOrigin, RegionVariableOrigin,
+};
 use rustc_infer::traits::SelectionError;
 use rustc_middle::bug;
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::{
-    AggregateKind, CallSource, ConstOperand, FakeReadCause, Local, LocalInfo, LocalKind, Location,
-    Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
-    TerminatorKind,
+    AggregateKind, CallSource, ConstOperand, ConstraintCategory, FakeReadCause, Local, LocalInfo,
+    LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement,
+    StatementKind, Terminator, TerminatorKind,
 };
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
@@ -33,7 +35,9 @@ use tracing::debug;
 
 use super::MirBorrowckCtxt;
 use super::borrow_set::BorrowData;
+use crate::constraints::OutlivesConstraint;
 use crate::fluent_generated as fluent;
+use crate::nll::ConstraintDescription;
 use crate::session_diagnostics::{
     CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause,
     CaptureVarKind, CaptureVarPathUseCause, OnClosureNote,
@@ -619,6 +623,52 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         region.print(&mut printer).unwrap();
         printer.into_buffer()
     }
+
+    /// Add a note to region errors and borrow explanations when higher-ranked regions in predicates
+    /// implicitly introduce an "outlives `'static`" constraint.
+    fn add_placeholder_from_predicate_note(
+        &self,
+        err: &mut Diag<'_>,
+        path: &[OutlivesConstraint<'tcx>],
+    ) {
+        let predicate_span = path.iter().find_map(|constraint| {
+            let outlived = constraint.sub;
+            if let Some(origin) = self.regioncx.var_infos.get(outlived)
+                && let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(_)) =
+                    origin.origin
+                && let ConstraintCategory::Predicate(span) = constraint.category
+            {
+                Some(span)
+            } else {
+                None
+            }
+        });
+
+        if let Some(span) = predicate_span {
+            err.span_note(span, "due to current limitations in the borrow checker, this implies a `'static` lifetime");
+        }
+    }
+
+    /// Add a label to region errors and borrow explanations when outlives constraints arise from
+    /// proving a type implements `Sized` or `Copy`.
+    fn add_sized_or_copy_bound_info(
+        &self,
+        err: &mut Diag<'_>,
+        blamed_category: ConstraintCategory<'tcx>,
+        path: &[OutlivesConstraint<'tcx>],
+    ) {
+        for sought_category in [ConstraintCategory::SizedBound, ConstraintCategory::CopyBound] {
+            if sought_category != blamed_category
+                && let Some(sought_constraint) = path.iter().find(|c| c.category == sought_category)
+            {
+                let label = format!(
+                    "requirement occurs due to {}",
+                    sought_category.description().trim_end()
+                );
+                err.span_label(sought_constraint.span, label);
+            }
+        }
+    }
 }
 
 /// The span(s) associated to a use of a place.
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 3555009c63f..f0baa20648c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -13,7 +13,7 @@ use rustc_hir::{PolyTraitRef, TyKind, WhereBoundPredicate};
 use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound};
 use rustc_middle::bug;
 use rustc_middle::hir::place::PlaceBase;
-use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
+use rustc_middle::mir::{AnnotationSource, ConstraintCategory, ReturnConstraint};
 use rustc_middle::ty::{self, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeVisitor};
 use rustc_span::{Ident, Span, kw};
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
@@ -29,7 +29,7 @@ use tracing::{debug, instrument, trace};
 use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource};
 use crate::nll::ConstraintDescription;
 use crate::region_infer::values::RegionElement;
-use crate::region_infer::{BlameConstraint, ExtraConstraintInfo, TypeTest};
+use crate::region_infer::{BlameConstraint, TypeTest};
 use crate::session_diagnostics::{
     FnMutError, FnMutReturnTypeErr, GenericDoesNotLiveLongEnough, LifetimeOutliveErr,
     LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote,
@@ -49,8 +49,8 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
             ConstraintCategory::Cast { is_implicit_coercion: false, .. } => "cast ",
             ConstraintCategory::Cast { is_implicit_coercion: true, .. } => "coercion ",
             ConstraintCategory::CallArgument(_) => "argument ",
-            ConstraintCategory::TypeAnnotation => "type annotation ",
-            ConstraintCategory::ClosureBounds => "closure body ",
+            ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg) => "generic argument ",
+            ConstraintCategory::TypeAnnotation(_) => "type annotation ",
             ConstraintCategory::SizedBound => "proving this value is `Sized` ",
             ConstraintCategory::CopyBound => "copying this value ",
             ConstraintCategory::OpaqueType => "opaque type ",
@@ -440,10 +440,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     ) {
         debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
 
-        let (blame_constraint, extra_info) =
-            self.regioncx.best_blame_constraint(fr, fr_origin, |r| {
-                self.regioncx.provides_universal_region(r, fr, outlived_fr)
-            });
+        let (blame_constraint, path) = self.regioncx.best_blame_constraint(fr, fr_origin, |r| {
+            self.regioncx.provides_universal_region(r, fr, outlived_fr)
+        });
         let BlameConstraint { category, cause, variance_info, .. } = blame_constraint;
 
         debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info);
@@ -554,13 +553,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             }
         }
 
-        for extra in extra_info {
-            match extra {
-                ExtraConstraintInfo::PlaceholderFromPredicate(span) => {
-                    diag.span_note(span, "due to current limitations in the borrow checker, this implies a `'static` lifetime");
-                }
-            }
-        }
+        self.add_placeholder_from_predicate_note(&mut diag, &path);
+        self.add_sized_or_copy_bound_info(&mut diag, category, &path);
 
         self.buffer_error(diag);
     }
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index c97c3f3f870..88d0933d8ce 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(file_buffered)]
+#![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 1e29b741854..59189082f6f 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -13,15 +13,16 @@ use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound,
 use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
 use rustc_middle::bug;
 use rustc_middle::mir::{
-    BasicBlock, Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureOutlivesSubjectTy,
-    ClosureRegionRequirements, ConstraintCategory, Local, Location, ReturnConstraint,
-    TerminatorKind,
+    AnnotationSource, BasicBlock, Body, ClosureOutlivesRequirement, ClosureOutlivesSubject,
+    ClosureOutlivesSubjectTy, ClosureRegionRequirements, ConstraintCategory, Local, Location,
+    ReturnConstraint, TerminatorKind,
 };
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex};
 use rustc_mir_dataflow::points::DenseLocationMap;
 use rustc_span::Span;
+use rustc_span::hygiene::DesugaringKind;
 use tracing::{debug, instrument, trace};
 
 use crate::BorrowckInferCtxt;
@@ -315,11 +316,6 @@ enum Trace<'tcx> {
     NotVisited,
 }
 
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub(crate) enum ExtraConstraintInfo {
-    PlaceholderFromPredicate(Span),
-}
-
 #[instrument(skip(infcx, sccs), level = "debug")]
 fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) {
     use crate::renumber::RegionCtxt;
@@ -1938,7 +1934,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         from_region: RegionVid,
         from_region_origin: NllRegionVariableOrigin,
         target_test: impl Fn(RegionVid) -> bool,
-    ) -> (BlameConstraint<'tcx>, Vec<ExtraConstraintInfo>) {
+    ) -> (BlameConstraint<'tcx>, Vec<OutlivesConstraint<'tcx>>) {
         // Find all paths
         let (path, target_region) = self
             .find_constraint_paths_between_regions(from_region, target_test)
@@ -1960,25 +1956,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 .collect::<Vec<_>>()
         );
 
-        let mut extra_info = vec![];
-        for constraint in path.iter() {
-            let outlived = constraint.sub;
-            let Some(origin) = self.var_infos.get(outlived) else {
-                continue;
-            };
-            let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(p)) = origin.origin
-            else {
-                continue;
-            };
-            debug!(?constraint, ?p);
-            let ConstraintCategory::Predicate(span) = constraint.category else {
-                continue;
-            };
-            extra_info.push(ExtraConstraintInfo::PlaceholderFromPredicate(span));
-            // We only want to point to one
-            break;
-        }
-
         // We try to avoid reporting a `ConstraintCategory::Predicate` as our best constraint.
         // Instead, we use it to produce an improved `ObligationCauseCode`.
         // FIXME - determine what we should do if we encounter multiple
@@ -1997,42 +1974,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             })
             .unwrap_or_else(|| ObligationCauseCode::Misc);
 
-        // Classify each of the constraints along the path.
-        let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
-            .iter()
-            .map(|constraint| BlameConstraint {
-                category: constraint.category,
-                from_closure: constraint.from_closure,
-                cause: ObligationCause::new(constraint.span, CRATE_DEF_ID, cause_code.clone()),
-                variance_info: constraint.variance_info,
-            })
-            .collect();
-        debug!("categorized_path={:#?}", categorized_path);
-
-        // To find the best span to cite, we first try to look for the
-        // final constraint that is interesting and where the `sup` is
-        // not unified with the ultimate target region. The reason
-        // for this is that we have a chain of constraints that lead
-        // from the source to the target region, something like:
-        //
-        //    '0: '1 ('0 is the source)
-        //    '1: '2
-        //    '2: '3
-        //    '3: '4
-        //    '4: '5
-        //    '5: '6 ('6 is the target)
-        //
-        // Some of those regions are unified with `'6` (in the same
-        // SCC). We want to screen those out. After that point, the
-        // "closest" constraint we have to the end is going to be the
-        // most likely to be the point where the value escapes -- but
-        // we still want to screen for an "interesting" point to
-        // highlight (e.g., a call site or something).
-        let target_scc = self.constraint_sccs.scc(target_region);
-        let mut range = 0..path.len();
-
-        // As noted above, when reporting an error, there is typically a chain of constraints
-        // leading from some "source" region which must outlive some "target" region.
+        // When reporting an error, there is typically a chain of constraints leading from some
+        // "source" region which must outlive some "target" region.
         // In most cases, we prefer to "blame" the constraints closer to the target --
         // but there is one exception. When constraints arise from higher-ranked subtyping,
         // we generally prefer to blame the source value,
@@ -2073,78 +2016,114 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             | NllRegionVariableOrigin::Existential { from_forall: true } => false,
         };
 
-        let find_region = |i: &usize| {
-            let constraint = &path[*i];
-
-            let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup);
-
-            if blame_source {
-                match categorized_path[*i].category {
-                    ConstraintCategory::OpaqueType
-                    | ConstraintCategory::Boring
-                    | ConstraintCategory::BoringNoLocation
-                    | ConstraintCategory::Internal
-                    | ConstraintCategory::Predicate(_) => false,
-                    ConstraintCategory::TypeAnnotation
-                    | ConstraintCategory::Return(_)
-                    | ConstraintCategory::Yield => true,
-                    _ => constraint_sup_scc != target_scc,
-                }
+        // To pick a constraint to blame, we organize constraints by how interesting we expect them
+        // to be in diagnostics, then pick the most interesting one closest to either the source or
+        // the target on our constraint path.
+        let constraint_interest = |constraint: &OutlivesConstraint<'tcx>| {
+            // Try to avoid blaming constraints from desugarings, since they may not clearly match
+            // match what users have written. As an exception, allow blaming returns generated by
+            // `?` desugaring, since the correspondence is fairly clear.
+            let category = if let Some(kind) = constraint.span.desugaring_kind()
+                && (kind != DesugaringKind::QuestionMark
+                    || !matches!(constraint.category, ConstraintCategory::Return(_)))
+            {
+                ConstraintCategory::Boring
             } else {
-                !matches!(
-                    categorized_path[*i].category,
-                    ConstraintCategory::OpaqueType
-                        | ConstraintCategory::Boring
-                        | ConstraintCategory::BoringNoLocation
-                        | ConstraintCategory::Internal
-                        | ConstraintCategory::Predicate(_)
-                )
-            }
-        };
-
-        let best_choice =
-            if blame_source { range.rev().find(find_region) } else { range.find(find_region) };
-
-        debug!(?best_choice, ?blame_source, ?extra_info);
+                constraint.category
+            };
 
-        if let Some(i) = best_choice {
-            if let Some(next) = categorized_path.get(i + 1) {
-                if matches!(categorized_path[i].category, ConstraintCategory::Return(_))
-                    && next.category == ConstraintCategory::OpaqueType
+            match category {
+                // Returns usually provide a type to blame and have specially written diagnostics,
+                // so prioritize them.
+                ConstraintCategory::Return(_) => 0,
+                // Unsizing coercions are interesting, since we have a note for that:
+                // `BorrowExplanation::add_object_lifetime_default_note`.
+                // FIXME(dianne): That note shouldn't depend on a coercion being blamed; see issue
+                // #131008 for an example of where we currently don't emit it but should.
+                // Once the note is handled properly, this case should be removed. Until then, it
+                // should be as limited as possible; the note is prone to false positives and this
+                // constraint usually isn't best to blame.
+                ConstraintCategory::Cast {
+                    unsize_to: Some(unsize_ty),
+                    is_implicit_coercion: true,
+                } if target_region == self.universal_regions().fr_static
+                    // Mirror the note's condition, to minimize how often this diverts blame.
+                    && let ty::Adt(_, args) = unsize_ty.kind()
+                    && args.iter().any(|arg| arg.as_type().is_some_and(|ty| ty.is_trait()))
+                    // Mimic old logic for this, to minimize false positives in tests.
+                    && !path
+                        .iter()
+                        .any(|c| matches!(c.category, ConstraintCategory::TypeAnnotation(_))) =>
                 {
-                    // The return expression is being influenced by the return type being
-                    // impl Trait, point at the return type and not the return expr.
-                    return (next.clone(), extra_info);
+                    1
                 }
+                // Between other interesting constraints, order by their position on the `path`.
+                ConstraintCategory::Yield
+                | ConstraintCategory::UseAsConst
+                | ConstraintCategory::UseAsStatic
+                | ConstraintCategory::TypeAnnotation(
+                    AnnotationSource::Ascription
+                    | AnnotationSource::Declaration
+                    | AnnotationSource::OpaqueCast,
+                )
+                | ConstraintCategory::Cast { .. }
+                | ConstraintCategory::CallArgument(_)
+                | ConstraintCategory::CopyBound
+                | ConstraintCategory::SizedBound
+                | ConstraintCategory::Assignment
+                | ConstraintCategory::Usage
+                | ConstraintCategory::ClosureUpvar(_) => 2,
+                // Generic arguments are unlikely to be what relates regions together
+                ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg) => 3,
+                // We handle predicates and opaque types specially; don't prioritize them here.
+                ConstraintCategory::Predicate(_) | ConstraintCategory::OpaqueType => 4,
+                // `Boring` constraints can correspond to user-written code and have useful spans,
+                // but don't provide any other useful information for diagnostics.
+                ConstraintCategory::Boring => 5,
+                // `BoringNoLocation` constraints can point to user-written code, but are less
+                // specific, and are not used for relations that would make sense to blame.
+                ConstraintCategory::BoringNoLocation => 6,
+                // Do not blame internal constraints.
+                ConstraintCategory::Internal => 7,
+                ConstraintCategory::IllegalUniverse => 8,
             }
+        };
 
-            if categorized_path[i].category == ConstraintCategory::Return(ReturnConstraint::Normal)
-            {
-                let field = categorized_path.iter().find_map(|p| {
-                    if let ConstraintCategory::ClosureUpvar(f) = p.category {
-                        Some(f)
-                    } else {
-                        None
-                    }
-                });
-
-                if let Some(field) = field {
-                    categorized_path[i].category =
-                        ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field));
-                }
-            }
+        let best_choice = if blame_source {
+            path.iter().enumerate().rev().min_by_key(|(_, c)| constraint_interest(c)).unwrap().0
+        } else {
+            path.iter().enumerate().min_by_key(|(_, c)| constraint_interest(c)).unwrap().0
+        };
 
-            return (categorized_path[i].clone(), extra_info);
-        }
+        debug!(?best_choice, ?blame_source);
 
-        // If that search fails, that is.. unusual. Maybe everything
-        // is in the same SCC or something. In that case, find what
-        // appears to be the most interesting point to report to the
-        // user via an even more ad-hoc guess.
-        categorized_path.sort_by_key(|p| p.category);
-        debug!("sorted_path={:#?}", categorized_path);
+        let best_constraint = if let Some(next) = path.get(best_choice + 1)
+            && matches!(path[best_choice].category, ConstraintCategory::Return(_))
+            && next.category == ConstraintCategory::OpaqueType
+        {
+            // The return expression is being influenced by the return type being
+            // impl Trait, point at the return type and not the return expr.
+            *next
+        } else if path[best_choice].category == ConstraintCategory::Return(ReturnConstraint::Normal)
+            && let Some(field) = path.iter().find_map(|p| {
+                if let ConstraintCategory::ClosureUpvar(f) = p.category { Some(f) } else { None }
+            })
+        {
+            OutlivesConstraint {
+                category: ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field)),
+                ..path[best_choice]
+            }
+        } else {
+            path[best_choice]
+        };
 
-        (categorized_path.remove(0), extra_info)
+        let blame_constraint = BlameConstraint {
+            category: best_constraint.category,
+            from_closure: best_constraint.from_closure,
+            cause: ObligationCause::new(best_constraint.span, CRATE_DEF_ID, cause_code.clone()),
+            variance_info: best_constraint.variance_info,
+        };
+        (blame_constraint, path)
     }
 
     pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 10fb8a399a2..1eb471968b2 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -298,7 +298,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                         context.ambient_variance(),
                         base_ty.ty,
                         location.to_locations(),
-                        ConstraintCategory::TypeAnnotation,
+                        ConstraintCategory::TypeAnnotation(AnnotationSource::OpaqueCast),
                     )
                     .unwrap();
             }
@@ -333,7 +333,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                 ty::Invariant,
                 &UserTypeProjection { base: annotation_index, projs: vec![] },
                 locations,
-                ConstraintCategory::Boring,
+                ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
             ) {
                 let annotation = &self.typeck.user_type_annotations[annotation_index];
                 span_mirbug!(
@@ -455,7 +455,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                     ty::Invariant,
                     user_ty,
                     Locations::All(*span),
-                    ConstraintCategory::TypeAnnotation,
+                    ConstraintCategory::TypeAnnotation(AnnotationSource::Declaration),
                 ) {
                     span_mirbug!(
                         self,
@@ -892,6 +892,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     Some(l) if !body.local_decls[l].is_user_variable() => {
                         ConstraintCategory::Boring
                     }
+                    Some(_)
+                        if let Some(body_id) = tcx
+                            .hir_node_by_def_id(body.source.def_id().expect_local())
+                            .body_id()
+                            && let params = tcx.hir().body(body_id).params
+                            && params
+                                .iter()
+                                .any(|param| param.span.contains(stmt.source_info.span)) =>
+                    {
+                        // Assignments generated from lowering argument patterns shouldn't be called
+                        // "assignments" in diagnostics and aren't interesting to blame for errors.
+                        ConstraintCategory::Boring
+                    }
                     _ => ConstraintCategory::Assignment,
                 };
                 debug!(
@@ -927,7 +940,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         ty::Invariant,
                         &UserTypeProjection { base: annotation_index, projs: vec![] },
                         location.to_locations(),
-                        ConstraintCategory::Boring,
+                        ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
                     ) {
                         let annotation = &self.user_type_annotations[annotation_index];
                         span_mirbug!(
@@ -962,7 +975,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     *variance,
                     projection,
                     Locations::All(stmt.source_info.span),
-                    ConstraintCategory::TypeAnnotation,
+                    ConstraintCategory::TypeAnnotation(AnnotationSource::Ascription),
                 ) {
                     let annotation = &self.user_type_annotations[projection.base];
                     span_mirbug!(
@@ -1226,6 +1239,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     Some(l) if !body.local_decls[l].is_user_variable() => {
                         ConstraintCategory::Boring
                     }
+                    // The return type of a call is interesting for diagnostics.
                     _ => ConstraintCategory::Assignment,
                 };
 
@@ -2169,7 +2183,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             ty_left,
                             common_ty,
                             location.to_locations(),
-                            ConstraintCategory::Boring,
+                            ConstraintCategory::CallArgument(None),
                         )
                         .unwrap_or_else(|err| {
                             bug!("Could not equate type variable with {:?}: {:?}", ty_left, err)
@@ -2178,7 +2192,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             ty_right,
                             common_ty,
                             location.to_locations(),
-                            ConstraintCategory::Boring,
+                            ConstraintCategory::CallArgument(None),
                         ) {
                             span_mirbug!(
                                 self,
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index e64500f812a..2c34df6ea61 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -6,7 +6,6 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 bitflags = "2.4.1"
-derive-where = "1.2.7"
 either = "1.5.0"
 field-offset = "0.3.5"
 gsgdt = "0.1.2"
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 429be9bc725..db5da941f1e 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -3,7 +3,6 @@
 use std::cell::Cell;
 use std::fmt::{self, Debug};
 
-use derive_where::derive_where;
 use rustc_abi::{FieldIdx, VariantIdx};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::ErrorGuaranteed;
@@ -225,29 +224,22 @@ rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
 /// See also `rustc_const_eval::borrow_check::constraints`.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
 #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
-#[derive_where(PartialOrd, Ord)]
 pub enum ConstraintCategory<'tcx> {
     Return(ReturnConstraint),
     Yield,
     UseAsConst,
     UseAsStatic,
-    TypeAnnotation,
+    TypeAnnotation(AnnotationSource),
     Cast {
         /// Whether this cast is a coercion that was automatically inserted by the compiler.
         is_implicit_coercion: bool,
         /// Whether this is an unsizing coercion and if yes, this contains the target type.
         /// Region variables are erased to ReErased.
-        #[derive_where(skip)]
         unsize_to: Option<Ty<'tcx>>,
     },
 
-    /// A constraint that came from checking the body of a closure.
-    ///
-    /// We try to get the category that the closure used when reporting this.
-    ClosureBounds,
-
     /// Contains the function type if available.
-    CallArgument(#[derive_where(skip)] Option<Ty<'tcx>>),
+    CallArgument(Option<Ty<'tcx>>),
     CopyBound,
     SizedBound,
     Assignment,
@@ -276,13 +268,22 @@ pub enum ConstraintCategory<'tcx> {
     IllegalUniverse,
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
 #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
 pub enum ReturnConstraint {
     Normal,
     ClosureUpvar(FieldIdx),
 }
 
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
+#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
+pub enum AnnotationSource {
+    Ascription,
+    Declaration,
+    OpaqueCast,
+    GenericArg,
+}
+
 /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
 /// that must outlive some region.
 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
diff --git a/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr
index e12d42e5ed0..42d83fca6ca 100644
--- a/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr
+++ b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr
@@ -7,9 +7,9 @@ LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>(
    |        lifetime `'a` defined here
 ...
 LL |     let z: I::A = if cond { x } else { y };
-   |                             ^ assignment requires that `'a` must outlive `'b`
+   |                             ^ assignment requires that `'b` must outlive `'a`
    |
-   = help: consider adding the following bound: `'a: 'b`
+   = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
   --> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:22:40
@@ -20,9 +20,9 @@ LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>(
    |        lifetime `'a` defined here
 ...
 LL |     let z: I::A = if cond { x } else { y };
-   |                                        ^ assignment requires that `'b` must outlive `'a`
+   |                                        ^ assignment requires that `'a` must outlive `'b`
    |
-   = help: consider adding the following bound: `'b: 'a`
+   = help: consider adding the following bound: `'a: 'b`
 
 help: `'a` and `'b` must be the same: replace one with the other
 
diff --git a/tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr b/tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr
index 77841780f62..3ef6b85c407 100644
--- a/tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr
+++ b/tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr
@@ -7,9 +7,9 @@ LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
    |        lifetime `'a` defined here
 LL |     let f = foo; // <-- No consistent type can be inferred for `f` here.
 LL |     let a = bar(f, x);
-   |             ^^^^^^^^^ argument requires that `'a` must outlive `'b`
+   |             ^^^^^^^^^ argument requires that `'b` must outlive `'a`
    |
-   = help: consider adding the following bound: `'a: 'b`
+   = help: consider adding the following bound: `'b: 'a`
    = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant
    = note: the struct `Type<'a>` is invariant over the parameter `'a`
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
@@ -23,9 +23,9 @@ LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
    |        lifetime `'a` defined here
 ...
 LL |     let b = bar(f, y);
-   |             ^^^^^^^^^ argument requires that `'b` must outlive `'a`
+   |             ^^^^^^^^^ argument requires that `'a` must outlive `'b`
    |
-   = help: consider adding the following bound: `'b: 'a`
+   = help: consider adding the following bound: `'a: 'b`
    = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant
    = note: the struct `Type<'a>` is invariant over the parameter `'a`
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
diff --git a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr
index be39dbf313b..329cec6dad3 100644
--- a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr
+++ b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr
@@ -7,7 +7,7 @@ LL |     let c = async || { println!("{}", *x); };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
 LL |     outlives::<'a>(c());
 LL |     outlives::<'a>(call_once(c));
-   |                    ------------ argument requires that `x` is borrowed for `'a`
+   |     ---------------------------- argument requires that `x` is borrowed for `'a`
 ...
 LL | }
    |  - `x` dropped here while still borrowed
@@ -21,10 +21,10 @@ LL | fn simple<'a>(x: &'a i32) {
 LL |     let c = async move || { println!("{}", *x); };
    |         - binding `c` declared here
 LL |     outlives::<'a>(c());
-   |                    ^--
-   |                    |
-   |                    borrowed value does not live long enough
-   |                    argument requires that `c` is borrowed for `'a`
+   |     ---------------^---
+   |     |              |
+   |     |              borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'a`
 LL |     outlives::<'a>(call_once(c));
 LL | }
    | - `c` dropped here while still borrowed
@@ -38,7 +38,7 @@ LL |     let c = async || { println!("{}", *x.0); };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
 LL |     outlives::<'a>(c());
 LL |     outlives::<'a>(call_once(c));
-   |                    ------------ argument requires that `x` is borrowed for `'a`
+   |     ---------------------------- argument requires that `x` is borrowed for `'a`
 ...
 LL | }
    |  - `x` dropped here while still borrowed
@@ -52,7 +52,7 @@ LL |     let c = async || { println!("{}", *x.0); };
    |             ---------------------------------- borrow of `x` occurs here
 LL |     outlives::<'a>(c());
 LL |     outlives::<'a>(call_once(c));
-   |                    ------------ argument requires that `x` is borrowed for `'a`
+   |     ---------------------------- argument requires that `x` is borrowed for `'a`
 LL |
 LL |     let c = async move || { println!("{}", *x.0); };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move out of `x` occurs here
@@ -66,10 +66,10 @@ LL | fn through_field<'a>(x: S<'a>) {
 LL |     let c = async move || { println!("{}", *x.0); };
    |         - binding `c` declared here
 LL |     outlives::<'a>(c());
-   |                    ^--
-   |                    |
-   |                    borrowed value does not live long enough
-   |                    argument requires that `c` is borrowed for `'a`
+   |     ---------------^---
+   |     |              |
+   |     |              borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'a`
 LL |     outlives::<'a>(call_once(c));
 LL | }
    | - `c` dropped here while still borrowed
@@ -83,10 +83,10 @@ LL | fn through_field<'a>(x: S<'a>) {
 LL |     let c = async move || { println!("{}", *x.0); };
    |         - binding `c` declared here
 LL |     outlives::<'a>(c());
-   |                    ---
-   |                    |
-   |                    borrow of `c` occurs here
-   |                    argument requires that `c` is borrowed for `'a`
+   |     -------------------
+   |     |              |
+   |     |              borrow of `c` occurs here
+   |     argument requires that `c` is borrowed for `'a`
 LL |     outlives::<'a>(call_once(c));
    |                              ^ move out of `c` occurs here
 
@@ -99,18 +99,18 @@ LL |     let c = async || { println!("{}", *x.0); };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
 LL |     outlives::<'a>(c());
 LL |     outlives::<'a>(call_once(c));
-   |                    ------------ argument requires that `x` is borrowed for `'a`
+   |     ---------------------------- argument requires that `x` is borrowed for `'a`
 LL | }
    |  - `x` dropped here while still borrowed
 
 error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/without-precise-captures-we-are-powerless.rs:38:20
+  --> $DIR/without-precise-captures-we-are-powerless.rs:38:5
    |
 LL | fn through_field_and_ref<'a>(x: &S<'a>) {
    |                                 ------ help: add explicit lifetime `'a` to the type of `x`: `&'a S<'a>`
 ...
 LL |     outlives::<'a>(call_once(c));
-   |                    ^^^^^^^^^^^^ lifetime `'a` required
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
 
 error[E0597]: `c` does not live long enough
   --> $DIR/without-precise-captures-we-are-powerless.rs:43:20
@@ -120,22 +120,22 @@ LL | fn through_field_and_ref_move<'a>(x: &S<'a>) {
 LL |     let c = async move || { println!("{}", *x.0); };
    |         - binding `c` declared here
 LL |     outlives::<'a>(c());
-   |                    ^--
-   |                    |
-   |                    borrowed value does not live long enough
-   |                    argument requires that `c` is borrowed for `'a`
+   |     ---------------^---
+   |     |              |
+   |     |              borrowed value does not live long enough
+   |     argument requires that `c` is borrowed for `'a`
 LL |     outlives::<'a>(call_once(c));
 LL | }
    | - `c` dropped here while still borrowed
 
 error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/without-precise-captures-we-are-powerless.rs:44:20
+  --> $DIR/without-precise-captures-we-are-powerless.rs:44:5
    |
 LL | fn through_field_and_ref_move<'a>(x: &S<'a>) {
    |                                      ------ help: add explicit lifetime `'a` to the type of `x`: `&'a S<'a>`
 ...
 LL |     outlives::<'a>(call_once(c));
-   |                    ^^^^^^^^^^^^ lifetime `'a` required
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
 
 error: aborting due to 10 previous errors
 
diff --git a/tests/ui/async-await/issues/issue-63388-1.rs b/tests/ui/async-await/issues/issue-63388-1.rs
index a6f499ba94e..acfc64baff9 100644
--- a/tests/ui/async-await/issues/issue-63388-1.rs
+++ b/tests/ui/async-await/issues/issue-63388-1.rs
@@ -11,8 +11,8 @@ impl Xyz {
         &'a self, foo: &dyn Foo
     ) -> &dyn Foo  //~ WARNING elided lifetime has a name
     {
-        //~^ ERROR explicit lifetime required in the type of `foo` [E0621]
         foo
+        //~^ ERROR explicit lifetime required in the type of `foo` [E0621]
     }
 }
 
diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr
index ef74bfe3237..579caa45bc9 100644
--- a/tests/ui/async-await/issues/issue-63388-1.stderr
+++ b/tests/ui/async-await/issues/issue-63388-1.stderr
@@ -10,16 +10,13 @@ LL |     ) -> &dyn Foo
    = note: `#[warn(elided_named_lifetimes)]` on by default
 
 error[E0621]: explicit lifetime required in the type of `foo`
-  --> $DIR/issue-63388-1.rs:13:5
+  --> $DIR/issue-63388-1.rs:14:9
    |
-LL |           &'a self, foo: &dyn Foo
-   |                          -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)`
-LL |       ) -> &dyn Foo
-LL | /     {
-LL | |
-LL | |         foo
-LL | |     }
-   | |_____^ lifetime `'a` required
+LL |         &'a self, foo: &dyn Foo
+   |                        -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)`
+...
+LL |         foo
+   |         ^^^ lifetime `'a` required
 
 error: aborting due to 1 previous error; 1 warning emitted
 
diff --git a/tests/ui/async-await/issues/issue-63388-2.rs b/tests/ui/async-await/issues/issue-63388-2.rs
index 85718f41121..8bb5cfa4a59 100644
--- a/tests/ui/async-await/issues/issue-63388-2.rs
+++ b/tests/ui/async-await/issues/issue-63388-2.rs
@@ -11,8 +11,8 @@ impl Xyz {
         foo: &dyn Foo, bar: &'a dyn Foo
     ) -> &dyn Foo //~ ERROR missing lifetime specifier
     {
-        //~^ ERROR explicit lifetime required in the type of `foo` [E0621]
         foo
+        //~^ ERROR explicit lifetime required in the type of `foo` [E0621]
     }
 }
 
diff --git a/tests/ui/async-await/issues/issue-63388-2.stderr b/tests/ui/async-await/issues/issue-63388-2.stderr
index e515f227c7e..7e3c0a1227d 100644
--- a/tests/ui/async-await/issues/issue-63388-2.stderr
+++ b/tests/ui/async-await/issues/issue-63388-2.stderr
@@ -13,16 +13,13 @@ LL |     ) -> &'a dyn Foo
    |           ++
 
 error[E0621]: explicit lifetime required in the type of `foo`
-  --> $DIR/issue-63388-2.rs:13:5
+  --> $DIR/issue-63388-2.rs:14:9
    |
-LL |           foo: &dyn Foo, bar: &'a dyn Foo
-   |                -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)`
-LL |       ) -> &dyn Foo
-LL | /     {
-LL | |
-LL | |         foo
-LL | |     }
-   | |_____^ lifetime `'a` required
+LL |         foo: &dyn Foo, bar: &'a dyn Foo
+   |              -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)`
+...
+LL |         foo
+   |         ^^^ lifetime `'a` required
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/borrowck/fn-item-check-type-params.stderr b/tests/ui/borrowck/fn-item-check-type-params.stderr
index 3a29edc55c5..aafb7e66ef5 100644
--- a/tests/ui/borrowck/fn-item-check-type-params.stderr
+++ b/tests/ui/borrowck/fn-item-check-type-params.stderr
@@ -12,12 +12,12 @@ LL |     extend_lt(val);
    |     argument requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/fn-item-check-type-params.rs:39:12
+  --> $DIR/fn-item-check-type-params.rs:39:31
    |
 LL | pub fn test_coercion<'a>() {
    |                      -- lifetime `'a` defined here
 LL |     let _: fn(&'a str) -> _ = extend_lt;
-   |            ^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |                               ^^^^^^^^^ coercion requires that `'a` must outlive `'static`
 
 error[E0716]: temporary value dropped while borrowed
   --> $DIR/fn-item-check-type-params.rs:48:11
diff --git a/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr b/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr
index 13c768dcbf6..4ec4d2138db 100644
--- a/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr
+++ b/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr
@@ -15,10 +15,10 @@ LL |     async {
 LL |         let not_static = 0;
    |             ---------- binding `not_static` declared here
 LL |         force_send(async_load(&not_static));
-   |                    -----------^^^^^^^^^^^-
-   |                    |          |
-   |                    |          borrowed value does not live long enough
-   |                    argument requires that `not_static` is borrowed for `'1`
+   |         ----------------------^^^^^^^^^^^--
+   |         |                     |
+   |         |                     borrowed value does not live long enough
+   |         argument requires that `not_static` is borrowed for `'1`
 ...
 LL |     }
    |     - `not_static` dropped here while still borrowed
diff --git a/tests/ui/borrowck/issue-7573.rs b/tests/ui/borrowck/issue-7573.rs
index 7c07411533f..f94cd75ab6e 100644
--- a/tests/ui/borrowck/issue-7573.rs
+++ b/tests/ui/borrowck/issue-7573.rs
@@ -17,6 +17,8 @@ pub fn remove_package_from_database() {
         lines_to_use.push(installed_id);
         //~^ ERROR borrowed data escapes outside of closure
         //~| NOTE `installed_id` escapes the closure body here
+        //~| NOTE requirement occurs because of a mutable reference to `Vec<&CrateId>`
+        //~| NOTE mutable references are invariant over their type parameter
     };
     list_database(push_id);
 
diff --git a/tests/ui/borrowck/issue-7573.stderr b/tests/ui/borrowck/issue-7573.stderr
index 07a67474c83..d0121f4ec17 100644
--- a/tests/ui/borrowck/issue-7573.stderr
+++ b/tests/ui/borrowck/issue-7573.stderr
@@ -9,6 +9,10 @@ LL |     let push_id = |installed_id: &CrateId| {
 LL |
 LL |         lines_to_use.push(installed_id);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `installed_id` escapes the closure body here
+   |
+   = note: requirement occurs because of a mutable reference to `Vec<&CrateId>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr b/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr
index 89b15a7a659..4d1d7ffd293 100644
--- a/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr
+++ b/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr
@@ -71,14 +71,13 @@ error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as imm
 LL | fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) {
    |                     -- lifetime `'a` defined here
 ...
+LL |     let reg = mk_reg();
+   |               -------- assignment requires that `reg.sess_mut` is borrowed for `'a`
 LL |     reg.register_univ(Box::new(CapturePass::new(&reg.sess_mut)));
-   |     ^^^^^^^^^^^^^^^^^^-----------------------------------------^
-   |     |                 |                         |
-   |     |                 |                         immutable borrow occurs here
-   |     |                 coercion requires that `reg.sess_mut` is borrowed for `'a`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^^
+   |     |                                           |
+   |     |                                           immutable borrow occurs here
    |     mutable borrow occurs here
-   |
-   = note: due to object lifetime defaults, `Box<dyn for<'b> LateLintPass<'b>>` actually means `Box<(dyn for<'b> LateLintPass<'b> + 'static)>`
 
 error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable
   --> $DIR/two-phase-surprise-no-conflict.rs:144:5
@@ -115,14 +114,13 @@ error[E0499]: cannot borrow `*reg` as mutable more than once at a time
 LL | fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) {
    |                     -- lifetime `'a` defined here
 ...
+LL |     let reg = mk_reg();
+   |               -------- assignment requires that `reg.sess_mut` is borrowed for `'a`
 LL |     reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
-   |     ^^^^^^^^^^^^^^^^^^-------------------------------------------------^
-   |     |                 |                             |
-   |     |                 |                             first mutable borrow occurs here
-   |     |                 coercion requires that `reg.sess_mut` is borrowed for `'a`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^^
+   |     |                                               |
+   |     |                                               first mutable borrow occurs here
    |     second mutable borrow occurs here
-   |
-   = note: due to object lifetime defaults, `Box<dyn for<'b> LateLintPass<'b>>` actually means `Box<(dyn for<'b> LateLintPass<'b> + 'static)>`
 
 error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:158:53
diff --git a/tests/ui/c-variadic/variadic-ffi-4.stderr b/tests/ui/c-variadic/variadic-ffi-4.stderr
index c9d90d73dea..fc9f8036083 100644
--- a/tests/ui/c-variadic/variadic-ffi-4.stderr
+++ b/tests/ui/c-variadic/variadic-ffi-4.stderr
@@ -120,14 +120,14 @@ LL | }
    | - `ap1` dropped here while still borrowed
 
 error: lifetime may not live long enough
-  --> $DIR/variadic-ffi-4.rs:35:12
+  --> $DIR/variadic-ffi-4.rs:35:5
    |
 LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
    |                                               -------                   ------- has type `VaListImpl<'2>`
    |                                               |
    |                                               has type `&mut VaListImpl<'1>`
 LL |     *ap0 = ap1.clone();
-   |            ^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |     ^^^^ assignment requires that `'2` must outlive `'1`
    |
    = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant
    = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f`
@@ -141,7 +141,7 @@ LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut
    |                                               |
    |                                               has type `&mut VaListImpl<'1>`
 LL |     *ap0 = ap1.clone();
-   |            ^^^^^^^^^^^ argument requires that `'2` must outlive `'1`
+   |            ^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
    |
    = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant
    = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f`
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs
index 18566acc07f..f8910c944c6 100644
--- a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs
+++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs
@@ -42,7 +42,7 @@ fn change_assoc_1<'a, 'b>(
 // This tests the default borrow check error, without the special casing for return values.
 fn require_static(_: *const dyn Trait<'static>) {}
 fn extend_to_static<'a>(ptr: *const dyn Trait<'a>) {
-    require_static(ptr as _) //~ error: lifetime may not live long enough
+    require_static(ptr as _) //~ error: borrowed data escapes outside of function
 }
 
 fn main() {}
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr
index 6f590585c4a..faaa6325f34 100644
--- a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr
+++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr
@@ -154,14 +154,22 @@ help: `'b` and `'a` must be the same: replace one with the other
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: lifetime may not live long enough
-  --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:45:20
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:45:5
    |
 LL | fn extend_to_static<'a>(ptr: *const dyn Trait<'a>) {
-   |                     -- lifetime `'a` defined here
+   |                     --  ---
+   |                     |   |
+   |                     |   `ptr` declared here, outside of the function body
+   |                     |   `ptr` is a reference that is only valid in the function body
+   |                     lifetime `'a` defined here
 LL |     require_static(ptr as _)
-   |                    ^^^^^^^^ cast requires that `'a` must outlive `'static`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     `ptr` escapes the function body here
+   |     argument requires that `'a` must outlive `'static`
 
 error: aborting due to 11 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0308, E0521.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/coroutine/resume-arg-outlives-2.rs b/tests/ui/coroutine/resume-arg-outlives-2.rs
index 387b143ea27..a805cea9b7e 100644
--- a/tests/ui/coroutine/resume-arg-outlives-2.rs
+++ b/tests/ui/coroutine/resume-arg-outlives-2.rs
@@ -18,8 +18,8 @@ fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> {
     // exploit:
     generator.as_mut().resume("");
     generator.as_mut().resume(s); // <- generator hoards it as `let ctx`.
-    //~^ ERROR borrowed data escapes outside of function
     thread::spawn(move || {
+        //~^ ERROR borrowed data escapes outside of function
         thread::sleep(time::Duration::from_millis(200));
         generator.as_mut().resume(""); // <- resumes from the last `yield`, running `dbg!(ctx)`.
     })
diff --git a/tests/ui/coroutine/resume-arg-outlives-2.stderr b/tests/ui/coroutine/resume-arg-outlives-2.stderr
index 3d630d7e7e4..92192d9a557 100644
--- a/tests/ui/coroutine/resume-arg-outlives-2.stderr
+++ b/tests/ui/coroutine/resume-arg-outlives-2.stderr
@@ -1,16 +1,20 @@
 error[E0521]: borrowed data escapes outside of function
-  --> $DIR/resume-arg-outlives-2.rs:20:5
+  --> $DIR/resume-arg-outlives-2.rs:21:5
    |
-LL | fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> {
-   |         -----------  - `s` is a reference that is only valid in the function body
-   |         |
-   |         lifetime `'not_static` defined here
+LL |   fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> {
+   |           -----------  - `s` is a reference that is only valid in the function body
+   |           |
+   |           lifetime `'not_static` defined here
 ...
-LL |     generator.as_mut().resume(s); // <- generator hoards it as `let ctx`.
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |     |
-   |     `s` escapes the function body here
-   |     argument requires that `'not_static` must outlive `'static`
+LL | /     thread::spawn(move || {
+LL | |
+LL | |         thread::sleep(time::Duration::from_millis(200));
+LL | |         generator.as_mut().resume(""); // <- resumes from the last `yield`, running `dbg!(ctx)`.
+LL | |     })
+   | |      ^
+   | |      |
+   | |______`s` escapes the function body here
+   |        argument requires that `'not_static` must outlive `'static`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/fn/fn_def_coercion.rs b/tests/ui/fn/fn_def_coercion.rs
index 313be6f28cd..31c8fa41de1 100644
--- a/tests/ui/fn/fn_def_coercion.rs
+++ b/tests/ui/fn/fn_def_coercion.rs
@@ -46,12 +46,12 @@ fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
 
 fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
     let x = match true {
-        true => foo::<&'c ()>,
+        true => foo::<&'c ()>, //~ ERROR lifetime may not live long enough
         false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough
     };
 
     x(a);
-    x(b); //~ ERROR lifetime may not live long enough
+    x(b);
     x(c);
 }
 
diff --git a/tests/ui/fn/fn_def_coercion.stderr b/tests/ui/fn/fn_def_coercion.stderr
index ec4a1bde7fd..c2776887b79 100644
--- a/tests/ui/fn/fn_def_coercion.stderr
+++ b/tests/ui/fn/fn_def_coercion.stderr
@@ -6,9 +6,9 @@ LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
    |      |
    |      lifetime `'a` defined here
 LL |     let mut x = foo::<&'a ()>;
-   |                 ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
+   |                 ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
    |
-   = help: consider adding the following bound: `'a: 'b`
+   = help: consider adding the following bound: `'b: 'a`
    = note: requirement occurs because of a function pointer to `foo`
    = note: the function `foo` is invariant over the parameter `T`
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
@@ -22,9 +22,9 @@ LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
    |      lifetime `'a` defined here
 LL |     let mut x = foo::<&'a ()>;
 LL |     x = foo::<&'b ()>;
-   |     ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
+   |     ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
    |
-   = help: consider adding the following bound: `'b: 'a`
+   = help: consider adding the following bound: `'a: 'b`
    = note: requirement occurs because of a function pointer to `foo`
    = note: the function `foo` is invariant over the parameter `T`
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
@@ -53,9 +53,9 @@ LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
    |      lifetime `'a` defined here
 LL |     let mut x = foo::<&'c ()>;
 LL |     x = foo::<&'b ()>;
-   |     ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
+   |     ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
    |
-   = help: consider adding the following bound: `'b: 'a`
+   = help: consider adding the following bound: `'a: 'b`
    = note: requirement occurs because of a function pointer to `foo`
    = note: the function `foo` is invariant over the parameter `T`
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
@@ -69,9 +69,9 @@ LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
    |      lifetime `'a` defined here
 ...
 LL |     x = foo::<&'a ()>;
-   |     ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
+   |     ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
    |
-   = help: consider adding the following bound: `'a: 'b`
+   = help: consider adding the following bound: `'b: 'a`
    = note: requirement occurs because of a function pointer to `foo`
    = note: the function `foo` is invariant over the parameter `T`
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
@@ -89,9 +89,9 @@ LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
    |      lifetime `'a` defined here
 LL |     let x = match true {
 LL |         true => foo::<&'b ()>,
-   |                 ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
+   |                 ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
    |
-   = help: consider adding the following bound: `'b: 'a`
+   = help: consider adding the following bound: `'a: 'b`
    = note: requirement occurs because of a function pointer to `foo`
    = note: the function `foo` is invariant over the parameter `T`
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
@@ -105,9 +105,9 @@ LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
    |      lifetime `'a` defined here
 ...
 LL |         false => foo::<&'a ()>,
-   |                  ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
+   |                  ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
    |
-   = help: consider adding the following bound: `'a: 'b`
+   = help: consider adding the following bound: `'b: 'a`
    = note: requirement occurs because of a function pointer to `foo`
    = note: the function `foo` is invariant over the parameter `T`
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
@@ -117,15 +117,15 @@ help: `'a` and `'b` must be the same: replace one with the other
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: lifetime may not live long enough
-  --> $DIR/fn_def_coercion.rs:50:18
+  --> $DIR/fn_def_coercion.rs:49:17
    |
 LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
    |      --      -- lifetime `'c` defined here
    |      |
    |      lifetime `'a` defined here
-...
-LL |         false => foo::<&'a ()>,
-   |                  ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'c`
+LL |     let x = match true {
+LL |         true => foo::<&'c ()>,
+   |                 ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'c`
    |
    = help: consider adding the following bound: `'a: 'c`
    = note: requirement occurs because of a function pointer to `foo`
@@ -133,17 +133,20 @@ LL |         false => foo::<&'a ()>,
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
-  --> $DIR/fn_def_coercion.rs:54:5
+  --> $DIR/fn_def_coercion.rs:50:18
    |
 LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
    |      --  -- lifetime `'b` defined here
    |      |
    |      lifetime `'a` defined here
 ...
-LL |     x(b);
-   |     ^^^^ argument requires that `'b` must outlive `'a`
+LL |         false => foo::<&'a ()>,
+   |                  ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a function pointer to `foo`
+   = note: the function `foo` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 help: the following changes may resolve your lifetime errors
    |
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr
index e57b5af82cd..85e3452fbf2 100644
--- a/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr
@@ -6,7 +6,7 @@ LL | fn g<'a, 'b>() {
    |      |
    |      lifetime `'a` defined here
 LL |     f::<'a, 'b>(());
-   |     ^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
+   |     ^^^^^^^^^^^^^^^ generic argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
    = note: requirement occurs because of a function pointer to `f`
diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr b/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr
index 00709ee7438..945fb0fc618 100644
--- a/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr
+++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr
@@ -6,6 +6,9 @@ LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
    |        |
    |        lifetime `'a` defined here
 ...
+LL |     let u = v;
+   |             - requirement occurs due to copying this value
+...
 LL |         let _: &'b i32 = *u.0;
    |                ^^^^^^^ type annotation requires that `'a` must outlive `'b`
    |
diff --git a/tests/ui/impl-trait/precise-capturing/migration-note.rs b/tests/ui/impl-trait/precise-capturing/migration-note.rs
index 36db07e5764..7587e89409a 100644
--- a/tests/ui/impl-trait/precise-capturing/migration-note.rs
+++ b/tests/ui/impl-trait/precise-capturing/migration-note.rs
@@ -29,11 +29,11 @@ fn needs_static() {
     let a = display_len(&x);
     //~^ ERROR `x` does not live long enough
     //~| NOTE this call may capture more lifetimes than intended
-    //~| NOTE argument requires that `x` is borrowed for `'static`
     //~| NOTE borrowed value does not live long enoug
 
     fn needs_static(_: impl Sized + 'static) {}
     needs_static(a);
+    //~^ NOTE argument requires that `x` is borrowed for `'static`
 }
 //~^ NOTE `x` dropped here while still borrowed
 
@@ -76,11 +76,11 @@ fn needs_static_mut() {
     let a = display_len_mut(&mut x);
     //~^ ERROR `x` does not live long enough
     //~| NOTE this call may capture more lifetimes than intended
-    //~| NOTE argument requires that `x` is borrowed for `'static`
     //~| NOTE borrowed value does not live long enough
 
     fn needs_static(_: impl Sized + 'static) {}
     needs_static(a);
+    //~^ NOTE argument requires that `x` is borrowed for `'static`
 }
 //~^ NOTE `x` dropped here while still borrowed
 
diff --git a/tests/ui/impl-trait/precise-capturing/migration-note.stderr b/tests/ui/impl-trait/precise-capturing/migration-note.stderr
index c9403532dfa..9caf7a201ef 100644
--- a/tests/ui/impl-trait/precise-capturing/migration-note.stderr
+++ b/tests/ui/impl-trait/precise-capturing/migration-note.stderr
@@ -42,11 +42,11 @@ LL |     let x = vec![1];
    |         - binding `x` declared here
 LL |
 LL |     let a = display_len(&x);
-   |             ------------^^-
-   |             |           |
-   |             |           borrowed value does not live long enough
-   |             argument requires that `x` is borrowed for `'static`
+   |                         ^^ borrowed value does not live long enough
 ...
+LL |     needs_static(a);
+   |     --------------- argument requires that `x` is borrowed for `'static`
+LL |
 LL | }
    | - `x` dropped here while still borrowed
    |
@@ -118,11 +118,11 @@ LL |     let mut x = vec![1];
    |         ----- binding `x` declared here
 LL |
 LL |     let a = display_len_mut(&mut x);
-   |             ----------------^^^^^^-
-   |             |               |
-   |             |               borrowed value does not live long enough
-   |             argument requires that `x` is borrowed for `'static`
+   |                             ^^^^^^ borrowed value does not live long enough
 ...
+LL |     needs_static(a);
+   |     --------------- argument requires that `x` is borrowed for `'static`
+LL |
 LL | }
    | - `x` dropped here while still borrowed
    |
diff --git a/tests/ui/inline-const/const-expr-lifetime-err.stderr b/tests/ui/inline-const/const-expr-lifetime-err.stderr
index be3fc8d28c5..031bf98262a 100644
--- a/tests/ui/inline-const/const-expr-lifetime-err.stderr
+++ b/tests/ui/inline-const/const-expr-lifetime-err.stderr
@@ -6,10 +6,9 @@ LL | fn foo<'a>() {
 LL |     let y = ();
    |         - binding `y` declared here
 LL |     equate(InvariantRef::new(&y), const { InvariantRef::<'a>::NEW });
-   |            ------------------^^-
-   |            |                 |
-   |            |                 borrowed value does not live long enough
-   |            argument requires that `y` is borrowed for `'a`
+   |                              ^^           ----------------------- using this value as a constant requires that `y` is borrowed for `'a`
+   |                              |
+   |                              borrowed value does not live long enough
 LL |
 LL | }
    | - `y` dropped here while still borrowed
diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr b/tests/ui/inline-const/const-match-pat-lifetime-err.stderr
index 95fe7085e50..7eea1846057 100644
--- a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr
+++ b/tests/ui/inline-const/const-match-pat-lifetime-err.stderr
@@ -9,7 +9,7 @@ LL |     match InvariantRef::new(&y) {
    |                             ^^ borrowed value does not live long enough
 LL |
 LL |         const { InvariantRef::<'a>::NEW } => (),
-   |         --------------------------------- type annotation requires that `y` is borrowed for `'a`
+   |                 ----------------------- using this value as a constant requires that `y` is borrowed for `'a`
 LL |     }
 LL | }
    | - `y` dropped here while still borrowed
diff --git a/tests/ui/kindck/kindck-impl-type-params.stderr b/tests/ui/kindck/kindck-impl-type-params.stderr
index a0a4ef09216..d375aa9cb59 100644
--- a/tests/ui/kindck/kindck-impl-type-params.stderr
+++ b/tests/ui/kindck/kindck-impl-type-params.stderr
@@ -112,13 +112,13 @@ LL |     struct Foo; // does not impl Copy
    |
 
 error: lifetime may not live long enough
-  --> $DIR/kindck-impl-type-params.rs:30:19
+  --> $DIR/kindck-impl-type-params.rs:30:13
    |
 LL | fn foo<'a>() {
    |        -- lifetime `'a` defined here
 LL |     let t: S<&'a isize> = S(marker::PhantomData);
 LL |     let a = &t as &dyn Gettable<&'a isize>;
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'a` must outlive `'static`
 
 error: aborting due to 7 previous errors
 
diff --git a/tests/ui/lifetimes/copy_modulo_regions.stderr b/tests/ui/lifetimes/copy_modulo_regions.stderr
index 310ddb21647..0d69f0323d6 100644
--- a/tests/ui/lifetimes/copy_modulo_regions.stderr
+++ b/tests/ui/lifetimes/copy_modulo_regions.stderr
@@ -4,7 +4,10 @@ error: lifetime may not live long enough
 LL | fn foo<'a>() -> [Foo<'a>; 100] {
    |        -- lifetime `'a` defined here
 LL |     [mk_foo::<'a>(); 100]
-   |     ^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     returning this value requires that `'a` must outlive `'static`
+   |     requirement occurs due to copying this value
    |
    = note: requirement occurs because of the type `Foo<'_>`, which makes the generic argument `'_` invariant
    = note: the struct `Foo<'a>` is invariant over the parameter `'a`
diff --git a/tests/ui/lifetimes/issue-90170-elision-mismatch.stderr b/tests/ui/lifetimes/issue-90170-elision-mismatch.stderr
index 82511d07b0e..5e16c57a618 100644
--- a/tests/ui/lifetimes/issue-90170-elision-mismatch.stderr
+++ b/tests/ui/lifetimes/issue-90170-elision-mismatch.stderr
@@ -7,6 +7,9 @@ LL | pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); }
    |                        |        let's call the lifetime of this reference `'1`
    |                        let's call the lifetime of this reference `'2`
    |
+   = note: requirement occurs because of a mutable reference to `Vec<&u8>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 help: consider introducing a named lifetime parameter
    |
 LL | pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
@@ -21,6 +24,9 @@ LL | pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); }
    |                         |           let's call the lifetime of this reference `'1`
    |                         let's call the lifetime of this reference `'2`
    |
+   = note: requirement occurs because of a mutable reference to `Vec<&u8>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 help: consider introducing a named lifetime parameter
    |
 LL | pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
@@ -35,6 +41,9 @@ LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); }
    |                                               |        let's call the lifetime of this reference `'1`
    |                                               let's call the lifetime of this reference `'2`
    |
+   = note: requirement occurs because of a mutable reference to `Vec<&u8>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 help: consider reusing a named lifetime parameter
    |
 LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
diff --git a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.rs b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.rs
index ce4cddc9b39..30a1811fee5 100644
--- a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.rs
+++ b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.rs
@@ -7,9 +7,9 @@ fn inner(mut foo: &[u8]) {
     let refcell = RefCell::new(&mut foo);
     //~^ ERROR `foo` does not live long enough
     let read = &refcell as &RefCell<dyn Read>;
-    //~^ ERROR lifetime may not live long enough
 
     read_thing(read);
+    //~^ ERROR borrowed data escapes outside of function
 }
 
 fn read_thing(refcell: &RefCell<dyn Read>) {}
diff --git a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr
index e4cd54ac337..4df2e906e22 100644
--- a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr
+++ b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr
@@ -5,22 +5,32 @@ LL | fn inner(mut foo: &[u8]) {
    |          ------- binding `foo` declared here
 LL |     let refcell = RefCell::new(&mut foo);
    |                                ^^^^^^^^ borrowed value does not live long enough
-LL |
-LL |     let read = &refcell as &RefCell<dyn Read>;
-   |                ------------------------------ cast requires that `foo` is borrowed for `'static`
 ...
+LL |     read_thing(read);
+   |     ---------------- argument requires that `foo` is borrowed for `'static`
+LL |
 LL | }
    |  - `foo` dropped here while still borrowed
 
-error: lifetime may not live long enough
-  --> $DIR/issue-90600-expected-return-static-indirect.rs:9:16
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/issue-90600-expected-return-static-indirect.rs:11:5
    |
 LL | fn inner(mut foo: &[u8]) {
-   |                   - let's call the lifetime of this reference `'1`
+   |          -------  - let's call the lifetime of this reference `'1`
+   |          |
+   |          `foo` is a reference that is only valid in the function body
 ...
-LL |     let read = &refcell as &RefCell<dyn Read>;
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static`
+LL |     read_thing(read);
+   |     ^^^^^^^^^^^^^^^^
+   |     |
+   |     `foo` escapes the function body here
+   |     argument requires that `'1` must outlive `'static`
+   |
+   = note: requirement occurs because of the type `RefCell<(dyn std::io::Read + 'static)>`, which makes the generic argument `(dyn std::io::Read + 'static)` invariant
+   = note: the struct `RefCell<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0597`.
+Some errors have detailed explanations: E0521, E0597.
+For more information about an error, try `rustc --explain E0521`.
diff --git a/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr b/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr
index 6f7127d4c4c..a187cb755dd 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr
@@ -8,6 +8,9 @@ LL | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
 LL |     x.push(y);
    |     ^^^^^^^^^ argument requires that `'1` must outlive `'2`
    |
+   = note: requirement occurs because of a mutable reference to `Vec<Ref<'_, i32>>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 help: consider introducing a named lifetime parameter
    |
 LL | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<'a, i32>) {
diff --git a/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr b/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr
index cace80272f5..610a669cded 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr
@@ -10,6 +10,9 @@ LL |     x.push(z);
    |     ^^^^^^^^^ argument requires that `'c` must outlive `'b`
    |
    = help: consider adding the following bound: `'c: 'b`
+   = note: requirement occurs because of a mutable reference to `Vec<Ref<'_, i32>>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs b/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs
index f573230293e..4cd06e1c02b 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs
+++ b/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs
@@ -4,9 +4,9 @@ struct Ref<'a, T: 'a> {
 
 fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
     let a: &mut Vec<Ref<i32>> = x;
+    //~^ ERROR lifetime may not live long enough
     let b = Ref { data: y.data };
     a.push(b);
-    //~^ ERROR lifetime may not live long enough
 }
 
 fn main() { }
diff --git a/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr
index 4a981e4de60..0da32aacdb3 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr
@@ -1,15 +1,17 @@
 error: lifetime may not live long enough
-  --> $DIR/ex2d-push-inference-variable-2.rs:8:5
+  --> $DIR/ex2d-push-inference-variable-2.rs:6:33
    |
 LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
    |            --  -- lifetime `'c` defined here
    |            |
    |            lifetime `'b` defined here
-...
-LL |     a.push(b);
-   |     ^^^^^^^^^ argument requires that `'c` must outlive `'b`
+LL |     let a: &mut Vec<Ref<i32>> = x;
+   |                                 ^ assignment requires that `'c` must outlive `'b`
    |
    = help: consider adding the following bound: `'c: 'b`
+   = note: requirement occurs because of a mutable reference to `Vec<Ref<'_, i32>>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs b/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs
index 4a934bbf080..498cea36824 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs
+++ b/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs
@@ -4,9 +4,9 @@ struct Ref<'a, T: 'a> {
 
 fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
     let a: &mut Vec<Ref<i32>> = x;
+    //~^ ERROR lifetime may not live long enough
     let b = Ref { data: y.data };
     Vec::push(a, b);
-    //~^ ERROR lifetime may not live long enough
 }
 
 fn main() { }
diff --git a/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr
index 2bd047113bc..4474a898fdc 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr
@@ -1,15 +1,17 @@
 error: lifetime may not live long enough
-  --> $DIR/ex2e-push-inference-variable-3.rs:8:5
+  --> $DIR/ex2e-push-inference-variable-3.rs:6:33
    |
 LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
    |            --  -- lifetime `'c` defined here
    |            |
    |            lifetime `'b` defined here
-...
-LL |     Vec::push(a, b);
-   |     ^^^^^^^^^^^^^^^ argument requires that `'c` must outlive `'b`
+LL |     let a: &mut Vec<Ref<i32>> = x;
+   |                                 ^ assignment requires that `'c` must outlive `'b`
    |
    = help: consider adding the following bound: `'c: 'b`
+   = note: requirement occurs because of a mutable reference to `Vec<Ref<'_, i32>>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr
index 6ba130308a3..c67ea19effc 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr
@@ -8,6 +8,9 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
 LL |     z.push((x,y));
    |     ^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
    |
+   = note: requirement occurs because of a mutable reference to `Vec<(&u8, &u8)>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 help: consider introducing a named lifetime parameter
    |
 LL | fn foo<'a>(z: &mut Vec<(&'a u8,&u8)>, (x, y): (&'a u8, &u8)) {
@@ -23,6 +26,9 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
 LL |     z.push((x,y));
    |     ^^^^^^^^^^^^^ argument requires that `'3` must outlive `'4`
    |
+   = note: requirement occurs because of a mutable reference to `Vec<(&u8, &u8)>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 help: consider introducing a named lifetime parameter
    |
 LL | fn foo<'a>(z: &mut Vec<(&u8,&'a u8)>, (x, y): (&u8, &'a u8)) {
diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr
index 352619c0ffc..0980b37e535 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr
@@ -10,6 +10,9 @@ LL |     x.push(y);
    |     ^^^^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable reference to `Vec<Ref<'_>>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr
index 16cf009ee48..16cd47420a5 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr
@@ -9,6 +9,9 @@ LL |     x.push(y);
    |     ^^^^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable reference to `Vec<Ref<'_>>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr
index 017bfa71463..264673ff3e8 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr
@@ -8,6 +8,9 @@ LL | fn foo(mut x: Vec<Ref>, y: Ref) {
 LL |     x.push(y);
    |     ^^^^^^^^^ argument requires that `'1` must outlive `'2`
    |
+   = note: requirement occurs because of a mutable reference to `Vec<Ref<'_>>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 help: consider introducing a named lifetime parameter
    |
 LL | fn foo<'a>(mut x: Vec<Ref<'a>>, y: Ref<'a>) {
diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr
index 080eb43cecb..8552755d168 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr
@@ -9,6 +9,9 @@ LL |     x.push(y);
    |     ^^^^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable reference to `Vec<&u8>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr
index cb629d2e3d3..2a2cf6508fd 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr
@@ -19,6 +19,9 @@ LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) {
 LL |   y.push(z);
    |   ^^^^^^^^^ argument requires that `'1` must outlive `'2`
    |
+   = note: requirement occurs because of a mutable reference to `Vec<&u8>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 help: consider introducing a named lifetime parameter
    |
 LL | fn foo<'a>(x:fn(&u8, &u8), y: Vec<&'a u8>, z: &'a u8) {
diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr
index 420cfa6b569..01bfe782920 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr
@@ -8,6 +8,9 @@ LL |     fn foo(x: &mut Vec<&u8>, y: &u8) {
 LL |         x.push(y);
    |         ^^^^^^^^^ argument requires that `'1` must outlive `'2`
    |
+   = note: requirement occurs because of a mutable reference to `Vec<&u8>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 help: consider introducing a named lifetime parameter and update trait if needed
    |
 LL |     fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) {
diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr
index 05f9308124b..41154755b5d 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr
@@ -19,6 +19,9 @@ LL | fn foo(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
 LL |   y.push(z);
    |   ^^^^^^^^^ argument requires that `'1` must outlive `'2`
    |
+   = note: requirement occurs because of a mutable reference to `Vec<&u8>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 help: consider introducing a named lifetime parameter
    |
 LL | fn foo<'a>(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&'a u8>, z: &'a u8) {
diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr
index 875d22576e5..10e8ca852f0 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr
@@ -8,6 +8,9 @@ LL | fn foo(x: &mut Vec<&u8>, y: &u8) {
 LL |     x.push(y);
    |     ^^^^^^^^^ argument requires that `'1` must outlive `'2`
    |
+   = note: requirement occurs because of a mutable reference to `Vec<&u8>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 help: consider introducing a named lifetime parameter
    |
 LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) {
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
index f37ce967a1b..60087ec992b 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -23,6 +23,10 @@ LL |         |_outlives1, _outlives2, _outlives3, x, y| {
 ...
 LL |             demand_y(x, y, p)
    |             ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |
+   = note: requirement occurs because of the type `Cell<&'?34 u32>`, which makes the generic argument `&'?34 u32` invariant
+   = note: the struct `Cell<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 note: no external requirements
   --> $DIR/propagate-approximated-fail-no-postdom.rs:38:1
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.rs b/tests/ui/nll/closure-requirements/propagate-approximated-ref.rs
index 1c27e38f832..f4db723704c 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-ref.rs
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-ref.rs
@@ -41,9 +41,10 @@ fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u3
 #[rustc_regions]
 fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+        //~^ ERROR lifetime may not live long enough
+
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
-        //~^ ERROR lifetime may not live long enough
     });
 }
 
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr
index e2d0b105ab1..7325a9de8b2 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -23,17 +23,21 @@ LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
    = note: defining type: supply
 
 error: lifetime may not live long enough
-  --> $DIR/propagate-approximated-ref.rs:45:9
+  --> $DIR/propagate-approximated-ref.rs:43:5
    |
-LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
-   |           --  -- lifetime `'b` defined here
-   |           |
-   |           lifetime `'a` defined here
-...
-LL |         demand_y(x, y, x.get())
-   |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
+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 | |     });
+   | |______^ argument requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of the type `Cell<&'?11 u32>`, which makes the generic argument `&'?11 u32` invariant
+   = note: the struct `Cell<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
index d7933a39eaa..0094d7a50d3 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -19,6 +19,10 @@ LL |     foo(cell, |cell_a, cell_x| {
    |                `cell_a` declared here, outside of the closure body
 LL |         cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here
+   |
+   = note: requirement occurs because of the type `Cell<&'?8 u32>`, which makes the generic argument `&'?8 u32` invariant
+   = note: the struct `Cell<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 note: no external requirements
   --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:18:1
@@ -56,11 +60,11 @@ error[E0597]: `a` does not live long enough
 LL |     let a = 0;
    |         - binding `a` declared here
 LL |     let cell = Cell::new(&a);
-   |                ----------^^-
-   |                |         |
-   |                |         borrowed value does not live long enough
-   |                argument requires that `a` is borrowed for `'static`
+   |                          ^^ borrowed value does not live long enough
 ...
+LL |         cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error
+   |         ------------------------ argument requires that `a` is borrowed for `'static`
+LL |     })
 LL | }
    | - `a` dropped here while still borrowed
 
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs
index 25e212a7225..afabb69ec4c 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs
@@ -30,10 +30,9 @@ fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u3
 #[rustc_regions]
 fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
-        //~^ ERROR borrowed data escapes outside of function
-
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
+        //~^ ERROR borrowed data escapes outside of function
     });
 }
 
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
index 3c04cf300ad..b9365c94a1b 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -23,23 +23,18 @@ LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
    = note: defining type: supply
 
 error[E0521]: borrowed data escapes outside of function
-  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:32:5
+  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:34:9
    |
-LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
-   |             --      ------ `cell_a` is a reference that is only valid in the function body
-   |             |
-   |             lifetime `'a` defined here
-LL | /     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
-...  |
-LL | |     });
-   | |      ^
-   | |      |
-   | |______`cell_a` escapes the function body here
-   |        argument requires that `'a` must outlive `'static`
-   |
-   = note: requirement occurs because of the type `Cell<&'?9 u32>`, which makes the generic argument `&'?9 u32` invariant
-   = note: the struct `Cell<T>` is invariant over the parameter `T`
-   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |           --      ------ `cell_a` is a reference that is only valid in the function body
+   |           |
+   |           lifetime `'a` defined here
+...
+LL |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         `cell_a` escapes the function body here
+   |         argument requires that `'a` must outlive `'static`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs
index cda7b22362f..9f3e80d3db6 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs
@@ -33,10 +33,9 @@ fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u3
 #[rustc_regions]
 fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-        //~^ ERROR borrowed data escapes outside of function
-
         // Only works if 'x: 'y:
         demand_y(x, y, x.get())
+        //~^ ERROR borrowed data escapes outside of function
     });
 }
 
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
index 9f5762ccbfa..e5d2867103c 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -23,23 +23,18 @@ LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
    = note: defining type: supply
 
 error[E0521]: borrowed data escapes outside of function
-  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:35:5
+  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:37:9
    |
-LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
-   |             --      ------ `cell_a` is a reference that is only valid in the function body
-   |             |
-   |             lifetime `'a` defined here
-LL | /     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-...  |
-LL | |     });
-   | |      ^
-   | |      |
-   | |______`cell_a` escapes the function body here
-   |        argument requires that `'a` must outlive `'static`
-   |
-   = note: requirement occurs because of the type `Cell<&'?10 u32>`, which makes the generic argument `&'?10 u32` invariant
-   = note: the struct `Cell<T>` is invariant over the parameter `T`
-   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+   |           --      ------ `cell_a` is a reference that is only valid in the function body
+   |           |
+   |           lifetime `'a` defined here
+...
+LL |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         `cell_a` escapes the function body here
+   |         argument requires that `'a` must outlive `'static`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.rs b/tests/ui/nll/closure-requirements/propagate-approximated-val.rs
index e7e2f157604..4d663c53d27 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-val.rs
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-val.rs
@@ -34,9 +34,10 @@ fn demand_y<'x, 'y>(_outlives1: Cell<&&'x u32>, _outlives2: Cell<&'y &u32>, _y:
 #[rustc_regions]
 fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
     establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
+        //~^ ERROR lifetime may not live long enough
+
         // Only works if 'x: 'y:
         demand_y(outlives1, outlives2, x.get())
-        //~^ ERROR lifetime may not live long enough
     });
 }
 
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr
index 4787577a6e1..a14bfb06e83 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -23,17 +23,21 @@ LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
    = note: defining type: test
 
 error: lifetime may not live long enough
-  --> $DIR/propagate-approximated-val.rs:38:9
+  --> $DIR/propagate-approximated-val.rs:36:5
    |
-LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
-   |         --  -- lifetime `'b` defined here
-   |         |
-   |         lifetime `'a` defined here
-...
-LL |         demand_y(outlives1, outlives2, x.get())
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
+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 | |     });
+   | |______^ argument requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of the type `Cell<&'?7 u32>`, which makes the generic argument `&'?7 u32` invariant
+   = note: the struct `Cell<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
index 669b56a0be7..4558ff50674 100644
--- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -22,6 +22,10 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
 LL |         // Only works if 'x: 'y:
 LL |         demand_y(x, y, x.get())
    |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |
+   = note: requirement occurs because of the type `Cell<&'?37 u32>`, which makes the generic argument `&'?37 u32` invariant
+   = note: the struct `Cell<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 note: no external requirements
   --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:34:1
diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
index 75f476ac5f1..83173ae80c0 100644
--- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -22,6 +22,10 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
 LL |         // Only works if 'x: 'y:
 LL |         demand_y(x, y, x.get())
    |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |
+   = note: requirement occurs because of the type `Cell<&'?43 u32>`, which makes the generic argument `&'?43 u32` invariant
+   = note: the struct `Cell<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 note: no external requirements
   --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:38:1
diff --git a/tests/ui/nll/issue-54779-anon-static-lifetime.rs b/tests/ui/nll/issue-54779-anon-static-lifetime.rs
index 260b6b109ca..6b8fa608ebb 100644
--- a/tests/ui/nll/issue-54779-anon-static-lifetime.rs
+++ b/tests/ui/nll/issue-54779-anon-static-lifetime.rs
@@ -29,7 +29,7 @@ impl DebugWith<dyn DebugContext> for Foo {
         fmt: &mut std::fmt::Formatter<'_>,
     ) -> std::fmt::Result {
         let Foo { bar } = self;
-        bar.debug_with(cx); //~ ERROR: lifetime may not live long enough
+        bar.debug_with(cx); //~ borrowed data escapes outside of method
         Ok(())
     }
 }
diff --git a/tests/ui/nll/issue-54779-anon-static-lifetime.stderr b/tests/ui/nll/issue-54779-anon-static-lifetime.stderr
index a454ed26568..03a55906614 100644
--- a/tests/ui/nll/issue-54779-anon-static-lifetime.stderr
+++ b/tests/ui/nll/issue-54779-anon-static-lifetime.stderr
@@ -1,11 +1,17 @@
-error: lifetime may not live long enough
-  --> $DIR/issue-54779-anon-static-lifetime.rs:32:24
+error[E0521]: borrowed data escapes outside of method
+  --> $DIR/issue-54779-anon-static-lifetime.rs:32:9
    |
 LL |         cx: &dyn DebugContext,
-   |             - let's call the lifetime of this reference `'1`
+   |         --  - let's call the lifetime of this reference `'1`
+   |         |
+   |         `cx` is a reference that is only valid in the method body
 ...
 LL |         bar.debug_with(cx);
-   |                        ^^ coercion requires that `'1` must outlive `'static`
+   |         ^^^^^^^^^^^^^^^^^^
+   |         |
+   |         `cx` escapes the method body here
+   |         argument requires that `'1` must outlive `'static`
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0521`.
diff --git a/tests/ui/nll/issue-62007-assign-const-index.stderr b/tests/ui/nll/issue-62007-assign-const-index.stderr
index 0db9fe62c38..32716c47cd4 100644
--- a/tests/ui/nll/issue-62007-assign-const-index.stderr
+++ b/tests/ui/nll/issue-62007-assign-const-index.stderr
@@ -17,10 +17,9 @@ LL | fn to_refs<T>(mut list: [&mut List<T>; 2]) -> Vec<&mut T> {
    |                          - let's call the lifetime of this reference `'1`
 ...
 LL |         if let Some(n) = list[0].next.as_mut() {
-   |                          ^^^^^^^^^^^^---------
-   |                          |
-   |                          `list[_].next` was mutably borrowed here in the previous iteration of the loop
-   |                          argument requires that `list[_].next` is borrowed for `'1`
+   |                          ^^^^^^^^^^^^ `list[_].next` was mutably borrowed here in the previous iteration of the loop
+LL |             list[0] = n;
+   |             ----------- assignment requires that `list[_].next` is borrowed for `'1`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/nll/issue-62007-assign-differing-fields.stderr b/tests/ui/nll/issue-62007-assign-differing-fields.stderr
index f1af2e855af..d51fd7a1389 100644
--- a/tests/ui/nll/issue-62007-assign-differing-fields.stderr
+++ b/tests/ui/nll/issue-62007-assign-differing-fields.stderr
@@ -17,10 +17,9 @@ LL | fn to_refs<'a, T>(mut list: (&'a mut List<T>, &'a mut List<T>)) -> Vec<&'a
    |            -- lifetime `'a` defined here
 ...
 LL |         if let Some(n) = (list.0).next.as_mut() {
-   |                          ^^^^^^^^^^^^^---------
-   |                          |
-   |                          `list.0.next` was mutably borrowed here in the previous iteration of the loop
-   |                          argument requires that `list.0.next` is borrowed for `'a`
+   |                          ^^^^^^^^^^^^^ `list.0.next` was mutably borrowed here in the previous iteration of the loop
+LL |             list.1 = n;
+   |             ---------- assignment requires that `list.0.next` is borrowed for `'a`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/nll/issue-67007-escaping-data.rs b/tests/ui/nll/issue-67007-escaping-data.rs
index 49ea2e5964f..92a47f78843 100644
--- a/tests/ui/nll/issue-67007-escaping-data.rs
+++ b/tests/ui/nll/issue-67007-escaping-data.rs
@@ -12,8 +12,8 @@ struct Consumer<'tcx>(&'tcx ());
 
 impl<'tcx> Consumer<'tcx> {
     fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) {
-        let other = self.use_fcx(fcx); //~ ERROR lifetime may not live long enough
-        fcx.use_it(other);
+        let other = self.use_fcx(fcx);
+        fcx.use_it(other); //~ ERROR lifetime may not live long enough
     }
 
     fn use_fcx<'a>(&self, _: &FnCtxt<'a, 'tcx>) -> &'a () {
diff --git a/tests/ui/nll/issue-67007-escaping-data.stderr b/tests/ui/nll/issue-67007-escaping-data.stderr
index eb7b57c7e99..3b9ed246851 100644
--- a/tests/ui/nll/issue-67007-escaping-data.stderr
+++ b/tests/ui/nll/issue-67007-escaping-data.stderr
@@ -1,14 +1,18 @@
 error: lifetime may not live long enough
-  --> $DIR/issue-67007-escaping-data.rs:15:21
+  --> $DIR/issue-67007-escaping-data.rs:16:9
    |
 LL | impl<'tcx> Consumer<'tcx> {
    |      ---- lifetime `'tcx` defined here
 LL |     fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) {
    |                   -- lifetime `'a` defined here
 LL |         let other = self.use_fcx(fcx);
-   |                     ^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'tcx`
+LL |         fcx.use_it(other);
+   |         ^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'tcx`
    |
    = help: consider adding the following bound: `'a: 'tcx`
+   = note: requirement occurs because of the type `FnCtxt<'_, '_>`, which makes the generic argument `'_` invariant
+   = note: the struct `FnCtxt<'a, 'tcx>` is invariant over the parameter `'tcx`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/nll/issue-95272.rs b/tests/ui/nll/issue-95272.rs
index 958cbde3788..b3325a05e5c 100644
--- a/tests/ui/nll/issue-95272.rs
+++ b/tests/ui/nll/issue-95272.rs
@@ -8,8 +8,8 @@ where
 
 fn test<'a, 'b>(x: Cell<&'a ()>, y: Cell<&'b ()>) {
     let f = check;
-    //~^ ERROR lifetime may not live long enough
     f(x, y);
+    //~^ ERROR lifetime may not live long enough
 }
 
 fn main() {}
diff --git a/tests/ui/nll/issue-95272.stderr b/tests/ui/nll/issue-95272.stderr
index 0453ef8e53e..3d1720239e9 100644
--- a/tests/ui/nll/issue-95272.stderr
+++ b/tests/ui/nll/issue-95272.stderr
@@ -1,16 +1,17 @@
 error: lifetime may not live long enough
-  --> $DIR/issue-95272.rs:10:13
+  --> $DIR/issue-95272.rs:11:5
    |
 LL | fn test<'a, 'b>(x: Cell<&'a ()>, y: Cell<&'b ()>) {
    |         --  -- lifetime `'b` defined here
    |         |
    |         lifetime `'a` defined here
 LL |     let f = check;
-   |             ^^^^^ assignment requires that `'a` must outlive `'b`
+LL |     f(x, y);
+   |     ^^^^^^^ argument requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
-   = note: requirement occurs because of a function pointer to `check`
-   = note: the function `check` is invariant over the parameter `'a`
+   = note: requirement occurs because of the type `Cell<&()>`, which makes the generic argument `&()` invariant
+   = note: the struct `Cell<T>` is invariant over the parameter `T`
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/nll/issue-98589-closures-relate-named-regions.stderr b/tests/ui/nll/issue-98589-closures-relate-named-regions.stderr
index 4e741abc2dc..4f244b54bd0 100644
--- a/tests/ui/nll/issue-98589-closures-relate-named-regions.stderr
+++ b/tests/ui/nll/issue-98589-closures-relate-named-regions.stderr
@@ -11,14 +11,14 @@ LL |     || { None::<&'a &'b ()>; };
    = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
-  --> $DIR/issue-98589-closures-relate-named-regions.rs:15:10
+  --> $DIR/issue-98589-closures-relate-named-regions.rs:15:5
    |
 LL | fn test_early_late<'a: 'a, 'b>() {
    |                    --      -- lifetime `'b` defined here
    |                    |
    |                    lifetime `'a` defined here
 LL |     || { None::<&'a &'b ()>; };
-   |          ^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
 
diff --git a/tests/ui/nll/outlives-suggestion-simple.stderr b/tests/ui/nll/outlives-suggestion-simple.stderr
index bcffd575aed..669532005b2 100644
--- a/tests/ui/nll/outlives-suggestion-simple.stderr
+++ b/tests/ui/nll/outlives-suggestion-simple.stderr
@@ -99,6 +99,10 @@ LL |     fn get_bar(&self) -> Bar2 {
    |                - let's call the lifetime of this reference `'1`
 LL |         Bar2::new(&self)
    |         ^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a`
+   |
+   = note: requirement occurs because of the type `Foo2<'_>`, which makes the generic argument `'_` invariant
+   = note: the struct `Foo2<'a>` is invariant over the parameter `'a`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 9 previous errors
 
diff --git a/tests/ui/nll/polonius/assignment-to-differing-field.stderr b/tests/ui/nll/polonius/assignment-to-differing-field.stderr
index acac47eac4f..c46d010e4f5 100644
--- a/tests/ui/nll/polonius/assignment-to-differing-field.stderr
+++ b/tests/ui/nll/polonius/assignment-to-differing-field.stderr
@@ -17,10 +17,10 @@ LL | fn assignment_to_field_projection<'a, T>(
    |                                   -- lifetime `'a` defined here
 ...
 LL |         if let Some(n) = (list.0).next.as_mut() {
-   |                          ^^^^^^^^^^^^^---------
-   |                          |
-   |                          `list.0.next` was mutably borrowed here in the previous iteration of the loop
-   |                          argument requires that `list.0.next` is borrowed for `'a`
+   |                          ^^^^^^^^^^^^^ `list.0.next` was mutably borrowed here in the previous iteration of the loop
+LL |
+LL |             list.1 = n;
+   |             ---------- assignment requires that `list.0.next` is borrowed for `'a`
 
 error[E0499]: cannot borrow `list.0.0.0.0.0.value` as mutable more than once at a time
   --> $DIR/assignment-to-differing-field.rs:37:21
@@ -41,10 +41,10 @@ LL | fn assignment_through_projection_chain<'a, T>(
    |                                        -- lifetime `'a` defined here
 ...
 LL |         if let Some(n) = ((((list.0).0).0).0).0.next.as_mut() {
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^---------
-   |                          |
-   |                          `list.0.0.0.0.0.next` was mutably borrowed here in the previous iteration of the loop
-   |                          argument requires that `list.0.0.0.0.0.next` is borrowed for `'a`
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `list.0.0.0.0.0.next` was mutably borrowed here in the previous iteration of the loop
+LL |
+LL |             *((((list.0).0).0).0).1 = n;
+   |             --------------------------- assignment requires that `list.0.0.0.0.0.next` is borrowed for `'a`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/nll/relate_tys/var-appears-twice.stderr b/tests/ui/nll/relate_tys/var-appears-twice.stderr
index 3f9a6cec0d2..2b2ec88ba8e 100644
--- a/tests/ui/nll/relate_tys/var-appears-twice.stderr
+++ b/tests/ui/nll/relate_tys/var-appears-twice.stderr
@@ -5,9 +5,10 @@ LL |     let b = 44;
    |         - binding `b` declared here
 ...
 LL |     let x: DoubleCell<_> = make_cell(&b);
-   |            -------------             ^^ borrowed value does not live long enough
-   |            |
-   |            type annotation requires that `b` is borrowed for `'static`
+   |                            ----------^^-
+   |                            |         |
+   |                            |         borrowed value does not live long enough
+   |                            assignment requires that `b` is borrowed for `'static`
 ...
 LL | }
    | - `b` dropped here while still borrowed
diff --git a/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr b/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr
index dda60398198..408c57a31ee 100644
--- a/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr
+++ b/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr
@@ -24,6 +24,22 @@ LL | |     T: Anything<'b>,
    |
    = note: defining type: no_relationships_late::<'?1, T>
 
+error: lifetime may not live long enough
+  --> $DIR/projection-one-region-closure.rs:45:5
+   |
+LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                          --  -- lifetime `'b` defined here
+   |                          |
+   |                          lifetime `'a` defined here
+...
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of the type `Cell<&'?6 ()>`, which makes the generic argument `&'?6 ()` invariant
+   = note: the struct `Cell<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/projection-one-region-closure.rs:45:39
    |
@@ -38,19 +54,6 @@ help: consider adding an explicit lifetime bound
 LL |     T: Anything<'b> + 'a,
    |                     ++++
 
-error: lifetime may not live long enough
-  --> $DIR/projection-one-region-closure.rs:45:39
-   |
-LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
-   |                          --  -- lifetime `'b` defined here
-   |                          |
-   |                          lifetime `'a` defined here
-...
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                                       ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
 note: external requirements
   --> $DIR/projection-one-region-closure.rs:56:29
    |
@@ -77,6 +80,22 @@ LL | |     'a: 'a,
    |
    = note: defining type: no_relationships_early::<'?1, '?2, T>
 
+error: lifetime may not live long enough
+  --> $DIR/projection-one-region-closure.rs:56:5
+   |
+LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+   |                           --  -- lifetime `'b` defined here
+   |                           |
+   |                           lifetime `'a` defined here
+...
+LL |     with_signature(cell, t, |cell, t| require(cell, t));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of the type `Cell<&'?7 ()>`, which makes the generic argument `&'?7 ()` invariant
+   = note: the struct `Cell<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/projection-one-region-closure.rs:56:39
    |
@@ -91,19 +110,6 @@ help: consider adding an explicit lifetime bound
 LL |     T: Anything<'b> + 'a,
    |                     ++++
 
-error: lifetime may not live long enough
-  --> $DIR/projection-one-region-closure.rs:56:39
-   |
-LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
-   |                           --  -- lifetime `'b` defined here
-   |                           |
-   |                           lifetime `'a` defined here
-...
-LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                                       ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
 note: external requirements
   --> $DIR/projection-one-region-closure.rs:70:29
    |
diff --git a/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
index 52040663e00..4ebdf10c5bf 100644
--- a/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
+++ b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
@@ -24,7 +24,7 @@ LL | |     T: Anything<'b>,
    = note: defining type: no_relationships_late::<'?1, T>
 
 error: lifetime may not live long enough
-  --> $DIR/projection-one-region-trait-bound-closure.rs:37:39
+  --> $DIR/projection-one-region-trait-bound-closure.rs:37:5
    |
 LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                          --  -- lifetime `'b` defined here
@@ -32,9 +32,12 @@ 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`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of the type `Cell<&'?6 ()>`, which makes the generic argument `&'?6 ()` invariant
+   = note: the struct `Cell<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 note: external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:47:29
@@ -62,7 +65,7 @@ LL | |     'a: 'a,
    = note: defining type: no_relationships_early::<'?1, '?2, T>
 
 error: lifetime may not live long enough
-  --> $DIR/projection-one-region-trait-bound-closure.rs:47:39
+  --> $DIR/projection-one-region-trait-bound-closure.rs:47:5
    |
 LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                           --  -- lifetime `'b` defined here
@@ -70,9 +73,12 @@ 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`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of the type `Cell<&'?7 ()>`, which makes the generic argument `&'?7 ()` invariant
+   = note: the struct `Cell<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 note: external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:60:29
diff --git a/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
index c157e89ff8f..f8dbe08af61 100644
--- a/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
+++ b/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
@@ -182,7 +182,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
-   = note: requirement occurs because of the type `Cell<&'?8 ()>`, which makes the generic argument `&'?8 ()` invariant
+   = note: requirement occurs because of the type `Cell<&'?6 ()>`, which makes the generic argument `&'?6 ()` invariant
    = note: the struct `Cell<T>` is invariant over the parameter `T`
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
diff --git a/tests/ui/nll/type-check-pointer-comparisons.stderr b/tests/ui/nll/type-check-pointer-comparisons.stderr
index 37098b585df..e362dfb3c6e 100644
--- a/tests/ui/nll/type-check-pointer-comparisons.stderr
+++ b/tests/ui/nll/type-check-pointer-comparisons.stderr
@@ -6,7 +6,7 @@ LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
    |                  |
    |                  lifetime `'a` defined here
 LL |     x == y;
-   |     ^ requires that `'a` must outlive `'b`
+   |     ^^^^^^ argument requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
    = note: requirement occurs because of a mutable reference to `&i32`
@@ -14,14 +14,14 @@ LL |     x == y;
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
-  --> $DIR/type-check-pointer-comparisons.rs:4:10
+  --> $DIR/type-check-pointer-comparisons.rs:4:5
    |
 LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
    |                  --  -- lifetime `'b` defined here
    |                  |
    |                  lifetime `'a` defined here
 LL |     x == y;
-   |          ^ requires that `'b` must outlive `'a`
+   |     ^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
    = note: requirement occurs because of a mutable reference to `&i32`
@@ -38,7 +38,7 @@ LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
    |                |
    |                lifetime `'a` defined here
 LL |     x == y;
-   |     ^ requires that `'a` must outlive `'b`
+   |     ^^^^^^ argument requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
    = note: requirement occurs because of a mutable pointer to `&i32`
@@ -46,14 +46,14 @@ LL |     x == y;
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
-  --> $DIR/type-check-pointer-comparisons.rs:10:10
+  --> $DIR/type-check-pointer-comparisons.rs:10:5
    |
 LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
    |                --  -- lifetime `'b` defined here
    |                |
    |                lifetime `'a` defined here
 LL |     x == y;
-   |          ^ requires that `'b` must outlive `'a`
+   |     ^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
    = note: requirement occurs because of a mutable pointer to `&i32`
@@ -72,7 +72,7 @@ LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32
    |                   |
    |                   lifetime `'a` defined here
 LL |     f == g;
-   |     ^ requires that `'a` must outlive `'b`
+   |     ^^^^^^ argument requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
    = note: requirement occurs because of a mutable reference to `&i32`
@@ -80,14 +80,14 @@ LL |     f == g;
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
-  --> $DIR/type-check-pointer-comparisons.rs:16:10
+  --> $DIR/type-check-pointer-comparisons.rs:16:5
    |
 LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) {
    |                   --  -- lifetime `'b` defined here
    |                   |
    |                   lifetime `'a` defined here
 LL |     f == g;
-   |          ^ requires that `'b` must outlive `'a`
+   |     ^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
    = note: requirement occurs because of a mutable reference to `&i32`
diff --git a/tests/ui/nll/user-annotations/adt-nullary-enums.stderr b/tests/ui/nll/user-annotations/adt-nullary-enums.stderr
index 644fc94f730..cdaa934122c 100644
--- a/tests/ui/nll/user-annotations/adt-nullary-enums.stderr
+++ b/tests/ui/nll/user-annotations/adt-nullary-enums.stderr
@@ -1,52 +1,49 @@
 error[E0597]: `c` does not live long enough
   --> $DIR/adt-nullary-enums.rs:33:41
    |
-LL |     let c = 66;
-   |         - binding `c` declared here
-LL |     combine(
-LL |         SomeEnum::SomeVariant(Cell::new(&c)),
-   |                               ----------^^-
-   |                               |         |
-   |                               |         borrowed value does not live long enough
-   |                               argument requires that `c` is borrowed for `'static`
-...
-LL | }
-   | - `c` dropped here while still borrowed
+LL |       let c = 66;
+   |           - binding `c` declared here
+LL | /     combine(
+LL | |         SomeEnum::SomeVariant(Cell::new(&c)),
+   | |                                         ^^ borrowed value does not live long enough
+LL | |         SomeEnum::SomeOtherVariant::<Cell<&'static u32>>,
+LL | |     );
+   | |_____- argument requires that `c` is borrowed for `'static`
+LL |   }
+   |   - `c` dropped here while still borrowed
 
 error[E0597]: `c` does not live long enough
   --> $DIR/adt-nullary-enums.rs:41:41
    |
-LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
-   |                                   -- lifetime `'a` defined here
-LL |     let c = 66;
-   |         - binding `c` declared here
-LL |     combine(
-LL |         SomeEnum::SomeVariant(Cell::new(&c)),
-   |                               ----------^^-
-   |                               |         |
-   |                               |         borrowed value does not live long enough
-   |                               argument requires that `c` is borrowed for `'a`
-...
-LL | }
-   | - `c` dropped here while still borrowed
+LL |   fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
+   |                                     -- lifetime `'a` defined here
+LL |       let c = 66;
+   |           - binding `c` declared here
+LL | /     combine(
+LL | |         SomeEnum::SomeVariant(Cell::new(&c)),
+   | |                                         ^^ borrowed value does not live long enough
+LL | |         SomeEnum::SomeOtherVariant::<Cell<&'a u32>>,
+LL | |     );
+   | |_____- argument requires that `c` is borrowed for `'a`
+LL |   }
+   |   - `c` dropped here while still borrowed
 
 error[E0597]: `c` does not live long enough
   --> $DIR/adt-nullary-enums.rs:54:45
    |
-LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
-   |                                              -- lifetime `'a` defined here
-LL |     let _closure = || {
-LL |         let c = 66;
-   |             - binding `c` declared here
-LL |         combine(
-LL |             SomeEnum::SomeVariant(Cell::new(&c)),
-   |                                   ----------^^-
-   |                                   |         |
-   |                                   |         borrowed value does not live long enough
-   |                                   argument requires that `c` is borrowed for `'a`
-...
-LL |     };
-   |     - `c` dropped here while still borrowed
+LL |   fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
+   |                                                -- lifetime `'a` defined here
+LL |       let _closure = || {
+LL |           let c = 66;
+   |               - binding `c` declared here
+LL | /         combine(
+LL | |             SomeEnum::SomeVariant(Cell::new(&c)),
+   | |                                             ^^ borrowed value does not live long enough
+LL | |             SomeEnum::SomeOtherVariant::<Cell<&'a u32>>,
+LL | |         );
+   | |_________- argument requires that `c` is borrowed for `'a`
+LL |       };
+   |       - `c` dropped here while still borrowed
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr
index 2084697e7e2..1478ad1431b 100644
--- a/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr
+++ b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr
@@ -4,11 +4,9 @@ error[E0597]: `c` does not live long enough
 LL |     let c = 66;
    |         - binding `c` declared here
 LL |     let f = SomeStruct::<&'static u32>;
+   |             -------------------------- assignment requires that `c` is borrowed for `'static`
 LL |     f(&c);
-   |     --^^-
-   |     | |
-   |     | borrowed value does not live long enough
-   |     argument requires that `c` is borrowed for `'static`
+   |       ^^ borrowed value does not live long enough
 LL | }
    | - `c` dropped here while still borrowed
 
@@ -20,11 +18,9 @@ LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
 LL |     let c = 66;
    |         - binding `c` declared here
 LL |     let f = SomeStruct::<&'a u32>;
+   |             --------------------- assignment requires that `c` is borrowed for `'a`
 LL |     f(&c);
-   |     --^^-
-   |     | |
-   |     | borrowed value does not live long enough
-   |     argument requires that `c` is borrowed for `'a`
+   |       ^^ borrowed value does not live long enough
 LL | }
    | - `c` dropped here while still borrowed
 
@@ -37,11 +33,9 @@ LL |     let _closure = || {
 LL |         let c = 66;
    |             - binding `c` declared here
 LL |         let f = SomeStruct::<&'a u32>;
+   |                 --------------------- assignment requires that `c` is borrowed for `'a`
 LL |         f(&c);
-   |         --^^-
-   |         | |
-   |         | borrowed value does not live long enough
-   |         argument requires that `c` is borrowed for `'a`
+   |           ^^ borrowed value does not live long enough
 LL |     };
    |     - `c` dropped here while still borrowed
 
diff --git a/tests/ui/nll/user-annotations/method-ufcs-1.stderr b/tests/ui/nll/user-annotations/method-ufcs-1.stderr
index c42ea0172cf..087e270c70f 100644
--- a/tests/ui/nll/user-annotations/method-ufcs-1.stderr
+++ b/tests/ui/nll/user-annotations/method-ufcs-1.stderr
@@ -4,11 +4,10 @@ error[E0597]: `a` does not live long enough
 LL |     let a = 22;
    |         - binding `a` declared here
 ...
+LL |     let x = <&'static u32 as Bazoom<_>>::method;
+   |             ----------------------------------- assignment requires that `a` is borrowed for `'static`
 LL |     x(&a, b, c);
-   |     --^^-------
-   |     | |
-   |     | borrowed value does not live long enough
-   |     argument requires that `a` is borrowed for `'static`
+   |       ^^ borrowed value does not live long enough
 LL | }
    | - `a` dropped here while still borrowed
 
diff --git a/tests/ui/nll/user-annotations/method-ufcs-2.stderr b/tests/ui/nll/user-annotations/method-ufcs-2.stderr
index 287337c7d52..c89bed3b1b1 100644
--- a/tests/ui/nll/user-annotations/method-ufcs-2.stderr
+++ b/tests/ui/nll/user-annotations/method-ufcs-2.stderr
@@ -4,11 +4,10 @@ error[E0597]: `a` does not live long enough
 LL |     let a = 22;
    |         - binding `a` declared here
 ...
+LL |     let x = <&'static u32 as Bazoom<_>>::method;
+   |             ----------------------------------- assignment requires that `a` is borrowed for `'static`
 LL |     x(&a, b, c);
-   |     --^^-------
-   |     | |
-   |     | borrowed value does not live long enough
-   |     argument requires that `a` is borrowed for `'static`
+   |       ^^ borrowed value does not live long enough
 LL | }
    | - `a` dropped here while still borrowed
 
diff --git a/tests/ui/nll/where_clauses_in_structs.stderr b/tests/ui/nll/where_clauses_in_structs.stderr
index 4cc7e5ab1b4..19a1ce00e9a 100644
--- a/tests/ui/nll/where_clauses_in_structs.stderr
+++ b/tests/ui/nll/where_clauses_in_structs.stderr
@@ -1,12 +1,12 @@
 error: lifetime may not live long enough
-  --> $DIR/where_clauses_in_structs.rs:11:11
+  --> $DIR/where_clauses_in_structs.rs:11:14
    |
 LL | fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) {
    |        --  -- lifetime `'b` defined here
    |        |
    |        lifetime `'a` defined here
 LL |     Foo { x, y };
-   |           ^ this usage requires that `'a` must outlive `'b`
+   |              ^ this usage requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
    = note: requirement occurs because of the type `Cell<&u32>`, which makes the generic argument `&u32` invariant
diff --git a/tests/ui/regions/better-blame-constraint-for-outlives-static.rs b/tests/ui/regions/better-blame-constraint-for-outlives-static.rs
new file mode 100644
index 00000000000..77cadb78301
--- /dev/null
+++ b/tests/ui/regions/better-blame-constraint-for-outlives-static.rs
@@ -0,0 +1,13 @@
+//! diagnostic test for #132749: ensure we pick a decent span and reason to blame for region errors
+//! when failing to prove a region outlives 'static
+
+struct Bytes(&'static [u8]);
+
+fn deserialize_simple_string(buf: &[u8]) -> (Bytes, &[u8]) {
+    //~^ NOTE let's call the lifetime of this reference `'1`
+    let (s, rest) = buf.split_at(2);
+    (Bytes(s), rest) //~ ERROR lifetime may not live long enough
+    //~| NOTE this usage requires that `'1` must outlive `'static`
+}
+
+fn main() {}
diff --git a/tests/ui/regions/better-blame-constraint-for-outlives-static.stderr b/tests/ui/regions/better-blame-constraint-for-outlives-static.stderr
new file mode 100644
index 00000000000..e1e88829f2c
--- /dev/null
+++ b/tests/ui/regions/better-blame-constraint-for-outlives-static.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+  --> $DIR/better-blame-constraint-for-outlives-static.rs:9:12
+   |
+LL | fn deserialize_simple_string(buf: &[u8]) -> (Bytes, &[u8]) {
+   |                                   - let's call the lifetime of this reference `'1`
+...
+LL |     (Bytes(s), rest)
+   |            ^ this usage requires that `'1` must outlive `'static`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.stderr b/tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.stderr
index fcd0a232a7b..9f1315070eb 100644
--- a/tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.stderr
+++ b/tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.stderr
@@ -25,6 +25,10 @@ LL |         self.enter_scope(|ctx| {
    |                           has type `&mut FooImpl<'2, '_, T>`
 LL |             BarImpl(ctx);
    |                     ^^^ this usage requires that `'1` must outlive `'2`
+   |
+   = note: requirement occurs because of a mutable reference to `FooImpl<'_, '_, T>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
   --> $DIR/lifetime-not-long-enough-suggestion-regression-test-124563.rs:22:9
diff --git a/tests/ui/regions/region-invariant-static-error-reporting.rs b/tests/ui/regions/region-invariant-static-error-reporting.rs
index 9ab46a77578..e58eea3f61a 100644
--- a/tests/ui/regions/region-invariant-static-error-reporting.rs
+++ b/tests/ui/regions/region-invariant-static-error-reporting.rs
@@ -3,7 +3,7 @@
 // over time, but this test used to exhibit some pretty bogus messages
 // that were not remotely helpful.
 
-//@ error-pattern:argument requires that `'a` must outlive `'static`
+//@ error-pattern:requires that `'a` must outlive `'static`
 
 struct Invariant<'a>(Option<&'a mut &'a mut ()>);
 
@@ -11,9 +11,9 @@ fn mk_static() -> Invariant<'static> { Invariant(None) }
 
 fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) {
     let bad = if x.is_some() {
-        x.unwrap() //~ ERROR borrowed data escapes outside of function [E0521]
+        x.unwrap()
     } else {
-        mk_static()
+        mk_static() //~ ERROR lifetime may not live long enough
     };
     f(bad);
 }
diff --git a/tests/ui/regions/region-invariant-static-error-reporting.stderr b/tests/ui/regions/region-invariant-static-error-reporting.stderr
index 834d5c6cf5a..2ccf36713ae 100644
--- a/tests/ui/regions/region-invariant-static-error-reporting.stderr
+++ b/tests/ui/regions/region-invariant-static-error-reporting.stderr
@@ -1,16 +1,11 @@
-error[E0521]: borrowed data escapes outside of function
-  --> $DIR/region-invariant-static-error-reporting.rs:14:9
+error: lifetime may not live long enough
+  --> $DIR/region-invariant-static-error-reporting.rs:16:9
    |
 LL | fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) {
-   |          --  - `x` is a reference that is only valid in the function body
-   |          |
-   |          lifetime `'a` defined here
-LL |     let bad = if x.is_some() {
-LL |         x.unwrap()
-   |         ^^^^^^^^^^
-   |         |
-   |         `x` escapes the function body here
-   |         argument requires that `'a` must outlive `'static`
+   |          -- lifetime `'a` defined here
+...
+LL |         mk_static()
+   |         ^^^^^^^^^^^ assignment requires that `'a` must outlive `'static`
    |
    = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
    = note: the struct `Invariant<'a>` is invariant over the parameter `'a`
@@ -18,4 +13,3 @@ LL |         x.unwrap()
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0521`.
diff --git a/tests/ui/traits/coercion-generic-regions.stderr b/tests/ui/traits/coercion-generic-regions.stderr
index 576035f8c13..c48767095df 100644
--- a/tests/ui/traits/coercion-generic-regions.stderr
+++ b/tests/ui/traits/coercion-generic-regions.stderr
@@ -4,11 +4,9 @@ error[E0597]: `person` does not live long enough
 LL |     let person = "Fred".to_string();
    |         ------ binding `person` declared here
 LL |     let person: &str = &person;
-   |                        ^^^^^^^
-   |                        |
-   |                        borrowed value does not live long enough
-   |                        assignment requires that `person` is borrowed for `'static`
+   |                        ^^^^^^^ borrowed value does not live long enough
 LL |     let s: Box<dyn Trait<&'static str>> = Box::new(Struct { person: person });
+   |                                                                     ------ this usage requires that `person` is borrowed for `'static`
 LL | }
    | - `person` dropped here while still borrowed
 
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr
index 0a969b611e9..01b8da645f3 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr
@@ -1,10 +1,10 @@
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-3.rs:11:18
+  --> $DIR/type-checking-test-3.rs:11:13
    |
 LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
    |                -- lifetime `'a` defined here
 LL |     let _ = x as &dyn Bar<'a>; // Error
-   |                  ^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |             ^^^^^^^^^^^^^^^^^ cast requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
   --> $DIR/type-checking-test-3.rs:16:18
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
index 090120a2327..e91ea193a01 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
@@ -1,10 +1,10 @@
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:19:18
+  --> $DIR/type-checking-test-4.rs:19:13
    |
 LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
    |                -- lifetime `'a` defined here
 LL |     let _ = x as &dyn Bar<'static, 'a>; // Error
-   |                  ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
   --> $DIR/type-checking-test-4.rs:24:18
diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr
index 40d34140245..e2f48f37f0d 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr
@@ -7,6 +7,10 @@ LL |     doit(0, &|x, y| {
    |               has type `&Cell<&'2 i32>`
 LL |         x.set(y);
    |         ^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |
+   = note: requirement occurs because of the type `Cell<&i32>`, which makes the generic argument `&i32` invariant
+   = note: the struct `Cell<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr b/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr
index ed9d22d2558..8bd9b1112c5 100644
--- a/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr
+++ b/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr
@@ -7,6 +7,9 @@ LL | fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); }
    |                    |           let's call the lifetime of this reference `'1`
    |                    let's call the lifetime of this reference `'2`
    |
+   = note: requirement occurs because of a mutable reference to `Vec<&u8>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 help: consider introducing a named lifetime parameter
    |
 LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
diff --git a/tests/ui/variance/variance-associated-types2.stderr b/tests/ui/variance/variance-associated-types2.stderr
index 158b09b0630..292d60941b1 100644
--- a/tests/ui/variance/variance-associated-types2.stderr
+++ b/tests/ui/variance/variance-associated-types2.stderr
@@ -1,10 +1,10 @@
 error: lifetime may not live long enough
-  --> $DIR/variance-associated-types2.rs:13:12
+  --> $DIR/variance-associated-types2.rs:13:42
    |
 LL | fn take<'a>(_: &'a u32) {
    |         -- lifetime `'a` defined here
 LL |     let _: Box<dyn Foo<Bar = &'a u32>> = make();
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |                                          ^^^^^^ coercion requires that `'a` must outlive `'static`
 
 error: aborting due to 1 previous error