about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-11-18 22:08:31 +0000
committerbors <bors@rust-lang.org>2019-11-18 22:08:31 +0000
commit0ccee30773050f6bf50fd6ceb9ac61e6d58aa4d8 (patch)
treedef8d2158300c8de61bada8c86b8fc835f02ed5e
parent3e525e3f6d9e85d54fa4c49b52df85aa0c990100 (diff)
parentcba0761e5f3677b90390fe7aee1eeda684296658 (diff)
downloadrust-0ccee30773050f6bf50fd6ceb9ac61e6d58aa4d8.tar.gz
rust-0ccee30773050f6bf50fd6ceb9ac61e6d58aa4d8.zip
Auto merge of #58281 - mark-i-m:synthesis, r=estebank
Add outlives suggestions for some lifetime errors

This PR implements suggestion diagnostics for some lifetime mismatch errors. When the borrow checker finds that some lifetime 'a doesn't outlive some other lifetime 'b that it should outlive, then in addition to the current lifetime error, we also emit a suggestion for how to fix the problem by adding a bound:

- If a and b are normal named regions, suggest to add the bound `'a: 'b`
- If b is static, suggest to replace a with static
- If b also needs to outlive a, they must be the same, so suggest unifying  them

We start with a simpler implementation that avoids diagnostic regression or implementation complexity:
- We only makes suggestions for lifetimes the user can already name (eg not closure regions or elided regions)
- For now, we only emit a help note, not an actually suggestion because it is significantly easier.

Finally, there is one hack: it seems that implicit regions in async fn are given the name '_ incorrectly. To avoid suggesting '_: 'x, we simply filter out such lifetimes by name.

For more info, see this internals thread:

https://internals.rust-lang.org/t/mechanical-suggestions-for-some-borrow-checker-errors/9049/3

TL;DR Make suggestions to add a `where 'a: 'b` constraint for some lifetime errors. Details are in the paper linked from the internals thread above.

r? @estebank

