about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs35
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs148
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs2
-rw-r--r--src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr15
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr5
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr10
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr5
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr5
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr5
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr5
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr5
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.nll.stderr5
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr10
-rw-r--r--src/test/ui/self/elision/lt-ref-self.nll.stderr30
-rw-r--r--src/test/ui/self/elision/ref-mut-self.nll.stderr30
-rw-r--r--src/test/ui/self/elision/ref-mut-struct.nll.stderr25
-rw-r--r--src/test/ui/self/elision/ref-self.nll.stderr35
-rw-r--r--src/test/ui/self/elision/ref-struct.nll.stderr25
-rw-r--r--src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.nll.stderr5
20 files changed, 331 insertions, 76 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index b5ee4a5edce..30fe4ea8662 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -2,7 +2,10 @@
 
 use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_infer::infer::{
-    error_reporting::nice_region_error::{self, find_param_with_region, NiceRegionError},
+    error_reporting::nice_region_error::{
+        self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params,
+        NiceRegionError,
+    },
     error_reporting::unexpected_hidden_region_diagnostic,
     NllRegionVariableOrigin, RelateParamBound,
 };
@@ -630,6 +633,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         }
 
         self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr);
+        self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr);
 
         diag
     }
@@ -694,4 +698,33 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             );
         }
     }
+
+    fn suggest_adding_lifetime_params(
+        &self,
+        diag: &mut Diagnostic,
+        sub: RegionVid,
+        sup: RegionVid,
+    ) {
+        let (Some(sub), Some(sup)) = (self.to_error_region(sub), self.to_error_region(sup)) else {
+            return
+        };
+
+        let Some((ty_sub, _)) = self
+            .infcx
+            .tcx
+            .is_suitable_region(sub)
+            .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sub, &anon_reg.boundregion)) else {
+            return
+        };
+
+        let Some((ty_sup, _)) = self
+            .infcx
+            .tcx
+            .is_suitable_region(sup)
+            .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sup, &anon_reg.boundregion)) else {
+            return
+        };
+
+        suggest_adding_lifetime_params(self.infcx.tcx, sub, ty_sup, ty_sub, diag);
+    }
 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
index 7721e00c141..be9db6aa25b 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -6,6 +6,7 @@ use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo;
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::infer::SubregionOrigin;
+use crate::infer::TyCtxt;
 
 use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed};
 use rustc_hir as hir;
@@ -145,84 +146,83 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             }
         }
 
-        self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut err);
+        if suggest_adding_lifetime_params(self.tcx(), sub, ty_sup, ty_sub, &mut err) {
+            err.note("each elided lifetime in input position becomes a distinct lifetime");
+        }
 
         let reported = err.emit();
         Some(reported)
     }
+}
 
