diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index b5ee4a5edce7d..30fe4ea8662eb 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 7721e00c141d7..be9db6aa25b75 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 135714af2a6c1..da4c2b41f09c3 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 79f852d8a95e7..9948d15c43115 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 a5bc7450bbff0..48fb3fb4a2293 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 a94f9a799061a..5a23f1e0e9d99 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 2ed4d6d4401aa..6ba130308a33a 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 1a19e81f235ba..5601335d275c3 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 87b13dc15914b..e221902c4a907 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 825c45b243441..a909c5fa82351 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 f3502674849ef..9661f1e5144b4 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 78a828dde866f..cce0a31bfbbf1 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 , 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 , 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 6989acfa1963b..ec9fac0c288e0 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 b06ebf7047737..057146e7cb0ad 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 1934207527b9c..2e26c703b6573 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>, 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>, 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>, 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>, 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 f1f4d341b2bd8..fd4ecae3cfe32 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>, 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>, 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>, 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>, 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 de7eb02d7a7fe..ede790c061143 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>, 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>, 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>, 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>, 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 f2b7b0ad01957..c0efc35fa6c8e 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>, 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>, 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>, 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>, 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 70453b0ddfc71..226923f59ff37 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>, 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>, 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>, 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>, 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 8e10242cb1331..a4dece320ec26 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