TODO
- [x] Clean up code
- [x] Only make idiomatic suggestions
     - [x] don't suggest naming `&'a self`
     - [x] rather than `'a: 'static`, suggest replacing `'a` with `'static`
     - [x] rather than `'a: 'b, 'b: 'a`, suggest replacing `'a` with `'b` or vice versa
- [x] Performance (maybe need a perf run when this is closer to the finish line?)
     - perf run was clean...
     - EDIT: perf run seems to only check non-error performance... How do we check that error performance didn't regress?
- [x] Needs ui tests
- [x] Integrate the `help` message into the main lifetime `error`
-rw-r--r--src/librustc_errors/diagnostic.rs16
-rw-r--r--src/librustc_errors/lib.rs5
-rw-r--r--src/librustc_mir/borrow_check/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs25
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/outlives_suggestion.rs317
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/mod.rs12
-rw-r--r--src/test/ui/associated-type-bounds/implied-region-constraints.nll.stderr4
-rw-r--r--src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.nll.stderr6
-rw-r--r--src/test/ui/associated-types/associated-types-subtyping-1.nll.stderr4
-rw-r--r--src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr6
-rw-r--r--src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr2
-rw-r--r--src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr6
-rw-r--r--src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr6
-rw-r--r--src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr2
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr2
-rw-r--r--src/test/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.nll.stderr2
-rw-r--r--src/test/ui/closures/closure-expected-type/expect-region-supply-region.nll.stderr2
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr4
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr2
-rw-r--r--src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr2
-rw-r--r--src/test/ui/impl-header-lifetime-elision/dyn-trait.nll.stderr2
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr1
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr4
-rw-r--r--src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr1
-rw-r--r--src/test/ui/in-band-lifetimes/mismatched.nll.stderr2
-rw-r--r--src/test/ui/issues/issue-10291.nll.stderr2
-rw-r--r--src/test/ui/issues/issue-26217.nll.stderr2
-rw-r--r--src/test/ui/issues/issue-28848.nll.stderr2
-rw-r--r--src/test/ui/issues/issue-52213.nll.stderr2
-rw-r--r--src/test/ui/issues/issue-54943.nll.stderr2
-rw-r--r--src/test/ui/issues/issue-55796.nll.stderr4
-rw-r--r--src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr4
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr2
-rw-r--r--src/test/ui/lub-if.nll.stderr4
-rw-r--r--src/test/ui/lub-match.nll.stderr4
-rw-r--r--src/test/ui/match/match-ref-mut-invariance.nll.stderr2
-rw-r--r--src/test/ui/match/match-ref-mut-let-invariance.nll.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr2
-rw-r--r--src/test/ui/nll/issue-50716.nll.stderr2
-rw-r--r--src/test/ui/nll/issue-52113.stderr2
-rw-r--r--src/test/ui/nll/issue-55401.nll.stderr2
-rw-r--r--src/test/ui/nll/issue-58299.stderr4
-rw-r--r--src/test/ui/nll/mir_check_cast_closure.stderr2
-rw-r--r--src/test/ui/nll/mir_check_cast_reify.stderr2
-rw-r--r--src/test/ui/nll/mir_check_cast_unsafe_fn.stderr2
-rw-r--r--src/test/ui/nll/mir_check_cast_unsize.stderr2
-rw-r--r--src/test/ui/nll/outlives-suggestion-more.rs28
-rw-r--r--src/test/ui/nll/outlives-suggestion-more.stderr100
-rw-r--r--src/test/ui/nll/outlives-suggestion-simple.rs77
-rw-r--r--src/test/ui/nll/outlives-suggestion-simple.stderr108
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr4
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr4
-rw-r--r--src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr2
-rw-r--r--src/test/ui/nll/ty-outlives/wf-unreachable.stderr16
-rw-r--r--src/test/ui/nll/type-check-pointer-coercions.stderr18
-rw-r--r--src/test/ui/nll/type-check-pointer-comparisons.stderr18
-rw-r--r--src/test/ui/nll/user-annotations/closure-substs.stderr4
-rw-r--r--src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.nll.stderr2
-rw-r--r--src/test/ui/nll/user-annotations/constant-in-expr-normalize.nll.stderr2
-rw-r--r--src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.nll.stderr2
-rw-r--r--src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.nll.stderr2
-rw-r--r--src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.nll.stderr2
-rw-r--r--src/test/ui/nll/user-annotations/inherent-associated-constants.stderr2
-rw-r--r--src/test/ui/nll/user-annotations/issue-54124.stderr2
-rw-r--r--src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr6
-rw-r--r--src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr8
-rw-r--r--src/test/ui/nll/user-annotations/patterns.stderr8
-rw-r--r--src/test/ui/nll/user-annotations/wf-self-type.stderr2
-rw-r--r--src/test/ui/nll/where_clauses_in_functions.stderr2
-rw-r--r--src/test/ui/nll/where_clauses_in_structs.stderr2
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-elision.nll.stderr2
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr2
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr2
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-mybox.nll.stderr4
-rw-r--r--src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr2
-rw-r--r--src/test/ui/regions/region-object-lifetime-2.nll.stderr2
-rw-r--r--src/test/ui/regions/region-object-lifetime-4.nll.stderr2
-rw-r--r--src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-bounded-by-trait-requiring-static.nll.stderr12
-rw-r--r--src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-bounded-method-type-parameters.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-bounds.nll.stderr4
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-2.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-4.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-close-over-type-parameter-multiple.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-creating-enums3.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-creating-enums4.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-early-bound-error-method.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-early-bound-error.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr4
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-caller.migrate.nll.stderr6
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-caller.nll.stderr6
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-incorrect.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-infer-contravariance-due-to-decl.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-infer-covariance-due-to-decl.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-infer-invariance-due-to-decl.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-infer-not-param.nll.stderr8
-rw-r--r--src/test/ui/regions/regions-nested-fns.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr4
-rw-r--r--src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr4
-rw-r--r--src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-outlives-projection-container.nll.stderr8
-rw-r--r--src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-static-bound.migrate.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-static-bound.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-trait-object-subtyping.nll.stderr4
-rw-r--r--src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-variance-contravariant-use-covariant.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-variance-covariant-use-contravariant.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-variance-invariant-use-contravariant.nll.stderr2
-rw-r--r--src/test/ui/regions/regions-variance-invariant-use-covariant.nll.stderr2
-rw-r--r--src/test/ui/variance/variance-btree-invariant-types.nll.stderr24
-rw-r--r--src/test/ui/variance/variance-cell-is-invariant.nll.stderr2
-rw-r--r--src/test/ui/variance/variance-contravariant-arg-object.nll.stderr4
-rw-r--r--src/test/ui/variance/variance-contravariant-arg-trait-match.nll.stderr4
-rw-r--r--src/test/ui/variance/variance-contravariant-self-trait-match.nll.stderr4
-rw-r--r--src/test/ui/variance/variance-covariant-arg-object.nll.stderr4
-rw-r--r--src/test/ui/variance/variance-covariant-arg-trait-match.nll.stderr4
-rw-r--r--src/test/ui/variance/variance-covariant-self-trait-match.nll.stderr4
-rw-r--r--src/test/ui/variance/variance-invariant-arg-object.nll.stderr4
-rw-r--r--src/test/ui/variance/variance-invariant-arg-trait-match.nll.stderr4
-rw-r--r--src/test/ui/variance/variance-invariant-self-trait-match.nll.stderr4
-rw-r--r--src/test/ui/variance/variance-use-contravariant-struct-1.nll.stderr2
-rw-r--r--src/test/ui/variance/variance-use-covariant-struct-1.nll.stderr2
-rw-r--r--src/test/ui/variance/variance-use-invariant-struct-1.nll.stderr4
-rw-r--r--src/test/ui/wf/wf-static-method.nll.stderr12
143 files changed, 1144 insertions, 6 deletions
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index 5a09898f18f..b9af4aae550 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -6,7 +6,7 @@ use crate::Applicability;
 use crate::Level;
 use crate::snippet::Style;
 use std::fmt;
-use syntax_pos::{MultiSpan, Span};
+use syntax_pos::{MultiSpan, Span, DUMMY_SP};
 
 #[must_use]
 #[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
@@ -17,6 +17,11 @@ pub struct Diagnostic {
     pub span: MultiSpan,
     pub children: Vec<SubDiagnostic>,
     pub suggestions: Vec<CodeSuggestion>,
+
+    /// This is not used for highlighting or rendering any error message.  Rather, it can be used
+    /// as a sort key to sort a buffer of diagnostics.  By default, it is the primary span of
+    /// `span` if there is one.  Otherwise, it is `DUMMY_SP`.
+    pub sort_span: Span,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
@@ -87,6 +92,7 @@ impl Diagnostic {
             span: MultiSpan::new(),
             children: vec![],
             suggestions: vec![],
+            sort_span: DUMMY_SP,
         }
     }
 
@@ -118,6 +124,11 @@ impl Diagnostic {
         self.level == Level::Cancelled
     }
 
+    /// Set the sorting span.
+    pub fn set_sort_span(&mut self, sp: Span) {
+        self.sort_span = sp;
+    }
+
     /// Adds a span/label to be included in the resulting snippet.
     /// This label will be shown together with the original span/label used when creating the
     /// diagnostic, *not* a span added by one of the `span_*` methods.
@@ -457,6 +468,9 @@ impl Diagnostic {
 
     pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
         self.span = sp.into();
+        if let Some(span) = self.span.primary_span() {
+            self.sort_span = span;
+        }
         self
     }
 
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index fb34d844fda..8a1799faaf8 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -575,6 +575,11 @@ impl Handler {
         DiagnosticBuilder::new(self, Level::Fatal, msg)
     }
 
+    /// Construct a builder at the `Help` level with the `msg`.
+    pub fn struct_help(&self, msg: &str) -> DiagnosticBuilder<'_> {
+        DiagnosticBuilder::new(self, Level::Help, msg)
+    }
+
     pub fn span_fatal(&self, span: impl Into<MultiSpan>, msg: &str) -> FatalError {
         self.emit_diag_at_span(Diagnostic::new(Fatal, msg), span);
         FatalError
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index f932a6bf155..b8b4a1053e5 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -367,7 +367,7 @@ fn do_mir_borrowck<'a, 'tcx>(
     }
 
     if !mbcx.errors_buffer.is_empty() {
-        mbcx.errors_buffer.sort_by_key(|diag| diag.span.primary_span());
+        mbcx.errors_buffer.sort_by_key(|diag| diag.sort_span);
 
         for diag in mbcx.errors_buffer.drain(..) {
             mbcx.infcx.tcx.sess.diagnostic().emit_diagnostic(&diag);
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index 7362ae9c638..26b288cb4b2 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -18,6 +18,10 @@ use syntax::errors::Applicability;
 use syntax::symbol::kw;
 use syntax_pos::Span;
 
+use self::outlives_suggestion::OutlivesSuggestionBuilder;
+
+pub mod outlives_suggestion;
+
 mod region_name;
 mod var_name;
 
@@ -56,7 +60,6 @@ enum Trace {
 /// Various pieces of state used when reporting borrow checker errors.
 pub struct ErrorReportingCtx<'a, 'b, 'tcx> {
     /// The region inference context used for borrow chekcing this MIR body.
-    #[allow(dead_code)] // FIXME(mark-i-m): used by outlives suggestions
     region_infcx: &'b RegionInferenceContext<'tcx>,
 
     /// The inference context used for type checking.
@@ -370,6 +373,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         fr: RegionVid,
         fr_origin: NLLRegionVariableOrigin,
         outlived_fr: RegionVid,
+        outlives_suggestion: &mut OutlivesSuggestionBuilder,
         renctx: &mut RegionErrorNamingCtx,
     ) -> DiagnosticBuilder<'a> {
         debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
@@ -415,9 +419,22 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 self.report_fnmut_error(&errctx, &errci, renctx)
             }
             (ConstraintCategory::Assignment, true, false)
-            | (ConstraintCategory::CallArgument, true, false) =>
-                self.report_escaping_data_error(&errctx, &errci, renctx),
-            _ => self.report_general_error(&errctx, &errci, renctx),
+            | (ConstraintCategory::CallArgument, true, false) => {
+                let mut db = self.report_escaping_data_error(&errctx, &errci, renctx);
+
+                outlives_suggestion.intermediate_suggestion(&errctx, &errci, renctx, &mut db);
+                outlives_suggestion.collect_constraint(fr, outlived_fr);
+
+                db
+            }
+            _ => {
+                let mut db = self.report_general_error(&errctx, &errci, renctx);
+
+                outlives_suggestion.intermediate_suggestion(&errctx, &errci, renctx, &mut db);
+                outlives_suggestion.collect_constraint(fr, outlived_fr);
+
+                db
+            }
         }
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/outlives_suggestion.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/outlives_suggestion.rs
new file mode 100644
index 00000000000..62142efe505
--- /dev/null
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/outlives_suggestion.rs
@@ -0,0 +1,317 @@
+//! Contains utilities for generating suggestions for borrowck errors related to unsatisified
+//! outlives constraints.
+
+use std::collections::BTreeMap;
+
+use log::debug;
+use rustc::{hir::def_id::DefId, infer::InferCtxt, mir::Body, ty::RegionVid};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::{Diagnostic, DiagnosticBuilder};
+
+use smallvec::SmallVec;
+
+use crate::borrow_check::nll::region_infer::{
+    error_reporting::{
+        region_name::{RegionName, RegionNameSource},
+        ErrorConstraintInfo, ErrorReportingCtx, RegionErrorNamingCtx,
+    },
+    RegionInferenceContext,
+};
+
+/// The different things we could suggest.
+enum SuggestedConstraint {
+    /// Outlives(a, [b, c, d, ...]) => 'a: 'b + 'c + 'd + ...
+    Outlives(RegionName, SmallVec<[RegionName; 2]>),
+
+    /// 'a = 'b
+    Equal(RegionName, RegionName),
+
+    /// 'a: 'static i.e. 'a = 'static and the user should just use 'static
+    Static(RegionName),
+}
+
+/// Collects information about outlives constraints that needed to be added for a given MIR node
+/// corresponding to a function definition.
+///
+/// Adds a help note suggesting adding a where clause with the needed constraints.
+pub struct OutlivesSuggestionBuilder {
+    /// The MIR DefId of the fn with the lifetime error.
+    mir_def_id: DefId,
+
+    /// The list of outlives constraints that need to be added. Specifically, we map each free
+    /// region to all other regions that it must outlive. I will use the shorthand `fr:
+    /// outlived_frs`. Not all of these regions will already have names necessarily. Some could be
+    /// implicit free regions that we inferred. These will need to be given names in the final
+    /// suggestion message.
+    constraints_to_add: BTreeMap<RegionVid, Vec<RegionVid>>,
+}
+
+impl OutlivesSuggestionBuilder {
+    /// Create a new builder for the given MIR node representing a fn definition.
+    crate fn new(mir_def_id: DefId) -> Self {
+        OutlivesSuggestionBuilder { mir_def_id, constraints_to_add: BTreeMap::default() }
+    }
+
+    /// Returns `true` iff the `RegionNameSource` is a valid source for an outlives
+    /// suggestion.
+    //
+    // FIXME: Currently, we only report suggestions if the `RegionNameSource` is an early-bound
+    // region or a named region, avoiding using regions with synthetic names altogether. This
+    // allows us to avoid giving impossible suggestions (e.g. adding bounds to closure args).
+    // We can probably be less conservative, since some inferred free regions are namable (e.g.
+    // the user can explicitly name them. To do this, we would allow some regions whose names
+    // come from `MatchedAdtAndSegment`, being careful to filter out bad suggestions, such as
+    // naming the `'self` lifetime in methods, etc.
+    fn region_name_is_suggestable(name: &RegionName) -> bool {
+        match name.source {
+            RegionNameSource::NamedEarlyBoundRegion(..)
+            | RegionNameSource::NamedFreeRegion(..)
+            | RegionNameSource::Static => {
+                // FIXME: This is a bit hacky. We should ideally have a semantic way for checking
+                // if the name is `'_`...
+                if name.name().with(|name| name != "'_") {
+                    debug!("Region {:?} is suggestable", name);
+                    true
+                } else {
+                    debug!("Region {:?} is NOT suggestable", name);
+                    false
+                }
+            }
+
+            // Don't give suggestions for upvars, closure return types, or other unnamable
+            // regions.
+            RegionNameSource::SynthesizedFreeEnvRegion(..)
+            | RegionNameSource::CannotMatchHirTy(..)
+            | RegionNameSource::MatchedHirTy(..)
+            | RegionNameSource::MatchedAdtAndSegment(..)
+            | RegionNameSource::AnonRegionFromUpvar(..)
+            | RegionNameSource::AnonRegionFromOutput(..)
+            | RegionNameSource::AnonRegionFromYieldTy(..) => {
+                debug!("Region {:?} is NOT suggestable", name);
+                false
+            }
+        }
+    }
+
+    /// Returns a name for the region if it is suggestable. See `region_name_is_suggestable`.
+    fn region_vid_to_name(
+        &self,
+        errctx: &ErrorReportingCtx<'_, '_, '_>,
+        renctx: &mut RegionErrorNamingCtx,
+        region: RegionVid,
+    ) -> Option<RegionName> {
+        errctx
+            .region_infcx
+            .give_region_a_name(errctx, renctx, region)
+            .filter(Self::region_name_is_suggestable)
+    }
+
+    /// Compiles a list of all suggestions to be printed in the final big suggestion.
+    fn compile_all_suggestions<'tcx>(
+        &self,
+        body: &Body<'tcx>,
+        region_infcx: &RegionInferenceContext<'tcx>,
+        infcx: &InferCtxt<'_, 'tcx>,
+        renctx: &mut RegionErrorNamingCtx,
+    ) -> SmallVec<[SuggestedConstraint; 2]> {
+        let mut suggested = SmallVec::new();
+
+        // Keep track of variables that we have already suggested unifying so that we don't print
+        // out silly duplicate messages.
+        let mut unified_already = FxHashSet::default();
+
+        let errctx = ErrorReportingCtx {
+            region_infcx,
+            infcx,
+            body,
+            mir_def_id: self.mir_def_id,
+
+            // We should not be suggesting naming upvars, so we pass in a dummy set of upvars that
+            // should never be used.
+            upvars: &[],
+        };
+
+        for (fr, outlived) in &self.constraints_to_add {
+            let fr_name = if let Some(fr_name) = self.region_vid_to_name(&errctx, renctx, *fr) {
+                fr_name
+            } else {
+                continue;
+            };
+
+            let outlived = outlived
+                .iter()
+                // if there is a `None`, we will just omit that constraint
+                .filter_map(|fr| {
+                    self.region_vid_to_name(&errctx, renctx, *fr).map(|rname| (fr, rname))
+                })
+                .collect::<Vec<_>>();
+
+            // No suggestable outlived lifetimes.
+            if outlived.is_empty() {
+                continue;
+            }
+
+            // There are three types of suggestions we can make:
+            // 1) Suggest a bound: 'a: 'b
+            // 2) Suggest replacing 'a with 'static. If any of `outlived` is `'static`, then we
+            //    should just replace 'a with 'static.
+            // 3) Suggest unifying 'a with 'b if we have both 'a: 'b and 'b: 'a
+
+            if outlived.iter().any(|(_, outlived_name)| {
+                if let RegionNameSource::Static = outlived_name.source {
+                    true
+                } else {
+                    false
+                }
+            }) {
+                suggested.push(SuggestedConstraint::Static(fr_name));
+            } else {
+                // We want to isolate out all lifetimes that should be unified and print out
+                // separate messages for them.
+
+                let (unified, other): (Vec<_>, Vec<_>) = outlived.into_iter().partition(
+                    // Do we have both 'fr: 'r and 'r: 'fr?
+                    |(r, _)| {
+                        self.constraints_to_add
+                            .get(r)
+                            .map(|r_outlived| r_outlived.as_slice().contains(fr))
+                            .unwrap_or(false)
+                    },
+                );
+
+                for (r, bound) in unified.into_iter() {
+                    if !unified_already.contains(fr) {
+                        suggested.push(SuggestedConstraint::Equal(fr_name.clone(), bound));
+                        unified_already.insert(r);
+                    }
+                }
+
+                if !other.is_empty() {
+                    let other =
+                        other.iter().map(|(_, rname)| rname.clone()).collect::<SmallVec<_>>();
+                    suggested.push(SuggestedConstraint::Outlives(fr_name, other))
+                }
+            }
+        }
+
+        suggested
+    }
+
+    /// Add the outlives constraint `fr: outlived_fr` to the set of constraints we need to suggest.
+    crate fn collect_constraint(&mut self, fr: RegionVid, outlived_fr: RegionVid) {
+        debug!("Collected {:?}: {:?}", fr, outlived_fr);
+
+        // Add to set of constraints for final help note.
+        self.constraints_to_add.entry(fr).or_insert(Vec::new()).push(outlived_fr);
+    }
+
+    /// Emit an intermediate note on the given `Diagnostic` if the involved regions are
+    /// suggestable.
+    crate fn intermediate_suggestion(
+        &mut self,
+        errctx: &ErrorReportingCtx<'_, '_, '_>,
+        errci: &ErrorConstraintInfo,
+        renctx: &mut RegionErrorNamingCtx,
+        diag: &mut DiagnosticBuilder<'_>,
+    ) {
+        // Emit an intermediate note.
+        let fr_name = self.region_vid_to_name(errctx, renctx, errci.fr);
+        let outlived_fr_name = self.region_vid_to_name(errctx, renctx, errci.outlived_fr);
+
+        if let (Some(fr_name), Some(outlived_fr_name)) = (fr_name, outlived_fr_name) {
+            if let RegionNameSource::Static = outlived_fr_name.source {
+                diag.help(&format!("consider replacing `{}` with `'static`", fr_name));
+            } else {
+                diag.help(&format!(
+                    "consider adding the following bound: `{}: {}`",
+                    fr_name, outlived_fr_name
+                ));
+            }
+        }
+    }
+
+    /// If there is a suggestion to emit, add a diagnostic to the buffer. This is the final
+    /// suggestion including all collected constraints.
+    crate fn add_suggestion<'tcx>(
+        &self,
+        body: &Body<'tcx>,
+        region_infcx: &RegionInferenceContext<'tcx>,
+        infcx: &InferCtxt<'_, 'tcx>,
+        errors_buffer: &mut Vec<Diagnostic>,
+        renctx: &mut RegionErrorNamingCtx,
+    ) {
+        // No constraints to add? Done.
+        if self.constraints_to_add.is_empty() {
+            debug!("No constraints to suggest.");
+            return;
+        }
+
+        // If there is only one constraint to suggest, then we already suggested it in the
+        // intermediate suggestion above.
+        if self.constraints_to_add.len() == 1 {
+            debug!("Only 1 suggestion. Skipping.");
+            return;
+        }
+
+        // Get all suggestable constraints.
+        let suggested = self.compile_all_suggestions(body, region_infcx, infcx, renctx);
+
+        // If there are no suggestable constraints...
+        if suggested.is_empty() {
+            debug!("Only 1 suggestable constraint. Skipping.");
+            return;
+        }
+
+        // If there is exactly one suggestable constraints, then just suggest it. Otherwise, emit a
+        // list of diagnostics.
+        let mut diag = if suggested.len() == 1 {
+            infcx.tcx.sess.diagnostic().struct_help(&match suggested.last().unwrap() {
+                SuggestedConstraint::Outlives(a, bs) => {
+                    let bs: SmallVec<[String; 2]> = bs.iter().map(|r| format!("{}", r)).collect();
+                    format!("add bound `{}: {}`", a, bs.join(" + "))
+                }
+
+                SuggestedConstraint::Equal(a, b) => {
+                    format!("`{}` and `{}` must be the same: replace one with the other", a, b)
+                }
+                SuggestedConstraint::Static(a) => format!("replace `{}` with `'static`", a),
+            })
+        } else {
+            // Create a new diagnostic.
+            let mut diag = infcx
+                .tcx
+                .sess
+                .diagnostic()
+                .struct_help("the following changes may resolve your lifetime errors");
+
+            // Add suggestions.
+            for constraint in suggested {
+                match constraint {
+                    SuggestedConstraint::Outlives(a, bs) => {
+                        let bs: SmallVec<[String; 2]> =
+                            bs.iter().map(|r| format!("{}", r)).collect();
+                        diag.help(&format!("add bound `{}: {}`", a, bs.join(" + ")));
+                    }
+                    SuggestedConstraint::Equal(a, b) => {
+                        diag.help(&format!(
+                            "`{}` and `{}` must be the same: replace one with the other",
+                            a, b
+                        ));
+                    }
+                    SuggestedConstraint::Static(a) => {
+                        diag.help(&format!("replace `{}` with `'static`", a));
+                    }
+                }
+            }
+
+            diag
+        };
+
+        // We want this message to appear after other messages on the mir def.
+        let mir_span = infcx.tcx.def_span(self.mir_def_id);
+        diag.sort_span = mir_span.shrink_to_hi();
+
+        // Buffer the diagnostic
+        diag.buffer(errors_buffer);
+    }
+}
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index dbb810db555..4de8200e6a0 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -11,6 +11,7 @@ use crate::borrow_check::nll::{
     region_infer::values::{
         PlaceholderIndices, RegionElement, ToElementIndex
     },
+    region_infer::error_reporting::outlives_suggestion::OutlivesSuggestionBuilder,
     type_check::{free_region_relations::UniversalRegionRelations, Locations},
 };
 use crate::borrow_check::Upvar;
@@ -1326,6 +1327,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         errors_buffer: &mut Vec<Diagnostic>,
         region_naming: &mut RegionErrorNamingCtx,
     ) {
+        let mut outlives_suggestion = OutlivesSuggestionBuilder::new(mir_def_id);
+
         for (fr, fr_definition) in self.definitions.iter_enumerated() {
             match fr_definition.origin {
                 NLLRegionVariableOrigin::FreeRegion => {
@@ -1339,6 +1342,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                         mir_def_id,
                         fr,
                         &mut propagated_outlives_requirements,
+                        &mut outlives_suggestion,
                         errors_buffer,
                         region_naming,
                     );
@@ -1353,6 +1357,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 }
             }
         }