-    fn suggest_adding_lifetime_params(
-        &self,
-        sub: Region<'tcx>,
-        ty_sup: &Ty<'_>,
-        ty_sub: &Ty<'_>,
-        err: &mut Diagnostic,
-    ) {
-        if let (
-            hir::Ty { kind: hir::TyKind::Rptr(lifetime_sub, _), .. },
-            hir::Ty { kind: hir::TyKind::Rptr(lifetime_sup, _), .. },
-        ) = (ty_sub, ty_sup)
-        {
-            if lifetime_sub.name.is_elided() && lifetime_sup.name.is_elided() {
-                if let Some(anon_reg) = self.tcx().is_suitable_region(sub) {
-                    let hir_id = self.tcx().hir().local_def_id_to_hir_id(anon_reg.def_id);
-
-                    let node = self.tcx().hir().get(hir_id);
-                    let is_impl = matches!(&node, hir::Node::ImplItem(_));
-                    let generics = match node {
-                        hir::Node::Item(&hir::Item {
-                            kind: hir::ItemKind::Fn(_, ref generics, ..),
-                            ..
-                        })
-                        | hir::Node::TraitItem(&hir::TraitItem { ref generics, .. })
-                        | hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => generics,
-                        _ => return,
-                    };
-
-                    let (suggestion_param_name, introduce_new) = generics
-                        .params
-                        .iter()
-                        .find(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
-                        .and_then(|p| self.tcx().sess.source_map().span_to_snippet(p.span).ok())
-                        .map(|name| (name, false))
-                        .unwrap_or_else(|| ("'a".to_string(), true));
-
-                    let mut suggestions = vec![
-                        if let hir::LifetimeName::Underscore = lifetime_sub.name {
-                            (lifetime_sub.span, suggestion_param_name.clone())
-                        } else {
-                            (lifetime_sub.span.shrink_to_hi(), suggestion_param_name.clone() + " ")
-                        },
-                        if let hir::LifetimeName::Underscore = lifetime_sup.name {
-                            (lifetime_sup.span, suggestion_param_name.clone())
-                        } else {
-                            (lifetime_sup.span.shrink_to_hi(), suggestion_param_name.clone() + " ")
-                        },
-                    ];
-
-                    if introduce_new {
-                        let new_param_suggestion = match &generics.params {
-                            [] => (generics.span, format!("<{}>", suggestion_param_name)),
-                            [first, ..] => {
-                                (first.span.shrink_to_lo(), format!("{}, ", suggestion_param_name))
-                            }
-                        };
-
-                        suggestions.push(new_param_suggestion);
-                    }
-
-                    let mut sugg = String::from("consider introducing a named lifetime parameter");
-                    if is_impl {
-                        sugg.push_str(" and update trait if needed");
-                    }
-                    err.multipart_suggestion(
-                        sugg.as_str(),
-                        suggestions,
-                        Applicability::MaybeIncorrect,
-                    );
-                    err.note("each elided lifetime in input position becomes a distinct lifetime");
-                }
-            }
-        }
+pub fn suggest_adding_lifetime_params<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    sub: Region<'tcx>,
+    ty_sup: &Ty<'_>,
+    ty_sub: &Ty<'_>,
+    err: &mut Diagnostic,
+) -> bool {
+    let (
+        hir::Ty { kind: hir::TyKind::Rptr(lifetime_sub, _), .. },
+        hir::Ty { kind: hir::TyKind::Rptr(lifetime_sup, _), .. },
+    ) = (ty_sub, ty_sup) else {
+        return false;
+    };
+
+    if !lifetime_sub.name.is_elided() || !lifetime_sup.name.is_elided() {
+        return false;
+    };
+
+    let Some(anon_reg) = tcx.is_suitable_region(sub) else {
+        return false;
+    };
+
+    let hir_id = tcx.hir().local_def_id_to_hir_id(anon_reg.def_id);
+
+    let node = tcx.hir().get(hir_id);
+    let is_impl = matches!(&node, hir::Node::ImplItem(_));
+    let generics = match node {
+        hir::Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, ref generics, ..), .. })
+        | hir::Node::TraitItem(&hir::TraitItem { ref generics, .. })
+        | hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => generics,
+        _ => return false,
+    };
+
+    let (suggestion_param_name, introduce_new) = generics
+        .params
+        .iter()
+        .find(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
+        .and_then(|p| tcx.sess.source_map().span_to_snippet(p.span).ok())
+        .map(|name| (name, false))
+        .unwrap_or_else(|| ("'a".to_string(), true));
+
+    let mut suggestions = vec![
+        if let hir::LifetimeName::Underscore = lifetime_sub.name {
+            (lifetime_sub.span, suggestion_param_name.clone())
+        } else {
+            (lifetime_sub.span.shrink_to_hi(), suggestion_param_name.clone() + " ")
+        },
+        if let hir::LifetimeName::Underscore = lifetime_sup.name {
+            (lifetime_sup.span, suggestion_param_name.clone())
+        } else {
+            (lifetime_sup.span.shrink_to_hi(), suggestion_param_name.clone() + " ")
+        },
+    ];
+
+    if introduce_new {
+        let new_param_suggestion = match &generics.params {
+            [] => (generics.span, format!("<{}>", suggestion_param_name)),
+            [first, ..] => (first.span.shrink_to_lo(), format!("{}, ", suggestion_param_name)),
+        };
+
+        suggestions.push(new_param_suggestion);
     }
+
+    let mut sugg = String::from("consider introducing a named lifetime parameter");
+    if is_impl {
+        sugg.push_str(" and update trait if needed");
+    }
+    err.multipart_suggestion(sugg.as_str(), suggestions, Applicability::MaybeIncorrect);
+
+    true
 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
index 135714af2a6..da4c2b41f09 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
@@ -20,7 +20,7 @@ use rustc_middle::ty::{self, Region, TyCtxt};
 /// ```
 /// The function returns the nested type corresponding to the anonymous region
 /// for e.g., `&u8` and `Vec<&u8>`.
-pub(crate) fn find_anon_type<'tcx>(
+pub fn find_anon_type<'tcx>(
     tcx: TyCtxt<'tcx>,
     region: Region<'tcx>,
     br: &ty::BoundRegionKind,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
index 79f852d8a95..9948d15c431 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
@@ -14,6 +14,8 @@ mod static_impl_trait;
 mod trait_impl_difference;
 mod util;
 
+pub use different_lifetimes::suggest_adding_lifetime_params;
+pub use find_anon_type::find_anon_type;
 pub use static_impl_trait::suggest_new_region_bound;
 pub use util::find_param_with_region;
 
diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr b/src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr
index a5bc7450bbf..48fb3fb4a22 100644
--- a/src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr
+++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr
@@ -6,6 +6,11 @@ LL | pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); }
    |                        |        |
    |                        |        let's call the lifetime of this reference `'1`
    |                        let's call the lifetime of this reference `'2`
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+   |           ++++              ++          ++
 
 error: lifetime may not live long enough
   --> $DIR/issue-90170-elision-mismatch.rs:5:44