+
+        // Emit outlives suggestions
+        outlives_suggestion.add_suggestion(body, self, infcx, errors_buffer, region_naming);
     }
 
     /// Checks the final value for the free region `fr` to see if it
@@ -1371,6 +1378,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         mir_def_id: DefId,
         longer_fr: RegionVid,
         propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
+        outlives_suggestion: &mut OutlivesSuggestionBuilder,
         errors_buffer: &mut Vec<Diagnostic>,
         region_naming: &mut RegionErrorNamingCtx,
     ) {
@@ -1399,6 +1407,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 upvars,
                 mir_def_id,
                 propagated_outlives_requirements,
+                outlives_suggestion,
                 errors_buffer,
                 region_naming,
             );
@@ -1416,6 +1425,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 upvars,
                 mir_def_id,
                 propagated_outlives_requirements,
+                outlives_suggestion,
                 errors_buffer,
                 region_naming,
             ) {
@@ -1438,6 +1448,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         upvars: &[Upvar],
         mir_def_id: DefId,
         propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
+        outlives_suggestion: &mut OutlivesSuggestionBuilder,
         errors_buffer: &mut Vec<Diagnostic>,
         region_naming: &mut RegionErrorNamingCtx,
     ) -> Option<ErrorReported> {
@@ -1497,6 +1508,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             longer_fr,
             NLLRegionVariableOrigin::FreeRegion,
             shorter_fr,
+            outlives_suggestion,
             region_naming,
         );
 
diff --git a/src/test/ui/associated-type-bounds/implied-region-constraints.nll.stderr b/src/test/ui/associated-type-bounds/implied-region-constraints.nll.stderr
index 32d099fce75..b8c54b13d8b 100644
--- a/src/test/ui/associated-type-bounds/implied-region-constraints.nll.stderr
+++ b/src/test/ui/associated-type-bounds/implied-region-constraints.nll.stderr
@@ -8,6 +8,8 @@ LL | fn _bad_st<'a, 'b, T>(x: St<'a, 'b, T>)
 ...
 LL |     let _failure_proves_not_implied_outlives_region_b: &'b T = &x.f0;
    |                                                        ^^^^^ type annotation requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/implied-region-constraints.rs:40:64
@@ -19,6 +21,8 @@ LL | fn _bad_en7<'a, 'b, T>(x: En7<'a, 'b, T>)
 ...
 LL |             let _failure_proves_not_implied_outlives_region_b: &'b T = &x;
    |                                                                ^^^^^ type annotation requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.nll.stderr b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.nll.stderr