@@ -15,6 +20,11 @@ LL | pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); }
    |                         |           |
    |                         |           let's call the lifetime of this reference `'1`
    |                         let's call the lifetime of this reference `'2`
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+   |            ++++              ~~          ++
 
 error: lifetime may not live long enough
   --> $DIR/issue-90170-elision-mismatch.rs:7:63
@@ -24,6 +34,11 @@ LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); }
    |                                               |        |
    |                                               |        let's call the lifetime of this reference `'1`
    |                                               let's call the lifetime of this reference `'2`
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+   |                                                ++          ++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr
index a94f9a79906..5a23f1e0e9d 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr
@@ -7,6 +7,11 @@ LL | fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) {
    |                                   let's call the lifetime of this reference `'2`
 LL |     *v = x;
    |     ^^^^^^ assignment requires that `'1` must outlive `'2`
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(&mut (ref mut v, w): &mut (&'a u8, &u8), x: &'a u8) {
+   |       ++++                             ++               ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
index 2ed4d6d4401..6ba130308a3 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
@@ -7,6 +7,11 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
    |                     let's call the lifetime of this reference `'2`
 LL |     z.push((x,y));
    |     ^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(z: &mut Vec<(&'a u8,&u8)>, (x, y): (&'a u8, &u8)) {
+   |       ++++               ++                     ++
 
 error: lifetime may not live long enough
   --> $DIR/ex3-both-anon-regions-3.rs:2:5
@@ -17,6 +22,11 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
    |                         let's call the lifetime of this reference `'4`
 LL |     z.push((x,y));
    |     ^^^^^^^^^^^^^ argument requires that `'3` must outlive `'4`
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(z: &mut Vec<(&u8,&'a u8)>, (x, y): (&u8, &'a u8)) {
+   |       ++++                   ++                      ++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr
index 1a19e81f235..5601335d275 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr
@@ -7,6 +7,11 @@ LL |   fn foo<'a>(&self, x: &i32) -> &i32 {
    |              let's call the lifetime of this reference `'2`
 LL |     x
    |     ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |   fn foo<'a>(&'a self, x: &'a i32) -> &i32 {
+   |               ++           ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr
index 87b13dc1591..e221902c4a9 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr
@@ -7,6 +7,11 @@ LL |     fn foo<'a>(&self, x: &Foo) -> &Foo {
    |                let's call the lifetime of this reference `'2`
 LL |         if true { x } else { self }
    |                   ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn foo<'a>(&'a self, x: &'a Foo) -> &Foo {
+   |                 ++           ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr
index 825c45b2434..a909c5fa823 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr
@@ -7,6 +7,11 @@ LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) {
    |                               let's call the lifetime of this reference `'2`
 LL |   y.push(z);
    |   ^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(x:fn(&u8, &u8), y: Vec<&'a u8>, z: &'a u8) {
+   |       ++++                         ++          ++
 
 error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
   --> $DIR/ex3-both-anon-regions-using-fn-items.rs:2:3
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr
index f3502674849..9661f1e5144 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr
@@ -7,6 +7,11 @@ LL |     fn foo(x: &mut Vec<&u8>, y: &u8) {
    |                        let's call the lifetime of this reference `'2`
 LL |         x.push(y);
    |         ^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) {
+   |           ++++              ++          ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr
index 78a828dde86..cce0a31bfbb 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr
@@ -7,6 +7,11 @@ LL | fn foo(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
    |                                         let's call the lifetime of this reference `'2`
 LL |   y.push(z);
    |   ^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(x:Box<dyn Fn(&'a u8, &'a u8)> , y: Vec<&u8>, z: &u8) {
+   |       ++++               ++      ++
 
 error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
   --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:2:3
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.nll.stderr
index 6989acfa196..ec9fac0c288 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.nll.stderr
@@ -7,6 +7,11 @@ LL | fn foo(x: &mut Vec<&u8>, y: &u8) {
    |                    let's call the lifetime of this reference `'2`
 LL |     x.push(y);
    |     ^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) {
+   |       ++++              ++          ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr
index b06ebf70477..057146e7cb0 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr
@@ -6,6 +6,11 @@ LL |     fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
    |                    |         |
    |                    |         let's call the lifetime of this reference `'1`
    |                    let's call the lifetime of this reference `'2`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn a<'a>(self: Pin<&'a Foo>, f: &'a Foo) -> &Foo { f }
+   |         ++++            ++           ++
 
 error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:14:69
@@ -15,6 +20,11 @@ LL |     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self,
    |                    |          |
    |                    |          let's call the lifetime of this reference `'1`
    |                    let's call the lifetime of this reference `'2`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn c<'a>(self: Pin<&'a Self>, f: &'a Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+   |         ++++            ++            ++
 
 error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:21:58
diff --git a/src/test/ui/self/elision/lt-ref-self.nll.stderr b/src/test/ui/self/elision/lt-ref-self.nll.stderr
index 1934207527b..2e26c703b65 100644
--- a/src/test/ui/self/elision/lt-ref-self.nll.stderr
+++ b/src/test/ui/self/elision/lt-ref-self.nll.stderr
@@ -7,6 +7,11 @@ LL |     fn ref_self(&self, f: &u32) -> &u32 {
    |                 let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
+   |                ++++  ++           ++
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self.rs:23:9
@@ -17,6 +22,11 @@ LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                       let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
+   |                ++++        ++           ++
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self.rs:29:9
@@ -27,6 +37,11 @@ LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                               let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++            ++
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self.rs:35:9
@@ -37,6 +52,11 @@ LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                               let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++            ++
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self.rs:41:9
@@ -47,6 +67,11 @@ LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
+   |                        ++++                ++             ++
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self.rs:47:9
@@ -57,6 +82,11 @@ LL |     fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                   let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
+   |                    ++++                ++             ++
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/self/elision/ref-mut-self.nll.stderr b/src/test/ui/self/elision/ref-mut-self.nll.stderr
index f1f4d341b2b..fd4ecae3cfe 100644
--- a/src/test/ui/self/elision/ref-mut-self.nll.stderr
+++ b/src/test/ui/self/elision/ref-mut-self.nll.stderr
@@ -7,6 +7,11 @@ LL |     fn ref_self(&mut self, f: &u32) -> &u32 {
    |                 let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_self<'a>(&'a mut self, f: &'a u32) -> &u32 {
+   |                ++++  ++               ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self.rs:23:9
@@ -17,6 +22,11 @@ LL |     fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
    |                       let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &u32 {
+   |                ++++        ++               ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self.rs:29:9
@@ -27,6 +37,11 @@ LL |     fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
    |                               let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++                ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self.rs:35:9
@@ -37,6 +52,11 @@ LL |     fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
    |                               let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++                ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self.rs:41:9
@@ -47,6 +67,11 @@ LL |     fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_Self<'a>(self: Box<Box<&'a mut Self>>, f: &'a u32) -> &u32 {
+   |                        ++++                ++                 ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self.rs:47:9
@@ -57,6 +82,11 @@ LL |     fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_ref_Self<'a>(self: Box<Pin<&'a mut Self>>, f: &'a u32) -> &u32 {
+   |                        ++++                ++                 ++
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/self/elision/ref-mut-struct.nll.stderr b/src/test/ui/self/elision/ref-mut-struct.nll.stderr
index de7eb02d7a7..ede790c0611 100644
--- a/src/test/ui/self/elision/ref-mut-struct.nll.stderr
+++ b/src/test/ui/self/elision/ref-mut-struct.nll.stderr
@@ -7,6 +7,11 @@ LL |     fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
    |                         let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_Struct<'a>(self: &'a mut Struct, f: &'a u32) -> &u32 {
+   |                  ++++        ++                 ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct.rs:21:9
@@ -17,6 +22,11 @@ LL |     fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
    |                                 let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_Struct<'a>(self: Box<&'a mut Struct>, f: &'a u32) -> &u32 {
+   |                      ++++            ++                  ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct.rs:27:9
@@ -27,6 +37,11 @@ LL |     fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
    |                                 let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_Struct<'a>(self: Pin<&'a mut Struct>, f: &'a u32) -> &u32 {
+   |                      ++++            ++                  ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct.rs:33:9
@@ -37,6 +52,11 @@ LL |     fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
    |                                         let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_Struct<'a>(self: Box<Box<&'a mut Struct>>, f: &'a u32) -> &u32 {
+   |                          ++++                ++                   ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct.rs:39:9
@@ -47,6 +67,11 @@ LL |     fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
    |                                         let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_ref_Struct<'a>(self: Box<Pin<&'a mut Struct>>, f: &'a u32) -> &u32 {
+   |                          ++++                ++                   ++
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/self/elision/ref-self.nll.stderr b/src/test/ui/self/elision/ref-self.nll.stderr
index f2b7b0ad019..c0efc35fa6c 100644
--- a/src/test/ui/self/elision/ref-self.nll.stderr
+++ b/src/test/ui/self/elision/ref-self.nll.stderr
@@ -7,6 +7,11 @@ LL |     fn ref_self(&self, f: &u32) -> &u32 {
    |                 let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
+   |                ++++  ++           ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:33:9
@@ -17,6 +22,11 @@ LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                       let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
+   |                ++++        ++           ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:39:9
@@ -27,6 +37,11 @@ LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                               let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++            ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:45:9
@@ -37,6 +52,11 @@ LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                               let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++            ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:51:9
@@ -47,6 +67,11 @@ LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
+   |                        ++++                ++             ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:57:9
@@ -57,6 +82,11 @@ LL |     fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_ref_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
+   |                        ++++                ++             ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:63:9
@@ -67,6 +97,11 @@ LL |     fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
    |                                      let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn wrap_ref_Self_Self<'a>(self: Wrap<&'a Self, Self>, f: &'a u8) -> &u8 {
+   |                          ++++             ++                  ++
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/self/elision/ref-struct.nll.stderr b/src/test/ui/self/elision/ref-struct.nll.stderr
index 70453b0ddfc..226923f59ff 100644
--- a/src/test/ui/self/elision/ref-struct.nll.stderr
+++ b/src/test/ui/self/elision/ref-struct.nll.stderr
@@ -7,6 +7,11 @@ LL |     fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |                         let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_Struct<'a>(self: &'a Struct, f: &'a u32) -> &u32 {
+   |                  ++++        ++             ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct.rs:21:9
@@ -17,6 +22,11 @@ LL |     fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
    |                                 let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_Struct<'a>(self: Box<&'a Struct>, f: &'a u32) -> &u32 {
+   |                      ++++            ++              ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct.rs:27:9
@@ -27,6 +37,11 @@ LL |     fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
    |                                 let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_Struct<'a>(self: Pin<&'a Struct>, f: &'a u32) -> &u32 {
+   |                      ++++            ++              ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct.rs:33:9
@@ -37,6 +52,11 @@ LL |     fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
    |                                         let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_Struct<'a>(self: Box<Box<&'a Struct>>, f: &'a u32) -> &u32 {
+   |                          ++++                ++               ++
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct.rs:39:9
@@ -47,6 +67,11 @@ LL |     fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
    |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_Struct<'a>(self: Box<Pin<&'a Struct>>, f: &'a u32) -> &u32 {
+   |                      ++++                ++               ++
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.nll.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.nll.stderr
index 8e10242cb13..a4dece320ec 100644
--- a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.nll.stderr
+++ b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.nll.stderr
@@ -6,6 +6,11 @@ LL | fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); }
    |                    |           |
    |                    |           let's call the lifetime of this reference `'1`
    |                    let's call the lifetime of this reference `'2`
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+   |       ++++              ~~          ~~
 
 error: aborting due to previous error