index ca99304f9b4..e12d42e5ed0 100644
--- a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.nll.stderr
+++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.nll.stderr
@@ -8,6 +8,8 @@ LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>(
 ...
 LL |     let z: I::A = if cond { x } else { y };
    |                             ^ assignment requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:22:40
@@ -19,6 +21,10 @@ LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>(
 ...
 LL |     let z: I::A = if cond { x } else { y };
    |                                        ^ assignment requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+help: `'a` and `'b` must be the same: replace one with the other
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/associated-types-subtyping-1.nll.stderr b/src/test/ui/associated-types/associated-types-subtyping-1.nll.stderr
index d8506b9c8c8..11d3cfe5b46 100644
--- a/src/test/ui/associated-types/associated-types-subtyping-1.nll.stderr
+++ b/src/test/ui/associated-types/associated-types-subtyping-1.nll.stderr
@@ -8,6 +8,8 @@ LL | fn method2<'a,'b,T>(x: &'a T, y: &'b T)
 ...
 LL |     let a: <T as Trait<'a>>::Type = make_any();
    |            ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
   --> $DIR/associated-types-subtyping-1.rs:35:13
@@ -19,6 +21,8 @@ LL | fn method3<'a,'b,T>(x: &'a T, y: &'b T)
 ...
 LL |     let _c: <T as Trait<'a>>::Type = b;
    |             ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr
index 779e6dac92e..a5b6d640391 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr
@@ -8,6 +8,8 @@ LL | fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
 ...
 LL |    (a, b)
    |    ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/project-fn-ret-contravariant.rs:45:4
@@ -19,6 +21,10 @@ LL | fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
 ...
 LL |    (a, b)
    |    ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+help: `'a` and `'b` must be the same: replace one with the other
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr
index f532c96ed2c..558f394ef86 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr
@@ -5,6 +5,8 @@ LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
    |        -- lifetime `'a` defined here
 LL |    bar(foo, x)
    |    ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr
index c45082fb053..71a533a36f4 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr
@@ -8,6 +8,8 @@ LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
 ...
 LL |    (a, b)
    |    ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/project-fn-ret-invariant.rs:55:4
@@ -19,6 +21,10 @@ LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
 ...
 LL |    (a, b)
    |    ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+help: `'a` and `'b` must be the same: replace one with the other
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr
index 2c11e7ffe93..c39030fbed1 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr
@@ -8,6 +8,8 @@ LL | fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
 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`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/project-fn-ret-invariant.rs:39:12
@@ -19,6 +21,10 @@ LL | fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
 ...
 LL |    let b = bar(f, y);
    |            ^^^^^^^^^ argument requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+help: `'a` and `'b` must be the same: replace one with the other
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr
index 8be0ad6e88f..f74d4ba73bf 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr
@@ -6,6 +6,8 @@ LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> {
 ...
 LL |    bar(foo, x)
    |    ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr
index b4d5d3ec051..53b0dd691b8 100644
--- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr
@@ -10,6 +10,8 @@ LL | |
 LL | |     (a, b)
 LL | | }
    | |_^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.nll.stderr b/src/test/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.nll.stderr
index e6d0f88e3ea..f28c42ce2d5 100644
--- a/src/test/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.nll.stderr
@@ -7,6 +7,8 @@ LL | fn copy_borrowed_ptr<'a,'b>(p: &'a mut S<'b>) -> S<'b> {
    |                      lifetime `'a` defined here
 LL |     S { pointer: &mut *p.pointer }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/closure-expected-type/expect-region-supply-region.nll.stderr b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.nll.stderr
index bbf75302d56..f816f27a892 100644
--- a/src/test/ui/closures/closure-expected-type/expect-region-supply-region.nll.stderr
+++ b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.nll.stderr
@@ -37,6 +37,8 @@ LL | fn expect_bound_supply_named<'x>() {
 ...
 LL |     closure_expecting_bound(|x: &'x u32| {
    |                              ^ requires that `'x` must outlive `'static`
+   |
+   = help: consider replacing `'x` with `'static`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr
index 070fe12a284..9b0c987c054 100644
--- a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr
@@ -11,6 +11,8 @@ LL |               gimme::<$t2>(None::<$t1>);
 LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
 LL | |                                     fn(Inv<'y>)) }
    | |__________________________________________________- in this macro invocation
+   |
+   = help: consider adding the following bound: `'x: 'y`
 
 error: lifetime may not live long enough
   --> $DIR/hr-subtype.rs:39:13
@@ -25,6 +27,8 @@ LL |               gimme::<$t1>(None::<$t2>);
 LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
 LL | |                                     fn(Inv<'y>)) }
    | |__________________________________________________- in this macro invocation
+   |
+   = help: consider adding the following bound: `'x: 'y`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr
index e140eaadd48..48558fad005 100644
--- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr
@@ -11,6 +11,8 @@ LL |               gimme::<$t1>(None::<$t2>);
 LL | / check! { free_x_vs_free_y: (fn(&'x u32),
 LL | |                             fn(&'y u32)) }
    | |__________________________________________- in this macro invocation
+   |
+   = help: consider adding the following bound: `'x: 'y`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr
index 6d1ef24b2dc..f1647d3d2e4 100644
--- a/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr
@@ -58,6 +58,8 @@ LL | fn foo_hrtb_bar_not<'b,T>(mut t: T)
 ...
 LL |     foo_hrtb_bar_not(&mut t);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
+   |
+   = help: consider replacing `'b` with `'static`
 
 warning: function cannot return without recursing
   --> $DIR/hrtb-perfect-forwarding.rs:49:1
diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.nll.stderr b/src/test/ui/impl-header-lifetime-elision/dyn-trait.nll.stderr
index da30997a231..8e660d6814c 100644
--- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.nll.stderr
+++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.nll.stderr
@@ -5,6 +5,8 @@ LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
    |                              - `x` is a reference that is only valid in the function body
 LL |     static_val(x);
    |     ^^^^^^^^^^^^^ `x` escapes the function body here
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr
index 82e280b9fb2..45c5142d93f 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr
+++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr
@@ -4,6 +4,7 @@ error: lifetime may not live long enough
 LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
    |        -- lifetime `'a` defined here                   ^^^^^^^^^ opaque type requires that `'a` must outlive `'static`
    |
+   = help: consider replacing `'a` with `'static`
 help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a constraint
    |
 LL | type E<'a, 'b> = impl Sized; + 'a
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
index 097f003575e..bb5a85aba97 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
@@ -19,6 +19,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
    |             |
    |             lifetime `'a` defined here
    |
+   = help: consider replacing `'a` with `'static`
 help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a constraint
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
@@ -31,6 +32,7 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    |               -- lifetime `'a` defined here                         ^ returning this value requires that `'a` must outlive `'static`
    |
    = help: consider replacing `'a` with `'static`
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/must_outlive_least_region_or_bound.rs:17:61
@@ -39,6 +41,8 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
    |                          --  -- lifetime `'b` defined here  ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a`
    |                          |
    |                          lifetime `'a` defined here
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/must_outlive_least_region_or_bound.rs:22:51
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr
index 423cfcc4989..22f081b79f1 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr
@@ -19,6 +19,7 @@ LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
    |                    |
    |                    lifetime `'a` defined here
    |
+   = help: consider replacing `'a` with `'static`
 help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a constraint
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
diff --git a/src/test/ui/in-band-lifetimes/mismatched.nll.stderr b/src/test/ui/in-band-lifetimes/mismatched.nll.stderr
index f5aee2d2d7e..db028e63a82 100644
--- a/src/test/ui/in-band-lifetimes/mismatched.nll.stderr
+++ b/src/test/ui/in-band-lifetimes/mismatched.nll.stderr
@@ -14,6 +14,8 @@ LL | fn foo2(x: &'a u32, y: &'b u32) -> &'a u32 { y }
    |             |           |
    |             |           lifetime `'b` defined here
    |             lifetime `'a` defined here
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-10291.nll.stderr b/src/test/ui/issues/issue-10291.nll.stderr
index a7b827d27a8..1ebb0c6cf1e 100644
--- a/src/test/ui/issues/issue-10291.nll.stderr
+++ b/src/test/ui/issues/issue-10291.nll.stderr
@@ -6,6 +6,8 @@ LL | fn test<'x>(x: &'x isize) {
 LL |     drop::<Box<dyn for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
 LL |         x
    |         ^ returning this value requires that `'x` must outlive `'static`
+   |
+   = help: consider replacing `'x` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-26217.nll.stderr b/src/test/ui/issues/issue-26217.nll.stderr
index c7601caacdc..83f10c67d43 100644
--- a/src/test/ui/issues/issue-26217.nll.stderr
+++ b/src/test/ui/issues/issue-26217.nll.stderr
@@ -5,6 +5,8 @@ LL | fn bar<'a>() {
    |        -- lifetime `'a` defined here
 LL |     foo::<&'a i32>();
    |     ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-28848.nll.stderr b/src/test/ui/issues/issue-28848.nll.stderr
index 5cf9856e4dc..a29dac4c9c8 100644
--- a/src/test/ui/issues/issue-28848.nll.stderr
+++ b/src/test/ui/issues/issue-28848.nll.stderr
@@ -7,6 +7,8 @@ LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
    |            lifetime `'a` defined here
 LL |     Foo::<'a, 'b>::xmute(u)
    |     ^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-52213.nll.stderr b/src/test/ui/issues/issue-52213.nll.stderr
index eba875de215..359f91309d4 100644
--- a/src/test/ui/issues/issue-52213.nll.stderr
+++ b/src/test/ui/issues/issue-52213.nll.stderr
@@ -8,6 +8,8 @@ LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T {
 LL |     match (&t,) {
 LL |         ((u,),) => u,
    |                    ^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-54943.nll.stderr b/src/test/ui/issues/issue-54943.nll.stderr
index 59be0f983b9..5bf6d3382d2 100644
--- a/src/test/ui/issues/issue-54943.nll.stderr
+++ b/src/test/ui/issues/issue-54943.nll.stderr
@@ -6,6 +6,8 @@ LL | fn boo<'a>() {
 ...
 LL |     let x = foo::<&'a u32>();
    |             ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-55796.nll.stderr b/src/test/ui/issues/issue-55796.nll.stderr
index 5809a56cd4b..baa0e6c29bf 100644
--- a/src/test/ui/issues/issue-55796.nll.stderr
+++ b/src/test/ui/issues/issue-55796.nll.stderr
@@ -6,6 +6,8 @@ LL | pub trait Graph<'a> {
 ...
 LL |         Box::new(self.out_edges(u).map(|e| e.target()))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/issue-55796.rs:21:9
@@ -15,6 +17,8 @@ LL | pub trait Graph<'a> {
 ...
 LL |         Box::new(self.in_edges(u).map(|e| e.target()))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr
index f2cf19abdac..60420973e1e 100644
--- a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr
@@ -6,6 +6,8 @@ LL | fn test2<'a>(x: &'a Box<dyn Fn() + 'a>) {
 LL |     // but ref_obj will not, so warn.
 LL |     ref_obj(x)
    |     ^^^^^^^^^^ `x` escapes the function body here
+   |
+   = help: consider replacing `'a` with `'static`
 
 error[E0521]: borrowed data escapes outside of function
   --> $DIR/lifetime-bound-will-change-warning.rs:39:5
@@ -15,6 +17,8 @@ LL | fn test2cc<'a>(x: &'a Box<dyn Fn() + 'a>) {
 LL |     // same as test2, but cross crate
 LL |     lib::ref_obj(x)
    |     ^^^^^^^^^^^^^^^ `x` escapes the function body here
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.nll.stderr
index fbefa1f5667..99fab4631a2 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.nll.stderr
@@ -8,6 +8,8 @@ LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
 LL |     let z = Ref { data: y.data };
 LL |     x.push(z);
    |     ^^^^^^^^^ argument requires that `'c` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'c: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr
index d889eb4afdb..52c5752f6ea 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr
@@ -8,6 +8,8 @@ LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
 ...
 LL |     a.push(b);
    |     ^^^^^^^^^ argument requires that `'c` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'c: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr
index 39eb4079352..e90c81ee3e1 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr
@@ -8,6 +8,8 @@ LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
 ...
 LL |     Vec::push(a, b);
    |     ^^^^^^^^^^^^^^^ argument requires that `'c` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'c: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr
index a39bb165806..b3d0bc2b882 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr
@@ -8,6 +8,8 @@ LL | fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>)
 ...
 LL |     x.push(y);
    |     ^^^^^^^^^ argument requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr
index 48ce5301ade..fbe98a4263e 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr
@@ -7,6 +7,8 @@ LL | fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>) {
    |        lifetime `'a` defined here
 LL |     x.push(y);
    |     ^^^^^^^^^ argument requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr
index 09960683980..1e24032fc1c 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr
@@ -7,6 +7,8 @@ LL | fn foo<'a,'b>(x: &mut Vec<&'a u8>, y: &'b u8) {
    |        lifetime `'a` defined here
 LL |     x.push(y);
    |     ^^^^^^^^^ argument requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lub-if.nll.stderr b/src/test/ui/lub-if.nll.stderr
index 832688f5162..1ef479fcd4b 100644
--- a/src/test/ui/lub-if.nll.stderr
+++ b/src/test/ui/lub-if.nll.stderr
@@ -6,6 +6,8 @@ LL | pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str {
 ...
 LL |         s
    |         ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/lub-if.rs:35:9
@@ -15,6 +17,8 @@ LL | pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str {
 ...
 LL |         s
    |         ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lub-match.nll.stderr b/src/test/ui/lub-match.nll.stderr
index 3a344a77d2c..ed551da54f5 100644
--- a/src/test/ui/lub-match.nll.stderr
+++ b/src/test/ui/lub-match.nll.stderr
@@ -6,6 +6,8 @@ LL | pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str {
 ...
 LL |             s
    |             ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/lub-match.rs:39:13
@@ -15,6 +17,8 @@ LL | pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str {
 ...
 LL |             s
    |             ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/match/match-ref-mut-invariance.nll.stderr b/src/test/ui/match/match-ref-mut-invariance.nll.stderr
index 505b8db6a33..1658efa28bf 100644
--- a/src/test/ui/match/match-ref-mut-invariance.nll.stderr
+++ b/src/test/ui/match/match-ref-mut-invariance.nll.stderr
@@ -7,6 +7,8 @@ LL |     fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
    |            -- lifetime `'a` defined here
 LL |         match self.0 { ref mut x => x }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr b/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr
index ab5f43d0222..dc227a36566 100644
--- a/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr
+++ b/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr
@@ -8,6 +8,8 @@ LL |     fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
 LL |         let ref mut x = self.0;
 LL |         x
    |         ^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
index 3bd3fc517ce..6f5b813e85e 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -42,6 +42,8 @@ LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
 ...
 LL |         demand_y(x, y, x.get())
    |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
index e93634aa3da..5ebf8e248b3 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -45,6 +45,8 @@ LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
 LL | |     });
    | |______^ `cell_a` escapes the function body here
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
index 2127eab4344..91caa42c9bf 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -45,6 +45,8 @@ LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
 LL | |     });
    | |______^ `cell_a` escapes the function body here
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
index 9078877492f..243c8b12ecb 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -42,6 +42,8 @@ LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
 ...
 LL |         demand_y(outlives1, outlives2, x.get())
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
index d0a24a267fd..1fa3d01017a 100644
--- a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
+++ b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
@@ -5,6 +5,8 @@ LL | fn foo<'a>(x: &'a u32) -> &'static u32 {
    |        -- lifetime `'a` defined here
 LL |     &*x
    |     ^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
index 6dc98a94408..d0ba5392532 100644
--- a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
+++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
@@ -7,6 +7,8 @@ LL | fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
    |        lifetime `'a` defined here
 LL |     &*x
    |     ^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/issue-50716.nll.stderr b/src/test/ui/nll/issue-50716.nll.stderr
index 38dd1b5f6fe..7b83e4beaf3 100644
--- a/src/test/ui/nll/issue-50716.nll.stderr
+++ b/src/test/ui/nll/issue-50716.nll.stderr
@@ -6,6 +6,8 @@ LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>)
 ...
 LL |     let _x = *s;
    |              ^^ proving this value is `Sized` requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/issue-52113.stderr b/src/test/ui/nll/issue-52113.stderr
index 590963ded78..dcf03386734 100644
--- a/src/test/ui/nll/issue-52113.stderr
+++ b/src/test/ui/nll/issue-52113.stderr
@@ -8,6 +8,8 @@ LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> i
 ...
 LL |     x
    |     ^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/issue-55401.nll.stderr b/src/test/ui/nll/issue-55401.nll.stderr
index 4f797f26a1a..df320aa0844 100644
--- a/src/test/ui/nll/issue-55401.nll.stderr
+++ b/src/test/ui/nll/issue-55401.nll.stderr
@@ -6,6 +6,8 @@ LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u
 LL |     let (ref y, _z): (&'a u32, u32) = (&22, 44);
 LL |     *y
    |     ^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/issue-58299.stderr b/src/test/ui/nll/issue-58299.stderr
index aba07542d02..5be4e56171c 100644
--- a/src/test/ui/nll/issue-58299.stderr
+++ b/src/test/ui/nll/issue-58299.stderr
@@ -6,6 +6,8 @@ LL | fn foo<'a>(x: i32) {
 ...
 LL |         A::<'a>::X..=A::<'static>::X => (),
    |         ^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/issue-58299.rs:24:27
@@ -15,6 +17,8 @@ LL | fn bar<'a>(x: i32) {
 ...
 LL |         A::<'static>::X..=A::<'a>::X => (),
    |                           ^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/mir_check_cast_closure.stderr b/src/test/ui/nll/mir_check_cast_closure.stderr
index e14cb074c81..113e220e513 100644
--- a/src/test/ui/nll/mir_check_cast_closure.stderr
+++ b/src/test/ui/nll/mir_check_cast_closure.stderr
@@ -8,6 +8,8 @@ LL | fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 {
 LL |     let g: fn(_, _) -> _ = |_x, y| y;
 LL |     g
    |     ^ returning this value requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/mir_check_cast_reify.stderr b/src/test/ui/nll/mir_check_cast_reify.stderr
index 4e8eec330a5..1722da8f343 100644
--- a/src/test/ui/nll/mir_check_cast_reify.stderr
+++ b/src/test/ui/nll/mir_check_cast_reify.stderr
@@ -6,6 +6,8 @@ LL | fn bar<'a>(x: &'a u32) -> &'static u32 {
 ...
 LL |     f(x)
    |     ^^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr
index 52959850a33..c87425ecfc0 100644
--- a/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr
+++ b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr
@@ -6,6 +6,8 @@ LL | fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 {
 ...
 LL |     unsafe { g(input) }
    |              ^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/mir_check_cast_unsize.stderr b/src/test/ui/nll/mir_check_cast_unsize.stderr
index 364d6c17ea7..cb7328d1179 100644
--- a/src/test/ui/nll/mir_check_cast_unsize.stderr
+++ b/src/test/ui/nll/mir_check_cast_unsize.stderr
@@ -5,6 +5,8 @@ LL | fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
    |        -- lifetime `'a` defined here
 LL |     x
    |     ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/outlives-suggestion-more.rs b/src/test/ui/nll/outlives-suggestion-more.rs
new file mode 100644
index 00000000000..4d80b78ac65
--- /dev/null
+++ b/src/test/ui/nll/outlives-suggestion-more.rs
@@ -0,0 +1,28 @@
+// Test the more elaborate outlives suggestions.
+
+#![feature(nll)]
+
+// Should suggest: 'a: 'c, 'b: 'd
+fn foo1<'a, 'b, 'c, 'd>(x: &'a usize, y: &'b usize) -> (&'c usize, &'d usize) {
+    (x, y) //~ERROR lifetime may not live long enough
+           //~^ERROR lifetime may not live long enough
+}
+
+// Should suggest: 'a: 'c and use 'static instead of 'b
+fn foo2<'a, 'b, 'c>(x: &'a usize, y: &'b usize) -> (&'c usize, &'static usize) {
+    (x, y) //~ERROR lifetime may not live long enough
+           //~^ERROR lifetime may not live long enough
+}
+
+// Should suggest: 'a and 'b are the same and use 'static instead of 'c
+fn foo3<'a, 'b, 'c, 'd, 'e>(
+    x: &'a usize,
+    y: &'b usize,
+    z: &'c usize,
+) -> (&'b usize, &'a usize, &'static usize) {
+    (x, y, z) //~ERROR lifetime may not live long enough
+              //~^ERROR lifetime may not live long enough
+              //~^^ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/outlives-suggestion-more.stderr b/src/test/ui/nll/outlives-suggestion-more.stderr
new file mode 100644
index 00000000000..2ebcbf5cbaf
--- /dev/null
+++ b/src/test/ui/nll/outlives-suggestion-more.stderr
@@ -0,0 +1,100 @@
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-more.rs:7:5
+   |
+LL | fn foo1<'a, 'b, 'c, 'd>(x: &'a usize, y: &'b usize) -> (&'c usize, &'d usize) {
+   |         --      -- lifetime `'c` defined here
+   |         |
+   |         lifetime `'a` defined here
+LL |     (x, y)
+   |     ^^^^^^ returning this value requires that `'a` must outlive `'c`
+   |
+   = help: consider adding the following bound: `'a: 'c`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-more.rs:7:5
+   |
+LL | fn foo1<'a, 'b, 'c, 'd>(x: &'a usize, y: &'b usize) -> (&'c usize, &'d usize) {
+   |             --      -- lifetime `'d` defined here
+   |             |
+   |             lifetime `'b` defined here
+LL |     (x, y)
+   |     ^^^^^^ returning this value requires that `'b` must outlive `'d`
+   |
+   = help: consider adding the following bound: `'b: 'd`
+
+help: the following changes may resolve your lifetime errors
+   |
+   = help: add bound `'a: 'c`
+   = help: add bound `'b: 'd`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-more.rs:13:5
+   |
+LL | fn foo2<'a, 'b, 'c>(x: &'a usize, y: &'b usize) -> (&'c usize, &'static usize) {
+   |         --      -- lifetime `'c` defined here
+   |         |
+   |         lifetime `'a` defined here
+LL |     (x, y)
+   |     ^^^^^^ returning this value requires that `'a` must outlive `'c`
+   |
+   = help: consider adding the following bound: `'a: 'c`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-more.rs:13:5
+   |
+LL | fn foo2<'a, 'b, 'c>(x: &'a usize, y: &'b usize) -> (&'c usize, &'static usize) {
+   |             -- lifetime `'b` defined here
+LL |     (x, y)
+   |     ^^^^^^ returning this value requires that `'b` must outlive `'static`
+   |
+   = help: consider replacing `'b` with `'static`
+
+help: the following changes may resolve your lifetime errors
+   |
+   = help: add bound `'a: 'c`
+   = help: replace `'b` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-more.rs:23:5
+   |
+LL | fn foo3<'a, 'b, 'c, 'd, 'e>(
+   |         --  -- lifetime `'b` defined here
+   |         |
+   |         lifetime `'a` defined here
+...
+LL |     (x, y, z)
+   |     ^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-more.rs:23:5
+   |
+LL | fn foo3<'a, 'b, 'c, 'd, 'e>(
+   |         --  -- lifetime `'b` defined here
+   |         |
+   |         lifetime `'a` defined here
+...
+LL |     (x, y, z)
+   |     ^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-more.rs:23:5
+   |
+LL | fn foo3<'a, 'b, 'c, 'd, 'e>(
+   |                 -- lifetime `'c` defined here
+...
+LL |     (x, y, z)
+   |     ^^^^^^^^^ returning this value requires that `'c` must outlive `'static`
+   |
+   = help: consider replacing `'c` with `'static`
+
+help: the following changes may resolve your lifetime errors
+   |
+   = help: `'a` and `'b` must be the same: replace one with the other
+   = help: replace `'c` with `'static`
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/nll/outlives-suggestion-simple.rs b/src/test/ui/nll/outlives-suggestion-simple.rs
new file mode 100644
index 00000000000..91a7a1d71e8
--- /dev/null
+++ b/src/test/ui/nll/outlives-suggestion-simple.rs
@@ -0,0 +1,77 @@
+// Test the simplest of outlives suggestions.
+
+#![feature(nll)]
+
+fn foo1<'a, 'b>(x: &'a usize) -> &'b usize {
+    x //~ERROR lifetime may not live long enough
+}
+
+fn foo2<'a>(x: &'a usize) -> &'static usize {
+    x //~ERROR lifetime may not live long enough
+}
+
+fn foo3<'a, 'b>(x: &'a usize, y: &'b usize) -> (&'b usize, &'a usize) {
+    (x, y) //~ERROR lifetime may not live long enough
+           //~^ERROR lifetime may not live long enough
+}
+
+fn foo4<'a, 'b, 'c>(x: &'a usize) -> (&'b usize, &'c usize) {
+    // FIXME: ideally, we suggest 'a: 'b + 'c, but as of today (may 04, 2019), the null error
+    // reporting stops after the first error in a MIR def so as not to produce too many errors, so
+    // currently we only report 'a: 'b. The user would then re-run and get another error.
+    (x, x) //~ERROR lifetime may not live long enough
+}
+
+struct Foo<'a> {
+    x: &'a usize,
+}
+
+impl Foo<'static> {
+    pub fn foo<'a>(x: &'a usize) -> Self {
+        Foo { x } //~ERROR lifetime may not live long enough
+    }
+}
+
+struct Bar<'a> {
+    x: &'a usize,
+}
+
+impl<'a> Bar<'a> {
+    pub fn get<'b>(&self) -> &'b usize {
+        self.x //~ERROR lifetime may not live long enough
+    }
+}
+
+// source: https://stackoverflow.com/questions/41417057/why-do-i-get-a-lifetime-error-when-i-use-a-mutable-reference-in-a-struct-instead
+struct Baz<'a> {
+    x: &'a mut i32,
+}
+
+impl<'a> Baz<'a> {
+    fn get<'b>(&'b self) -> &'a i32 {
+        self.x //~ERROR lifetime may not live long enough
+    }
+}
+
+// source: https://stackoverflow.com/questions/41204134/rust-lifetime-error
+struct Bar2<'a> {
+    bar: &'a str,
+}
+impl<'a> Bar2<'a> {
+    fn new(foo: &'a Foo2<'a>) -> Bar2<'a> {
+        Bar2 { bar: foo.raw }
+    }
+}
+
+pub struct Foo2<'a> {
+    raw: &'a str,
+    cell: std::cell::Cell<&'a str>,
+}
+impl<'a> Foo2<'a> {
+    // should not produce outlives suggestions to name 'self
+    fn get_bar(&self) -> Bar2 {
+        Bar2::new(&self) //~ERROR borrowed data escapes outside of function
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/outlives-suggestion-simple.stderr b/src/test/ui/nll/outlives-suggestion-simple.stderr
new file mode 100644
index 00000000000..f7603e29d48
--- /dev/null
+++ b/src/test/ui/nll/outlives-suggestion-simple.stderr
@@ -0,0 +1,108 @@
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:6:5
+   |
+LL | fn foo1<'a, 'b>(x: &'a usize) -> &'b usize {
+   |         --  -- lifetime `'b` defined here
+   |         |
+   |         lifetime `'a` defined here
+LL |     x
+   |     ^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:10:5
+   |
+LL | fn foo2<'a>(x: &'a usize) -> &'static usize {
+   |         -- lifetime `'a` defined here
+LL |     x
+   |     ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:14:5
+   |
+LL | fn foo3<'a, 'b>(x: &'a usize, y: &'b usize) -> (&'b usize, &'a usize) {
+   |         --  -- lifetime `'b` defined here
+   |         |
+   |         lifetime `'a` defined here
+LL |     (x, y)
+   |     ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:14:5
+   |
+LL | fn foo3<'a, 'b>(x: &'a usize, y: &'b usize) -> (&'b usize, &'a usize) {
+   |         --  -- lifetime `'b` defined here
+   |         |
+   |         lifetime `'a` defined here
+LL |     (x, y)
+   |     ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+help: `'a` and `'b` must be the same: replace one with the other
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:22:5
+   |
+LL | fn foo4<'a, 'b, 'c>(x: &'a usize) -> (&'b usize, &'c usize) {
+   |         --  -- lifetime `'b` defined here
+   |         |
+   |         lifetime `'a` defined here
+...
+LL |     (x, x)
+   |     ^^^^^^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:31:9
+   |
+LL |     pub fn foo<'a>(x: &'a usize) -> Self {
+   |                -- lifetime `'a` defined here
+LL |         Foo { x }
+   |         ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:41:9
+   |
+LL | impl<'a> Bar<'a> {
+   |      -- lifetime `'a` defined here
+LL |     pub fn get<'b>(&self) -> &'b usize {
+   |                -- lifetime `'b` defined here
+LL |         self.x
+   |         ^^^^^^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:52:9
+   |
+LL | impl<'a> Baz<'a> {
+   |      -- lifetime `'a` defined here
+LL |     fn get<'b>(&'b self) -> &'a i32 {
+   |            -- lifetime `'b` defined here
+LL |         self.x
+   |         ^^^^^^ returning this value requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/outlives-suggestion-simple.rs:73:9
+   |
+LL |     fn get_bar(&self) -> Bar2 {
+   |                -----
+   |                |
+   |                `self` is declared here, outside of the function body
+   |                `self` is a reference that is only valid in the function body
+LL |         Bar2::new(&self)
+   |         ^^^^^^^^^^^^^^^^ `self` escapes the function body here
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
index c5c0e106c8a..d33f6722298 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
@@ -50,6 +50,8 @@ LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 ...
 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
@@ -104,6 +106,8 @@ LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 ...
 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/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
index 3fcf9731fc3..0be25de72f3 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
@@ -41,6 +41,8 @@ LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 ...
 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-trait-bound-closure.rs:47:29
@@ -86,6 +88,8 @@ LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 ...
 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-trait-bound-closure.rs:60:29
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
index c4f65a29b8e..ed548a3b4e2 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
@@ -236,6 +236,8 @@ LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 ...
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 note: External requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:97:29
diff --git a/src/test/ui/nll/ty-outlives/wf-unreachable.stderr b/src/test/ui/nll/ty-outlives/wf-unreachable.stderr
index 9128fd16479..f15c2ffd0d7 100644
--- a/src/test/ui/nll/ty-outlives/wf-unreachable.stderr
+++ b/src/test/ui/nll/ty-outlives/wf-unreachable.stderr
@@ -6,6 +6,8 @@ LL | fn uninit<'a>() {
 LL |     return;
 LL |     let x: &'static &'a ();
    |            ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/wf-unreachable.rs:13:12
@@ -15,6 +17,8 @@ LL | fn var_type<'a>() {
 LL |     return;
 LL |     let x: &'static &'a () = &&();
    |            ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/wf-unreachable.rs:17:12
@@ -23,6 +27,8 @@ LL | fn uninit_infer<'a>() {
    |                 -- lifetime `'a` defined here
 LL |     let x: &'static &'a _;
    |            ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/wf-unreachable.rs:23:12
@@ -32,6 +38,8 @@ LL | fn infer<'a>() {
 LL |     return;
 LL |     let x: &'static &'a _ = &&();
    |            ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/wf-unreachable.rs:28:12
@@ -41,6 +49,8 @@ LL | fn uninit_no_var<'a>() {
 LL |     return;
 LL |     let _: &'static &'a ();
    |            ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/wf-unreachable.rs:33:12
@@ -50,6 +60,8 @@ LL | fn no_var<'a>() {
 LL |     return;
 LL |     let _: &'static &'a () = &&();
    |            ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/wf-unreachable.rs:38:12
@@ -59,6 +71,8 @@ LL | fn infer_no_var<'a>() {
 LL |     return;
 LL |     let _: &'static &'a _ = &&();
    |            ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/wf-unreachable.rs:51:12
@@ -68,6 +82,8 @@ LL | fn required_substs<'a>() {
 LL |     return;
 LL |     let _: C<'static, 'a, _> = C((), &(), &());
    |            ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/nll/type-check-pointer-coercions.stderr b/src/test/ui/nll/type-check-pointer-coercions.stderr
index 9aa78dfbd4a..39fd98f7151 100644
--- a/src/test/ui/nll/type-check-pointer-coercions.stderr
+++ b/src/test/ui/nll/type-check-pointer-coercions.stderr
@@ -7,6 +7,8 @@ LL | fn shared_to_const<'a, 'b>(x: &&'a i32) -> *const &'b i32 {
    |                    lifetime `'a` defined here
 LL |     x
    |     ^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-coercions.rs:8:5
@@ -17,6 +19,8 @@ LL | fn unique_to_const<'a, 'b>(x: &mut &'a i32) -> *const &'b i32 {
    |                    lifetime `'a` defined here
 LL |     x
    |     ^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-coercions.rs:13:5
@@ -28,6 +32,8 @@ LL | fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 {
 LL |     // Two errors because *mut is invariant
 LL |     x
    |     ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-coercions.rs:13:5
@@ -39,6 +45,10 @@ LL | fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 {
 LL |     // Two errors because *mut is invariant
 LL |     x
    |     ^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+help: `'b` and `'a` must be the same: replace one with the other
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-coercions.rs:18:5
@@ -49,6 +59,8 @@ LL | fn mut_to_const<'a, 'b>(x: *mut &'a i32) -> *const &'b i32 {
    |                 lifetime `'a` defined here
 LL |     x
    |     ^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-coercions.rs:24:5
@@ -60,6 +72,8 @@ LL | fn array_elem<'a, 'b>(x: &'a i32) -> *const &'b i32 {
 ...
 LL |     y
    |     ^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-coercions.rs:30:5
@@ -71,6 +85,8 @@ LL | fn array_coerce<'a, 'b>(x: &'a i32) -> *const [&'b i32; 3] {
 ...
 LL |     y
    |     ^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-coercions.rs:36:5
@@ -82,6 +98,8 @@ LL | fn nested_array<'a, 'b>(x: &'a i32) -> *const [&'b i32; 2] {
 ...
 LL |     y
    |     ^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/nll/type-check-pointer-comparisons.stderr b/src/test/ui/nll/type-check-pointer-comparisons.stderr
index c0a994cfb63..f350b861eb6 100644
--- a/src/test/ui/nll/type-check-pointer-comparisons.stderr
+++ b/src/test/ui/nll/type-check-pointer-comparisons.stderr
@@ -7,6 +7,8 @@ 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`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-comparisons.rs:6:10
@@ -17,6 +19,10 @@ 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 `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+help: `'a` and `'b` must be the same: replace one with the other
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-comparisons.rs:12:5
@@ -27,6 +33,8 @@ 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`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-comparisons.rs:12:10
@@ -37,6 +45,10 @@ LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
    |                lifetime `'a` defined here
 LL |     x == y;
    |          ^ requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+help: `'a` and `'b` must be the same: replace one with the other
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-comparisons.rs:18:5
@@ -47,6 +59,8 @@ 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`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-comparisons.rs:18:10
@@ -57,6 +71,10 @@ 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 `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+help: `'a` and `'b` must be the same: replace one with the other
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/nll/user-annotations/closure-substs.stderr b/src/test/ui/nll/user-annotations/closure-substs.stderr
index 384d53f0e4b..e3e294106d1 100644
--- a/src/test/ui/nll/user-annotations/closure-substs.stderr
+++ b/src/test/ui/nll/user-annotations/closure-substs.stderr
@@ -6,6 +6,8 @@ LL | fn foo<'a>() {
 ...
 LL |         return x;
    |                ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/closure-substs.rs:15:16
@@ -23,6 +25,8 @@ LL | fn bar<'a>() {
 ...
 LL |         b(x);
    |         ^^^^ argument requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error[E0521]: borrowed data escapes outside of closure
   --> $DIR/closure-substs.rs:29:9
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.nll.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.nll.stderr
index c39301588ac..e9a0b8173ce 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.nll.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.nll.stderr
@@ -5,6 +5,8 @@ LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
    |        -- lifetime `'a` defined here
 LL |     <Foo<'a>>::C
    |     ^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.nll.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.nll.stderr
index 541a2cfaf29..52ec36ef542 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.nll.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.nll.stderr
@@ -5,6 +5,8 @@ LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
    |        -- lifetime `'a` defined here
 LL |     <() as Foo<'a>>::C
    |     ^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.nll.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.nll.stderr
index ea0fcb6d634..5f3212eb9aa 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.nll.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.nll.stderr
@@ -5,6 +5,8 @@ LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
    |        -- lifetime `'a` defined here
 LL |     <() as Foo<'a>>::C
    |     ^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.nll.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.nll.stderr
index ff549f1d88b..490030d30f3 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.nll.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.nll.stderr
@@ -5,6 +5,8 @@ LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 {
    |        -- lifetime `'a` defined here
 LL |     <T as Foo<'a>>::C
    |     ^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.nll.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.nll.stderr
index 7f160d8e398..5e687805c6f 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.nll.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.nll.stderr
@@ -5,6 +5,8 @@ LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 {
    |        -- lifetime `'a` defined here
 LL |     T::C
    |     ^^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/user-annotations/inherent-associated-constants.stderr b/src/test/ui/nll/user-annotations/inherent-associated-constants.stderr
index 76845469898..7b5646de775 100644
--- a/src/test/ui/nll/user-annotations/inherent-associated-constants.stderr
+++ b/src/test/ui/nll/user-annotations/inherent-associated-constants.stderr
@@ -5,6 +5,8 @@ LL | fn non_wf_associated_const<'a>(x: i32) {
    |                            -- lifetime `'a` defined here
 LL |     A::<'a>::IC;
    |     ^^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/user-annotations/issue-54124.stderr b/src/test/ui/nll/user-annotations/issue-54124.stderr
index 6cfccf7cb69..97653b8c199 100644
--- a/src/test/ui/nll/user-annotations/issue-54124.stderr
+++ b/src/test/ui/nll/user-annotations/issue-54124.stderr
@@ -15,6 +15,8 @@ LL | fn test<'a>() {
    |         -- lifetime `'a` defined here
 LL |     let _:fn(&()) = |_:&'a ()| {};
    |                      ^ requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr
index 5929707e41e..f23ea9fdb5c 100644
--- a/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr
+++ b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr
@@ -6,6 +6,8 @@ LL | fn coupled_regions_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
 ...
 LL |     y
    |     ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/issue-55748-pat-types-constrain-bindings.rs:49:5
@@ -15,6 +17,8 @@ LL | fn coupled_types_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
 ...
 LL |     y
    |     ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/issue-55748-pat-types-constrain-bindings.rs:62:5
@@ -24,6 +28,8 @@ LL | fn coupled_wilds_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
 ...
 LL |     y
    |     ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr b/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr
index c99f53c5aa4..426c57ef9c4 100644
--- a/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr
+++ b/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr
@@ -6,6 +6,8 @@ LL | fn coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
 LL |     let ((y, _z),) = ((s, _x),): (PairCoupledTypes<_>,);
 LL |     y
    |     ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/issue-57731-ascibed-coupled-types.rs:22:5
@@ -15,6 +17,8 @@ LL | fn coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
 LL |     let ((y, _z),) = ((s, _x),): (PairCoupledRegions<_>,);
 LL |     y
    |     ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/issue-57731-ascibed-coupled-types.rs:32:5
@@ -24,6 +28,8 @@ LL | fn cast_coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32
 LL |     let ((y, _z),) = ((s, _x),) as (PairCoupledTypes<_>,);
 LL |     y
    |     ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/issue-57731-ascibed-coupled-types.rs:37:5
@@ -33,6 +39,8 @@ LL | fn cast_coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u
 LL |     let ((y, _z),) = ((s, _x),) as (PairCoupledRegions<_>,);
 LL |     y
    |     ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/nll/user-annotations/patterns.stderr b/src/test/ui/nll/user-annotations/patterns.stderr
index 7ebd0ae227a..c2786f0e8cc 100644
--- a/src/test/ui/nll/user-annotations/patterns.stderr
+++ b/src/test/ui/nll/user-annotations/patterns.stderr
@@ -156,6 +156,8 @@ LL | fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 {
 ...
 LL |     y
    |     ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/patterns.rs:125:5
@@ -165,6 +167,8 @@ LL | fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 {
 ...
 LL |     y
    |     ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/patterns.rs:130:5
@@ -174,6 +178,8 @@ LL | fn static_to_a_to_static_through_struct<'a>(_x: &'a u32) -> &'static u32 {
 LL |     let Single { value: y }: Single<&'a u32> = Single { value: &22 };
 LL |     y
    |     ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/patterns.rs:134:18
@@ -182,6 +188,8 @@ LL | fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 {
    |                            -- lifetime `'a` defined here
 LL |     let (y, _z): (&'static u32, u32) = (x, 44);
    |                  ^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to 19 previous errors
 
diff --git a/src/test/ui/nll/user-annotations/wf-self-type.stderr b/src/test/ui/nll/user-annotations/wf-self-type.stderr
index 8f8e1bc28f6..33bb1c519b1 100644
--- a/src/test/ui/nll/user-annotations/wf-self-type.stderr
+++ b/src/test/ui/nll/user-annotations/wf-self-type.stderr
@@ -7,6 +7,8 @@ LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
    |            lifetime `'a` defined here
 LL |     Foo::xmute(u)
    |     ^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/where_clauses_in_functions.stderr b/src/test/ui/nll/where_clauses_in_functions.stderr
index f3b65ec31ac..1badb7d753b 100644
--- a/src/test/ui/nll/where_clauses_in_functions.stderr
+++ b/src/test/ui/nll/where_clauses_in_functions.stderr
@@ -7,6 +7,8 @@ LL | fn bar<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
    |        lifetime `'a` defined here
 LL |     foo(x, y)
    |     ^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/where_clauses_in_structs.stderr b/src/test/ui/nll/where_clauses_in_structs.stderr
index e0feb40273f..2e990131e61 100644
--- a/src/test/ui/nll/where_clauses_in_structs.stderr
+++ b/src/test/ui/nll/where_clauses_in_structs.stderr
@@ -7,6 +7,8 @@ LL | fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) {
    |        lifetime `'a` defined here
 LL |     Foo { x, y };
    |           ^ requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-elision.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-elision.nll.stderr
index e94f2a92125..900cdfca244 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-elision.nll.stderr
+++ b/src/test/ui/object-lifetime/object-lifetime-default-elision.nll.stderr
@@ -8,6 +8,8 @@ LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
 ...
 LL |     ss
    |     ^^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr
index 7d6f9f39d13..defffe2b84b 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr
@@ -5,6 +5,8 @@ LL | fn c<'a>(t: &'a Box<dyn Test+'a>, mut ss: SomeStruct<'a>) {
    |      -- lifetime `'a` defined here
 LL |     ss.t = t;
    |     ^^^^^^^^ assignment requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr
index 6df54638ce0..8c28a7a011a 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr
@@ -5,6 +5,8 @@ LL | fn c<'a>(t: &'a MyBox<dyn Test+'a>, mut ss: SomeStruct<'a>) {
    |      -- lifetime `'a` defined here
 LL |     ss.t = t;
    |     ^^^^^^^^ assignment requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-mybox.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-mybox.nll.stderr
index cdfbf0fc878..d871eb5327d 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-mybox.nll.stderr
+++ b/src/test/ui/object-lifetime/object-lifetime-default-mybox.nll.stderr
@@ -8,6 +8,8 @@ LL | fn load1<'a,'b>(a: &'a MyBox<dyn SomeTrait>,
 ...
 LL |     a
    |     ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error[E0521]: borrowed data escapes outside of function
   --> $DIR/object-lifetime-default-mybox.rs:31:5
@@ -16,6 +18,8 @@ LL | fn load2<'a>(ss: &MyBox<dyn SomeTrait + 'a>) -> MyBox<dyn SomeTrait + 'a> {
    |              -- `ss` is a reference that is only valid in the function body
 LL |     load0(ss)
    |     ^^^^^^^^^ `ss` escapes the function body here
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr b/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr
index 76129b4d188..d941030d824 100644
--- a/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr
+++ b/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr
@@ -6,6 +6,8 @@ LL | fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) {
 LL |     let bad = if x.is_some() {
 LL |         x.unwrap()
    |         ^^^^^^^^^^ `x` escapes the function body here
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/region-object-lifetime-2.nll.stderr b/src/test/ui/regions/region-object-lifetime-2.nll.stderr
index 60084773466..db45a03ad18 100644
--- a/src/test/ui/regions/region-object-lifetime-2.nll.stderr
+++ b/src/test/ui/regions/region-object-lifetime-2.nll.stderr
@@ -7,6 +7,8 @@ LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () {
    |                                          lifetime `'a` defined here
 LL |     x.borrowed()
    |     ^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/region-object-lifetime-4.nll.stderr b/src/test/ui/regions/region-object-lifetime-4.nll.stderr
index 75b049dae21..fda66a2412c 100644
--- a/src/test/ui/regions/region-object-lifetime-4.nll.stderr
+++ b/src/test/ui/regions/region-object-lifetime-4.nll.stderr
@@ -7,6 +7,8 @@ LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'
    |                                         lifetime `'a` defined here
 LL |     x.borrowed()
    |     ^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
index 43acbfd412d..767853d8148 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
@@ -32,6 +32,8 @@ LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
    |      lifetime `'a` defined here
 LL |     Box::new(v)
    |     ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr
index 4944f2649b7..9bb385b0dcd 100644
--- a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr
+++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr
@@ -8,6 +8,8 @@ LL | fn with_assoc<'a,'b>() {
 ...
 LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.nll.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.nll.stderr
index 4944f2649b7..9bb385b0dcd 100644
--- a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.nll.stderr
+++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.nll.stderr
@@ -8,6 +8,8 @@ LL | fn with_assoc<'a,'b>() {
 ...
 LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-bounded-by-trait-requiring-static.nll.stderr b/src/test/ui/regions/regions-bounded-by-trait-requiring-static.nll.stderr
index 86bd100538d..ca153b9d9b1 100644
--- a/src/test/ui/regions/regions-bounded-by-trait-requiring-static.nll.stderr
+++ b/src/test/ui/regions/regions-bounded-by-trait-requiring-static.nll.stderr
@@ -5,6 +5,8 @@ LL | fn param_not_ok<'a>(x: &'a isize) {
    |                 -- lifetime `'a` defined here
 LL |     assert_send::<&'a isize>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/regions-bounded-by-trait-requiring-static.rs:26:5
@@ -13,6 +15,8 @@ LL | fn param_not_ok1<'a>(_: &'a isize) {
    |                  -- lifetime `'a` defined here
 LL |     assert_send::<&'a str>();
    |     ^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/regions-bounded-by-trait-requiring-static.rs:30:5
@@ -21,6 +25,8 @@ LL | fn param_not_ok2<'a>(_: &'a isize) {
    |                  -- lifetime `'a` defined here
 LL |     assert_send::<&'a [isize]>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/regions-bounded-by-trait-requiring-static.rs:44:5
@@ -29,6 +35,8 @@ LL | fn box_with_region_not_ok<'a>() {
    |                           -- lifetime `'a` defined here
 LL |     assert_send::<Box<&'a isize>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/regions-bounded-by-trait-requiring-static.rs:55:5
@@ -37,6 +45,8 @@ LL | fn unsafe_ok2<'a>(_: &'a isize) {
    |               -- lifetime `'a` defined here
 LL |     assert_send::<*const &'a isize>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/regions-bounded-by-trait-requiring-static.rs:59:5
@@ -45,6 +55,8 @@ LL | fn unsafe_ok3<'a>(_: &'a isize) {
    |               -- lifetime `'a` defined here
 LL |     assert_send::<*mut &'a isize>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.nll.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.nll.stderr
index a8ab92d75c0..47796e50a88 100644
--- a/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.nll.stderr
+++ b/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.nll.stderr
@@ -8,6 +8,8 @@ LL | fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) {
 LL |     // Here the value provided for 'y is 'y, and hence 'y:'x does not hold.
 LL |     a.bigger_region(b)
    |     ^^^^^^^^^^^^^^^^^^ argument requires that `'y` must outlive `'x`
+   |
+   = help: consider adding the following bound: `'y: 'x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr
index 52ad2d9daeb..d352d119a70 100644
--- a/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr
+++ b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr
@@ -8,6 +8,8 @@ LL | fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
 LL |     // Here the value provided for 'y is 'b, and hence 'b:'a does not hold.
 LL |     f.method(b);
    |     ^^^^^^^^^^^ `b` escapes the function body here
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters.nll.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters.nll.stderr
index b6d7b8aac5f..2076772b59d 100644
--- a/src/test/ui/regions/regions-bounded-method-type-parameters.nll.stderr
+++ b/src/test/ui/regions/regions-bounded-method-type-parameters.nll.stderr
@@ -5,6 +5,8 @@ LL | fn caller<'a>(x: &isize) {
    |           -- lifetime `'a` defined here
 LL |     Foo.some_method::<&'a isize>();
    |         ^^^^^^^^^^^ requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-bounds.nll.stderr b/src/test/ui/regions/regions-bounds.nll.stderr
index 3345946bfdd..dd702755c7e 100644
--- a/src/test/ui/regions/regions-bounds.nll.stderr
+++ b/src/test/ui/regions/regions-bounds.nll.stderr
@@ -7,6 +7,8 @@ LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> {
    |          lifetime `'a` defined here
 LL |     return e;
    |            ^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/regions-bounds.rs:13:12
@@ -17,6 +19,8 @@ LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> {
    |          lifetime `'a` defined here
 LL |     return e;
    |            ^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/regions/regions-close-object-into-object-2.nll.stderr b/src/test/ui/regions/regions-close-object-into-object-2.nll.stderr
index 806a3ca8242..882faf4ece3 100644
--- a/src/test/ui/regions/regions-close-object-into-object-2.nll.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-2.nll.stderr
@@ -5,6 +5,8 @@ LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
    |      -- lifetime `'a` defined here
 LL |     box B(&*v) as Box<dyn X>
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error[E0515]: cannot return value referencing local data `*v`
   --> $DIR/regions-close-object-into-object-2.rs:10:5
diff --git a/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr b/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr
index 1e57023bc23..93ac17810da 100644
--- a/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr
@@ -13,6 +13,8 @@ LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
    |      -- lifetime `'a` defined here
 LL |     box B(&*v) as Box<dyn X>
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error[E0515]: cannot return value referencing local data `*v`
   --> $DIR/regions-close-object-into-object-4.rs:10:5
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.nll.stderr b/src/test/ui/regions/regions-close-over-type-parameter-multiple.nll.stderr
index 88d6abd1428..2fb9dcc4e9e 100644
--- a/src/test/ui/regions/regions-close-over-type-parameter-multiple.nll.stderr
+++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.nll.stderr
@@ -8,6 +8,8 @@ LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait +
 LL |     // A outlives 'a AND 'b...but not 'c.
 LL |     box v as Box<dyn SomeTrait + 'a>
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'c`
+   |
+   = help: consider adding the following bound: `'a: 'c`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-creating-enums3.nll.stderr b/src/test/ui/regions/regions-creating-enums3.nll.stderr
index e35a878fce1..41d609b56d2 100644
--- a/src/test/ui/regions/regions-creating-enums3.nll.stderr
+++ b/src/test/ui/regions/regions-creating-enums3.nll.stderr
@@ -7,6 +7,8 @@ LL | fn mk_add_bad1<'a,'b>(x: &'a Ast<'a>, y: &'b Ast<'b>) -> Ast<'a> {
    |                lifetime `'a` defined here
 LL |     Ast::Add(x, y)
    |     ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-creating-enums4.nll.stderr b/src/test/ui/regions/regions-creating-enums4.nll.stderr
index 4eac457feda..dda374c90d9 100644
--- a/src/test/ui/regions/regions-creating-enums4.nll.stderr
+++ b/src/test/ui/regions/regions-creating-enums4.nll.stderr
@@ -7,6 +7,8 @@ LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> {
    |                lifetime `'a` defined here
 LL |     Ast::Add(x, y)
    |     ^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-early-bound-error-method.nll.stderr b/src/test/ui/regions/regions-early-bound-error-method.nll.stderr
index 1540a7bacd7..4957bcf3f73 100644
--- a/src/test/ui/regions/regions-early-bound-error-method.nll.stderr
+++ b/src/test/ui/regions/regions-early-bound-error-method.nll.stderr
@@ -7,6 +7,8 @@ LL |     fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize {
    |           -- lifetime `'b` defined here
 LL |         g2.get()
    |         ^^^^^^^^ returning this value requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-early-bound-error.nll.stderr b/src/test/ui/regions/regions-early-bound-error.nll.stderr
index 7836291a7ca..eb4cd5ca72e 100644
--- a/src/test/ui/regions/regions-early-bound-error.nll.stderr
+++ b/src/test/ui/regions/regions-early-bound-error.nll.stderr
@@ -7,6 +7,8 @@ LL | fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize {
    |        lifetime `'a` defined here
 LL |     g1.get()
    |     ^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr
index 9ae484eaf45..f61f068a486 100644
--- a/src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr
+++ b/src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr
@@ -8,6 +8,8 @@ LL | fn ordering2<'a, 'b>(x: &'a &'b usize, y: &'a usize) -> &'b usize {
 LL |     // However, it is not safe to assume that 'b <= 'a
 LL |     &*y
    |     ^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/regions-free-region-ordering-callee.rs:18:12
@@ -19,6 +21,8 @@ LL | fn ordering3<'a, 'b>(x: &'a usize, y: &'b usize) -> &'a &'b usize {
 LL |     // Do not infer an ordering from the return value.
 LL |     let z: &'b usize = &*x;
    |            ^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.migrate.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.migrate.nll.stderr
index 16eda2844c6..0d4694a64d0 100644
--- a/src/test/ui/regions/regions-free-region-ordering-caller.migrate.nll.stderr
+++ b/src/test/ui/regions/regions-free-region-ordering-caller.migrate.nll.stderr
@@ -7,6 +7,8 @@ LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          lifetime `'a` defined here
 LL |     let z: Option<&'b &'a usize> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/regions-free-region-ordering-caller.rs:17:12
@@ -18,6 +20,8 @@ LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
 LL |     let y: Paramd<'a> = Paramd { x: a };
 LL |     let z: Option<&'b Paramd<'a>> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/regions-free-region-ordering-caller.rs:22:12
@@ -28,6 +32,8 @@ LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          lifetime `'a` defined here
 LL |     let z: Option<&'a &'b usize> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.nll.stderr
index 16eda2844c6..0d4694a64d0 100644
--- a/src/test/ui/regions/regions-free-region-ordering-caller.nll.stderr
+++ b/src/test/ui/regions/regions-free-region-ordering-caller.nll.stderr
@@ -7,6 +7,8 @@ LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          lifetime `'a` defined here
 LL |     let z: Option<&'b &'a usize> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/regions-free-region-ordering-caller.rs:17:12
@@ -18,6 +20,8 @@ LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
 LL |     let y: Paramd<'a> = Paramd { x: a };
 LL |     let z: Option<&'b Paramd<'a>> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/regions-free-region-ordering-caller.rs:22:12
@@ -28,6 +32,8 @@ LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          lifetime `'a` defined here
 LL |     let z: Option<&'a &'b usize> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/regions/regions-free-region-ordering-incorrect.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-incorrect.nll.stderr
index 480a81d33f6..106d3df2744 100644
--- a/src/test/ui/regions/regions-free-region-ordering-incorrect.nll.stderr
+++ b/src/test/ui/regions/regions-free-region-ordering-incorrect.nll.stderr
@@ -10,6 +10,8 @@ LL | |             Some(ref next) => next.get(),
 LL | |             None => &self.val
 LL | |         }
    | |_________^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-infer-contravariance-due-to-decl.nll.stderr b/src/test/ui/regions/regions-infer-contravariance-due-to-decl.nll.stderr
index cefeecf16e2..94b80852d01 100644
--- a/src/test/ui/regions/regions-infer-contravariance-due-to-decl.nll.stderr
+++ b/src/test/ui/regions/regions-infer-contravariance-due-to-decl.nll.stderr
@@ -8,6 +8,8 @@ LL | fn use_<'short,'long>(c: Contravariant<'short>,
 ...
 LL |     let _: Contravariant<'long> = c;
    |            ^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long`
+   |
+   = help: consider adding the following bound: `'short: 'long`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-infer-covariance-due-to-decl.nll.stderr b/src/test/ui/regions/regions-infer-covariance-due-to-decl.nll.stderr
index 1bddecba50a..f44a0fad59b 100644
--- a/src/test/ui/regions/regions-infer-covariance-due-to-decl.nll.stderr
+++ b/src/test/ui/regions/regions-infer-covariance-due-to-decl.nll.stderr
@@ -8,6 +8,8 @@ LL | fn use_<'short,'long>(c: Covariant<'long>,
 ...
 LL |     let _: Covariant<'short> = c;
    |            ^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long`
+   |
+   = help: consider adding the following bound: `'short: 'long`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-decl.nll.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-decl.nll.stderr
index 0c1e3989b23..3256e3c0dd3 100644
--- a/src/test/ui/regions/regions-infer-invariance-due-to-decl.nll.stderr
+++ b/src/test/ui/regions/regions-infer-invariance-due-to-decl.nll.stderr
@@ -5,6 +5,8 @@ LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> {
    |                       -- lifetime `'r` defined here
 LL |     b_isize
    |     ^^^^^^^ returning this value requires that `'r` must outlive `'static`
+   |
+   = help: consider replacing `'r` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.nll.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.nll.stderr
index 0edeb272399..991f9a287b9 100644
--- a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.nll.stderr
+++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.nll.stderr
@@ -5,6 +5,8 @@ LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> {
    |                       -- lifetime `'r` defined here
 LL |     b_isize
    |     ^^^^^^^ returning this value requires that `'r` must outlive `'static`
+   |
+   = help: consider replacing `'r` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.nll.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.nll.stderr
index 724dd7e3f6d..2d62fb85b81 100644
--- a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.nll.stderr
+++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.nll.stderr
@@ -5,6 +5,8 @@ LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> {
    |                       -- lifetime `'r` defined here
 LL |     b_isize
    |     ^^^^^^^ returning this value requires that `'r` must outlive `'static`
+   |
+   = help: consider replacing `'r` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-infer-not-param.nll.stderr b/src/test/ui/regions/regions-infer-not-param.nll.stderr
index 2064b060ec4..fcc2ec31f3e 100644
--- a/src/test/ui/regions/regions-infer-not-param.nll.stderr
+++ b/src/test/ui/regions/regions-infer-not-param.nll.stderr
@@ -5,6 +5,8 @@ LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p }
    |                -- -- lifetime `'b` defined here      ^ returning this value requires that `'a` must outlive `'b`
    |                |
    |                lifetime `'a` defined here
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/regions-infer-not-param.rs:19:63
@@ -13,6 +15,8 @@ LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p }
    |                   -- -- lifetime `'b` defined here            ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
    |                   |
    |                   lifetime `'a` defined here
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
   --> $DIR/regions-infer-not-param.rs:19:63
@@ -21,6 +25,10 @@ LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p }
    |                   -- -- lifetime `'b` defined here            ^ returning this value requires that `'a` must outlive `'b`
    |                   |
    |                   lifetime `'a` defined here
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+help: `'b` and `'a` must be the same: replace one with the other
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/regions/regions-nested-fns.nll.stderr b/src/test/ui/regions/regions-nested-fns.nll.stderr
index 97650636cb6..305a76815ac 100644
--- a/src/test/ui/regions/regions-nested-fns.nll.stderr
+++ b/src/test/ui/regions/regions-nested-fns.nll.stderr
@@ -45,6 +45,8 @@ LL | fn nested<'x>(x: &'x isize) {
 ...
 LL |         if false { return x; }
    |                           ^ returning this value requires that `'x` must outlive `'static`
+   |
+   = help: consider replacing `'x` with `'static`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr
index eed9934be12..29e92f33ec9 100644
--- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr
+++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr
@@ -8,6 +8,8 @@ LL | fn with_assoc<'a,'b>() {
 ...
 LL |     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
   --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12
@@ -19,6 +21,8 @@ LL | fn with_assoc_sub<'a,'b>() {
 ...
 LL |     let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr
index eed9934be12..29e92f33ec9 100644
--- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr
+++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr
@@ -8,6 +8,8 @@ LL | fn with_assoc<'a,'b>() {
 ...
 LL |     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
   --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12
@@ -19,6 +21,8 @@ LL | fn with_assoc_sub<'a,'b>() {
 ...
 LL |     let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr
index 8c54d8da0a0..70351443024 100644
--- a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr
+++ b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr
@@ -8,6 +8,8 @@ LL | fn with_assoc<'a,'b>() {
 ...
 LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr
index 8c54d8da0a0..70351443024 100644
--- a/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr
+++ b/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr
@@ -8,6 +8,8 @@ LL | fn with_assoc<'a,'b>() {
 ...
 LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-outlives-projection-container.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container.nll.stderr
index 2cf6e245d19..073a3190022 100644
--- a/src/test/ui/regions/regions-outlives-projection-container.nll.stderr
+++ b/src/test/ui/regions/regions-outlives-projection-container.nll.stderr
@@ -8,6 +8,8 @@ LL | fn with_assoc<'a,'b>() {
 ...
 LL |     let _x: &'a WithAssoc<TheType<'b>> = loop { };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
   --> $DIR/regions-outlives-projection-container.rs:54:13
@@ -19,6 +21,8 @@ LL | fn without_assoc<'a,'b>() {
 ...
 LL |     let _x: &'a WithoutAssoc<TheType<'b>> = loop { };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
   --> $DIR/regions-outlives-projection-container.rs:63:5
@@ -30,6 +34,8 @@ LL | fn call_with_assoc<'a,'b>() {
 ...
 LL |     call::<&'a WithAssoc<TheType<'b>>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
   --> $DIR/regions-outlives-projection-container.rs:70:5
@@ -41,6 +47,8 @@ LL | fn call_without_assoc<'a,'b>() {
 ...
 LL |     call::<&'a WithoutAssoc<TheType<'b>>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.nll.stderr b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.nll.stderr
index c8582f8bfe7..dc905d076bb 100644
--- a/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.nll.stderr
+++ b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.nll.stderr
@@ -7,6 +7,8 @@ LL | fn copy_borrowed_ptr<'a, 'b, 'c>(p: &'a mut &'b mut &'c mut isize) -> &'b m
    |                      lifetime `'a` defined here
 LL |     &mut ***p
    |     ^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.nll.stderr b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.nll.stderr
index 5946e7bf849..c98ec477417 100644
--- a/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.nll.stderr
+++ b/src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.nll.stderr
@@ -7,6 +7,8 @@ LL | fn copy_borrowed_ptr<'a, 'b>(p: &'a mut &'b mut isize) -> &'b mut isize {
    |                      lifetime `'a` defined here
 LL |     &mut **p
    |     ^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-static-bound.migrate.nll.stderr b/src/test/ui/regions/regions-static-bound.migrate.nll.stderr
index b5f3e6cfaba..6f2c75d2eba 100644
--- a/src/test/ui/regions/regions-static-bound.migrate.nll.stderr
+++ b/src/test/ui/regions/regions-static-bound.migrate.nll.stderr
@@ -5,6 +5,8 @@ LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
    |                        -- lifetime `'a` defined here
 LL |     t
    |     ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error[E0621]: explicit lifetime required in the type of `u`
   --> $DIR/regions-static-bound.rs:14:5
diff --git a/src/test/ui/regions/regions-static-bound.nll.stderr b/src/test/ui/regions/regions-static-bound.nll.stderr
index b5f3e6cfaba..6f2c75d2eba 100644
--- a/src/test/ui/regions/regions-static-bound.nll.stderr
+++ b/src/test/ui/regions/regions-static-bound.nll.stderr
@@ -5,6 +5,8 @@ LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
    |                        -- lifetime `'a` defined here
 LL |     t
    |     ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
 
 error[E0621]: explicit lifetime required in the type of `u`
   --> $DIR/regions-static-bound.rs:14:5
diff --git a/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr b/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr
index f4b1a89db9a..f92923a1125 100644
--- a/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr
+++ b/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr
@@ -8,6 +8,8 @@ LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy {
 LL |     // Without knowing 'a:'b, we can't coerce
 LL |     x
    |     ^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
   --> $DIR/regions-trait-object-subtyping.rs:22:5
@@ -19,6 +21,8 @@ LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dum
 LL |     // We can't coerce because it is packed in `Wrapper`
 LL |     x
    |     ^ returning this value requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.nll.stderr b/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.nll.stderr
index f5b96f314c5..5352be430fb 100644
--- a/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.nll.stderr
+++ b/src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.nll.stderr
@@ -8,6 +8,8 @@ LL | fn use_<'short,'long>(c: S<'long, 'short>,
 ...
 LL |     let _: S<'long, 'long> = c;
    |            ^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long`
+   |
+   = help: consider adding the following bound: `'short: 'long`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-variance-contravariant-use-covariant.nll.stderr b/src/test/ui/regions/regions-variance-contravariant-use-covariant.nll.stderr
index 372510a2f7e..22c9b915bb9 100644
--- a/src/test/ui/regions/regions-variance-contravariant-use-covariant.nll.stderr
+++ b/src/test/ui/regions/regions-variance-contravariant-use-covariant.nll.stderr
@@ -8,6 +8,8 @@ LL | fn use_<'short,'long>(c: Contravariant<'short>,
 ...
 LL |     let _: Contravariant<'long> = c;
    |            ^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long`
+   |
+   = help: consider adding the following bound: `'short: 'long`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-variance-covariant-use-contravariant.nll.stderr b/src/test/ui/regions/regions-variance-covariant-use-contravariant.nll.stderr
index e87e914727c..a07181ad553 100644
--- a/src/test/ui/regions/regions-variance-covariant-use-contravariant.nll.stderr
+++ b/src/test/ui/regions/regions-variance-covariant-use-contravariant.nll.stderr
@@ -8,6 +8,8 @@ LL | fn use_<'short,'long>(c: Covariant<'long>,
 ...
 LL |     let _: Covariant<'short> = c;
    |            ^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long`
+   |
+   = help: consider adding the following bound: `'short: 'long`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-variance-invariant-use-contravariant.nll.stderr b/src/test/ui/regions/regions-variance-invariant-use-contravariant.nll.stderr
index adee33bfc7e..d51db99f81f 100644
--- a/src/test/ui/regions/regions-variance-invariant-use-contravariant.nll.stderr
+++ b/src/test/ui/regions/regions-variance-invariant-use-contravariant.nll.stderr
@@ -8,6 +8,8 @@ LL | fn use_<'short,'long>(c: Invariant<'long>,
 ...
 LL |     let _: Invariant<'short> = c;
    |            ^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long`
+   |
+   = help: consider adding the following bound: `'short: 'long`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-variance-invariant-use-covariant.nll.stderr b/src/test/ui/regions/regions-variance-invariant-use-covariant.nll.stderr
index 15853e6ca5d..90388a1c51b 100644
--- a/src/test/ui/regions/regions-variance-invariant-use-covariant.nll.stderr
+++ b/src/test/ui/regions/regions-variance-invariant-use-covariant.nll.stderr
@@ -6,6 +6,8 @@ LL | fn use_<'b>(c: Invariant<'b>) {
 ...
 LL |     let _: Invariant<'static> = c;
    |            ^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'static`
+   |
+   = help: consider replacing `'b` with `'static`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/variance/variance-btree-invariant-types.nll.stderr b/src/test/ui/variance/variance-btree-invariant-types.nll.stderr
index 344437f74e4..be18737b5f1 100644
--- a/src/test/ui/variance/variance-btree-invariant-types.nll.stderr
+++ b/src/test/ui/variance/variance-btree-invariant-types.nll.stderr
@@ -5,6 +5,8 @@ LL | fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &
    |                     ---- lifetime `'new` defined here
 LL |     v
    |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/variance-btree-invariant-types.rs:7:5
@@ -13,6 +15,8 @@ LL | fn iter_cov_val<'a, 'new>(v: IterMut<'a, (), &'static ()>) -> IterMut<'a, (
    |                     ---- lifetime `'new` defined here
 LL |     v
    |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/variance-btree-invariant-types.rs:10:5
@@ -21,6 +25,8 @@ LL | fn iter_contra_key<'a, 'new>(v: IterMut<'a, &'new (), ()>) -> IterMut<'a, &
    |                        ---- lifetime `'new` defined here
 LL |     v
    |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/variance-btree-invariant-types.rs:13:5
@@ -29,6 +35,8 @@ LL | fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (
    |                        ---- lifetime `'new` defined here
 LL |     v
    |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/variance-btree-invariant-types.rs:18:5
@@ -38,6 +46,8 @@ LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>)
 LL |                          -> OccupiedEntry<'a, &'new (), ()> {
 LL |     v
    |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/variance-btree-invariant-types.rs:22:5
@@ -47,6 +57,8 @@ LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>)
 LL |                          -> OccupiedEntry<'a, (), &'new ()> {
 LL |     v
    |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/variance-btree-invariant-types.rs:26:5
@@ -56,6 +68,8 @@ LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>)
 LL |                             -> OccupiedEntry<'a, &'static (), ()> {
 LL |     v
    |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/variance-btree-invariant-types.rs:30:5
@@ -65,6 +79,8 @@ LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>)
 LL |                             -> OccupiedEntry<'a, (), &'static ()> {
 LL |     v
    |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/variance-btree-invariant-types.rs:35:5
@@ -74,6 +90,8 @@ LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>)
 LL |                          -> VacantEntry<'a, &'new (), ()> {
 LL |     v
    |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/variance-btree-invariant-types.rs:39:5
@@ -83,6 +101,8 @@ LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>)
 LL |                          -> VacantEntry<'a, (), &'new ()> {
 LL |     v
    |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/variance-btree-invariant-types.rs:43:5
@@ -92,6 +112,8 @@ LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>)
 LL |                             -> VacantEntry<'a, &'static (), ()> {
 LL |     v
    |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/variance-btree-invariant-types.rs:47:5
@@ -101,6 +123,8 @@ LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>)
 LL |                             -> VacantEntry<'a, (), &'static ()> {
 LL |     v
    |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
 
 error: aborting due to 12 previous errors
 
diff --git a/src/test/ui/variance/variance-cell-is-invariant.nll.stderr b/src/test/ui/variance/variance-cell-is-invariant.nll.stderr
index a3ae5320c90..1fcdfc4b5bb 100644
--- a/src/test/ui/variance/variance-cell-is-invariant.nll.stderr
+++ b/src/test/ui/variance/variance-cell-is-invariant.nll.stderr
@@ -8,6 +8,8 @@ LL | fn use_<'short,'long>(c: Foo<'short>,
 ...
 LL |     let _: Foo<'long> = c;
    |            ^^^^^^^^^^ type annotation requires that `'short` must outlive `'long`
+   |
+   = help: consider adding the following bound: `'short: 'long`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr b/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr
index 69818aedd15..91d4fd2e971 100644
--- a/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr
+++ b/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr
@@ -8,6 +8,8 @@ LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
 ...
 LL |     v
    |     ^ returning this value requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: lifetime may not live long enough
   --> $DIR/variance-contravariant-arg-object.rs:22:5
@@ -19,6 +21,8 @@ LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
 ...
 LL |     v
    |     ^ returning this value requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/variance/variance-contravariant-arg-trait-match.nll.stderr b/src/test/ui/variance/variance-contravariant-arg-trait-match.nll.stderr
index dbd75cb52fa..6f136750ee1 100644
--- a/src/test/ui/variance/variance-contravariant-arg-trait-match.nll.stderr
+++ b/src/test/ui/variance/variance-contravariant-arg-trait-match.nll.stderr
@@ -8,6 +8,8 @@ LL | fn get_min_from_max<'min, 'max, G>()
 ...
 LL |     impls_get::<G,&'min i32>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: lifetime may not live long enough
   --> $DIR/variance-contravariant-arg-trait-match.rs:21:5
@@ -19,6 +21,8 @@ LL | fn get_max_from_min<'min, 'max, G>()
 ...
 LL |     impls_get::<G,&'max i32>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/variance/variance-contravariant-self-trait-match.nll.stderr b/src/test/ui/variance/variance-contravariant-self-trait-match.nll.stderr
index 9212cf24be3..fe08ce0b84d 100644
--- a/src/test/ui/variance/variance-contravariant-self-trait-match.nll.stderr
+++ b/src/test/ui/variance/variance-contravariant-self-trait-match.nll.stderr
@@ -8,6 +8,8 @@ LL | fn get_min_from_max<'min, 'max, G>()
 ...
 LL |     impls_get::<&'min G>();
    |     ^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: lifetime may not live long enough
   --> $DIR/variance-contravariant-self-trait-match.rs:22:5
@@ -19,6 +21,8 @@ LL | fn get_max_from_min<'min, 'max, G>()
 ...
 LL |     impls_get::<&'max G>();
    |     ^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/variance/variance-covariant-arg-object.nll.stderr b/src/test/ui/variance/variance-covariant-arg-object.nll.stderr
index 63ab7fe9651..37fdea960be 100644
--- a/src/test/ui/variance/variance-covariant-arg-object.nll.stderr
+++ b/src/test/ui/variance/variance-covariant-arg-object.nll.stderr
@@ -8,6 +8,8 @@ LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
 ...
 LL |     v
    |     ^ returning this value requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: lifetime may not live long enough
   --> $DIR/variance-covariant-arg-object.rs:22:5
@@ -19,6 +21,8 @@ LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
 ...
 LL |     v
    |     ^ returning this value requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/variance/variance-covariant-arg-trait-match.nll.stderr b/src/test/ui/variance/variance-covariant-arg-trait-match.nll.stderr
index 33589121c4b..a982a29d499 100644
--- a/src/test/ui/variance/variance-covariant-arg-trait-match.nll.stderr
+++ b/src/test/ui/variance/variance-covariant-arg-trait-match.nll.stderr
@@ -8,6 +8,8 @@ LL | fn get_min_from_max<'min, 'max, G>()
 ...
 LL |     impls_get::<G,&'min i32>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: lifetime may not live long enough
   --> $DIR/variance-covariant-arg-trait-match.rs:20:5
@@ -19,6 +21,8 @@ LL | fn get_max_from_min<'min, 'max, G>()
 ...
 LL |     impls_get::<G,&'max i32>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/variance/variance-covariant-self-trait-match.nll.stderr b/src/test/ui/variance/variance-covariant-self-trait-match.nll.stderr
index 6b2413d68be..81b25e38ec6 100644
--- a/src/test/ui/variance/variance-covariant-self-trait-match.nll.stderr
+++ b/src/test/ui/variance/variance-covariant-self-trait-match.nll.stderr
@@ -8,6 +8,8 @@ LL | fn get_min_from_max<'min, 'max, G>()
 ...
 LL |     impls_get::<&'min G>();
    |     ^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: lifetime may not live long enough
   --> $DIR/variance-covariant-self-trait-match.rs:20:5
@@ -19,6 +21,8 @@ LL | fn get_max_from_min<'min, 'max, G>()
 ...
 LL |     impls_get::<&'max G>();
    |     ^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/variance/variance-invariant-arg-object.nll.stderr b/src/test/ui/variance/variance-invariant-arg-object.nll.stderr
index fe2f35b63b5..f6265980af7 100644
--- a/src/test/ui/variance/variance-invariant-arg-object.nll.stderr
+++ b/src/test/ui/variance/variance-invariant-arg-object.nll.stderr
@@ -8,6 +8,8 @@ LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
 ...
 LL |     v
    |     ^ returning this value requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: lifetime may not live long enough
   --> $DIR/variance-invariant-arg-object.rs:18:5
@@ -19,6 +21,8 @@ LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
 ...
 LL |     v
    |     ^ returning this value requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/variance/variance-invariant-arg-trait-match.nll.stderr b/src/test/ui/variance/variance-invariant-arg-trait-match.nll.stderr
index 2ab44c54c72..2909e81fcbf 100644
--- a/src/test/ui/variance/variance-invariant-arg-trait-match.nll.stderr
+++ b/src/test/ui/variance/variance-invariant-arg-trait-match.nll.stderr
@@ -8,6 +8,8 @@ LL | fn get_min_from_max<'min, 'max, G>()
 ...
 LL |     impls_get::<G,&'min i32>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: lifetime may not live long enough
   --> $DIR/variance-invariant-arg-trait-match.rs:16:5
@@ -19,6 +21,8 @@ LL | fn get_max_from_min<'min, 'max, G>()
 ...
 LL |     impls_get::<G,&'max i32>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/variance/variance-invariant-self-trait-match.nll.stderr b/src/test/ui/variance/variance-invariant-self-trait-match.nll.stderr
index 7b7c42fea8d..01b2c8803ae 100644
--- a/src/test/ui/variance/variance-invariant-self-trait-match.nll.stderr
+++ b/src/test/ui/variance/variance-invariant-self-trait-match.nll.stderr
@@ -8,6 +8,8 @@ LL | fn get_min_from_max<'min, 'max, G>()
 ...
 LL |     impls_get::<&'min G>();
    |     ^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: lifetime may not live long enough
   --> $DIR/variance-invariant-self-trait-match.rs:16:5
@@ -19,6 +21,8 @@ LL | fn get_max_from_min<'min, 'max, G>()
 ...
 LL |     impls_get::<&'max G>();
    |     ^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/variance/variance-use-contravariant-struct-1.nll.stderr b/src/test/ui/variance/variance-use-contravariant-struct-1.nll.stderr
index 8468448b27b..eddd4b217c0 100644
--- a/src/test/ui/variance/variance-use-contravariant-struct-1.nll.stderr
+++ b/src/test/ui/variance/variance-use-contravariant-struct-1.nll.stderr
@@ -8,6 +8,8 @@ LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>)
 ...
 LL |     v
    |     ^ returning this value requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/variance/variance-use-covariant-struct-1.nll.stderr b/src/test/ui/variance/variance-use-covariant-struct-1.nll.stderr
index 19a22f064be..a86c1b93a73 100644
--- a/src/test/ui/variance/variance-use-covariant-struct-1.nll.stderr
+++ b/src/test/ui/variance/variance-use-covariant-struct-1.nll.stderr
@@ -8,6 +8,8 @@ LL | fn foo<'min,'max>(v: SomeStruct<&'min ()>)
 ...
 LL |     v
    |     ^ returning this value requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/variance/variance-use-invariant-struct-1.nll.stderr b/src/test/ui/variance/variance-use-invariant-struct-1.nll.stderr
index 61f80fe77e6..385d83adaf8 100644
--- a/src/test/ui/variance/variance-use-invariant-struct-1.nll.stderr
+++ b/src/test/ui/variance/variance-use-invariant-struct-1.nll.stderr
@@ -8,6 +8,8 @@ LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>)
 ...
 LL |     v
    |     ^ returning this value requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: lifetime may not live long enough
   --> $DIR/variance-use-invariant-struct-1.rs:19:5
@@ -19,6 +21,8 @@ LL | fn bar<'min,'max>(v: SomeStruct<&'min ()>)
 ...
 LL |     v
    |     ^ returning this value requires that `'min` must outlive `'max`
+   |
+   = help: consider adding the following bound: `'min: 'max`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/wf/wf-static-method.nll.stderr b/src/test/ui/wf/wf-static-method.nll.stderr
index 338de6db180..d031a68a51d 100644
--- a/src/test/ui/wf/wf-static-method.nll.stderr
+++ b/src/test/ui/wf/wf-static-method.nll.stderr
@@ -8,6 +8,8 @@ LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () {
 ...
 LL |         u
    |         ^ returning this value requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
   --> $DIR/wf-static-method.rs:26:18
@@ -19,6 +21,8 @@ LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> {
 ...
 LL |         let me = Self::make_me();
    |                  ^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
   --> $DIR/wf-static-method.rs:33:9
@@ -30,6 +34,8 @@ LL | impl<'a, 'b> Evil<'a, 'b> {
 LL |     fn inherent_evil(u: &'b u32) -> &'a u32 {
 LL |         u
    |         ^ returning this value requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
   --> $DIR/wf-static-method.rs:41:5
@@ -40,6 +46,8 @@ LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 {
    |         lifetime `'a` defined here
 LL |     <()>::static_evil(b)
    |     ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
   --> $DIR/wf-static-method.rs:45:5
@@ -50,6 +58,8 @@ LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 {
    |                  lifetime `'a` defined here
 LL |     <IndirectEvil>::static_evil(b)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
   --> $DIR/wf-static-method.rs:50:5
@@ -60,6 +70,8 @@ LL | fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 {
    |                  lifetime `'a` defined here
 LL |     <Evil>::inherent_evil(b) // bug? shouldn't this be an error
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error: aborting due to 6 previous errors