diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index df30c185c60..61c7846ea61 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -8,7 +8,7 @@ use crate::{PathResult, PathSource, Segment}; use rustc_hir::def::Namespace::{self, *}; use rustc_ast::ptr::P; -use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt}; +use rustc_ast::visit::{walk_ty, FnCtxt, FnKind, LifetimeCtxt, Visitor}; use rustc_ast::{ self as ast, AssocItemKind, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind, MethodCall, NodeId, Path, Ty, TyKind, DUMMY_NODE_ID, @@ -2830,6 +2830,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { .collect(); debug!(?in_scope_lifetimes); + let mut maybe_static = false; debug!(?function_param_lifetimes); if let Some((param_lifetimes, params)) = &function_param_lifetimes { let elided_len = param_lifetimes.len(); @@ -2868,10 +2869,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { if num_params == 0 { err.help( - "this function's return type contains a borrowed value, \ - but there is no value for it to be borrowed from", + "this function's return type contains a borrowed value, but there is no value \ + for it to be borrowed from", ); if in_scope_lifetimes.is_empty() { + maybe_static = true; in_scope_lifetimes = vec![( Ident::with_dummy_span(kw::StaticLifetime), (DUMMY_NODE_ID, LifetimeRes::Static), @@ -2879,11 +2881,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } } else if elided_len == 0 { err.help( - "this function's return type contains a borrowed value with \ - an elided lifetime, but the lifetime cannot be derived from \ - the arguments", + "this function's return type contains a borrowed value with an elided \ + lifetime, but the lifetime cannot be derived from the arguments", ); if in_scope_lifetimes.is_empty() { + maybe_static = true; in_scope_lifetimes = vec![( Ident::with_dummy_span(kw::StaticLifetime), (DUMMY_NODE_ID, LifetimeRes::Static), @@ -2891,13 +2893,13 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } } else if num_params == 1 { err.help(format!( - "this function's return type contains a borrowed value, \ - but the signature does not say which {m} it is borrowed from" + "this function's return type contains a borrowed value, but the signature does \ + not say which {m} it is borrowed from", )); } else { err.help(format!( - "this function's return type contains a borrowed value, \ - but the signature does not say whether it is borrowed from {m}" + "this function's return type contains a borrowed value, but the signature does \ + not say whether it is borrowed from {m}", )); } } @@ -2962,11 +2964,238 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { ); } 1 => { + let post = if maybe_static { + let owned = if let [lt] = &lifetime_refs[..] + && lt.kind != MissingLifetimeKind::Ampersand + { + ", or if you will only have owned values" + } else { + "" + }; + format!( + ", but this is uncommon unless you're returning a borrowed value from a \ + `const` or a `static`{owned}", + ) + } else { + String::new() + }; err.multipart_suggestion_verbose( - format!("consider using the `{existing_name}` lifetime"), + format!("consider using the `{existing_name}` lifetime{post}"), spans_suggs, Applicability::MaybeIncorrect, ); + if maybe_static { + // FIXME: what follows are general suggestions, but we'd want to perform some + // minimal flow analysis to provide more accurate suggestions. For example, if + // we identified that the return expression references only one argument, we + // would suggest borrowing only that argument, and we'd skip the prior + // "use `'static`" suggestion entirely. + if let [lt] = &lifetime_refs[..] + && (lt.kind == MissingLifetimeKind::Ampersand + || lt.kind == MissingLifetimeKind::Underscore) + { + let pre = if lt.kind == MissingLifetimeKind::Ampersand + && let Some((kind, _span)) = self.diagnostic_metadata.current_function + && let FnKind::Fn(_, _, sig, _, _, _) = kind + && !sig.decl.inputs.is_empty() + && let sugg = sig + .decl + .inputs + .iter() + .filter_map(|param| { + if param.ty.span.contains(lt.span) { + // We don't want to suggest `fn elision(_: &fn() -> &i32)` + // when we have `fn elision(_: fn() -> &i32)` + None + } else if let TyKind::CVarArgs = param.ty.kind { + // Don't suggest `&...` for ffi fn with varargs + None + } else if let TyKind::ImplTrait(..) = ¶m.ty.kind { + // We handle these in the next `else if` branch. + None + } else { + Some((param.ty.span.shrink_to_lo(), "&".to_string())) + } + }) + .collect::>() + && !sugg.is_empty() + { + let (the, s) = if sig.decl.inputs.len() == 1 { + ("the", "") + } else { + ("one of the", "s") + }; + err.multipart_suggestion_verbose( + format!( + "instead, you are more likely to want to change {the} \ + argument{s} to be borrowed...", + ), + sugg, + Applicability::MaybeIncorrect, + ); + "...or alternatively, you might want" + } else if (lt.kind == MissingLifetimeKind::Ampersand + || lt.kind == MissingLifetimeKind::Underscore) + && let Some((kind, _span)) = self.diagnostic_metadata.current_function + && let FnKind::Fn(_, _, sig, _, _, _) = kind + && let ast::FnRetTy::Ty(ret_ty) = &sig.decl.output + && !sig.decl.inputs.is_empty() + && let arg_refs = sig + .decl + .inputs + .iter() + .filter_map(|param| match ¶m.ty.kind { + TyKind::ImplTrait(_, bounds) => Some(bounds), + _ => None, + }) + .flat_map(|bounds| bounds.into_iter()) + .collect::>() + && !arg_refs.is_empty() + { + // We have a situation like + // fn g(mut x: impl Iterator) -> Option<&()> + // So we look at every ref in the trait bound. If there's any, we + // suggest + // fn g<'a>(mut x: impl Iterator) -> Option<&'a ()> + let mut lt_finder = + LifetimeFinder { lifetime: lt.span, found: None, seen: vec![] }; + for bound in arg_refs { + if let ast::GenericBound::Trait(trait_ref, _) = bound { + lt_finder.visit_trait_ref(&trait_ref.trait_ref); + } + } + lt_finder.visit_ty(ret_ty); + let spans_suggs: Vec<_> = lt_finder + .seen + .iter() + .filter_map(|ty| match &ty.kind { + TyKind::Ref(_, mut_ty) => { + let span = ty.span.with_hi(mut_ty.ty.span.lo()); + Some((span, "&'a ".to_string())) + } + _ => None, + }) + .collect(); + self.suggest_introducing_lifetime( + err, + None, + |err, higher_ranked, span, message, intro_sugg| { + err.multipart_suggestion_verbose( + message, + std::iter::once((span, intro_sugg)) + .chain(spans_suggs.iter().cloned()) + .collect(), + Applicability::MaybeIncorrect, + ); + higher_ranked + }, + ); + "alternatively, you might want" + } else { + "instead, you are more likely to want" + }; + let mut owned_sugg = lt.kind == MissingLifetimeKind::Ampersand; + let mut sugg = vec![(lt.span, String::new())]; + if let Some((kind, _span)) = self.diagnostic_metadata.current_function + && let FnKind::Fn(_, _, sig, _, _, _) = kind + && let ast::FnRetTy::Ty(ty) = &sig.decl.output + { + let mut lt_finder = + LifetimeFinder { lifetime: lt.span, found: None, seen: vec![] }; + lt_finder.visit_ty(&ty); + + if let [Ty { span, kind: TyKind::Ref(_, mut_ty), .. }] = + <_finder.seen[..] + { + // We might have a situation like + // fn g(mut x: impl Iterator) -> Option<&'_ ()> + // but `lt.span` only points at `'_`, so to suggest `-> Option<()>` + // we need to find a more accurate span to end up with + // fn g<'a>(mut x: impl Iterator) -> Option<()> + sugg = vec![(span.with_hi(mut_ty.ty.span.lo()), String::new())]; + owned_sugg = true; + } + if let Some(ty) = lt_finder.found { + if let TyKind::Path(None, path) = &ty.kind { + // Check if the path being borrowed is likely to be owned. + let path: Vec<_> = Segment::from_path(path); + match self.resolve_path(&path, Some(TypeNS), None) { + PathResult::Module(ModuleOrUniformRoot::Module(module)) => { + match module.res() { + Some(Res::PrimTy(PrimTy::Str)) => { + // Don't suggest `-> str`, suggest `-> String`. + sugg = vec![( + lt.span.with_hi(ty.span.hi()), + "String".to_string(), + )]; + } + Some(Res::PrimTy(..)) => {} + Some(Res::Def( + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::ForeignTy + | DefKind::AssocTy + | DefKind::OpaqueTy + | DefKind::TyParam, + _, + )) => {} + _ => { + // Do not suggest in all other cases. + owned_sugg = false; + } + } + } + PathResult::NonModule(res) => { + match res.base_res() { + Res::PrimTy(PrimTy::Str) => { + // Don't suggest `-> str`, suggest `-> String`. + sugg = vec![( + lt.span.with_hi(ty.span.hi()), + "String".to_string(), + )]; + } + Res::PrimTy(..) => {} + Res::Def( + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::ForeignTy + | DefKind::AssocTy + | DefKind::OpaqueTy + | DefKind::TyParam, + _, + ) => {} + _ => { + // Do not suggest in all other cases. + owned_sugg = false; + } + } + } + _ => { + // Do not suggest in all other cases. + owned_sugg = false; + } + } + } + if let TyKind::Slice(inner_ty) = &ty.kind { + // Don't suggest `-> [T]`, suggest `-> Vec`. + sugg = vec![ + (lt.span.with_hi(inner_ty.span.lo()), "Vec<".to_string()), + (ty.span.with_lo(inner_ty.span.hi()), ">".to_string()), + ]; + } + } + } + if owned_sugg { + err.multipart_suggestion_verbose( + format!("{pre} to return an owned value"), + sugg, + Applicability::MaybeIncorrect, + ); + } + } + } // Record as using the suggested resolution. let (_, (_, res)) = in_scope_lifetimes[0]; @@ -2996,7 +3225,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { fn mk_where_bound_predicate( path: &Path, poly_trait_ref: &ast::PolyTraitRef, - ty: &ast::Ty, + ty: &Ty, ) -> Option { use rustc_span::DUMMY_SP; let modified_segments = { @@ -3073,6 +3302,24 @@ pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: I err.emit(); } +struct LifetimeFinder<'ast> { + lifetime: Span, + found: Option<&'ast Ty>, + seen: Vec<&'ast Ty>, +} + +impl<'ast> Visitor<'ast> for LifetimeFinder<'ast> { + fn visit_ty(&mut self, t: &'ast Ty) { + if let TyKind::Ref(_, mut_ty) = &t.kind { + self.seen.push(t); + if t.span.lo() == self.lifetime.lo() { + self.found = Some(&mut_ty.ty); + } + } + walk_ty(self, t) + } +} + /// Shadowing involving a label is only a warning for historical reasons. //FIXME: make this a proper lint. pub(super) fn signal_label_shadowing(sess: &Session, orig: Span, shadower: Ident) { diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index dfa386b49de..40149f8f1c3 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -11,7 +11,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. const ISSUES_ENTRY_LIMIT: usize = 1852; -const ROOT_ENTRY_LIMIT: usize = 867; +const ROOT_ENTRY_LIMIT: usize = 866; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr b/tests/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr index 8ccfb212216..24fd38f31ad 100644 --- a/tests/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr +++ b/tests/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr @@ -5,10 +5,15 @@ LL | fn elision &i32>() { | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | fn elision &'static i32>() { | +++++++ +help: instead, you are more likely to want to return an owned value + | +LL - fn elision &i32>() { +LL + fn elision i32>() { + | error: aborting due to 1 previous error diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.elision.stderr b/tests/ui/associated-types/bound-lifetime-in-return-only.elision.stderr index 0593a62a750..d24378487e7 100644 --- a/tests/ui/associated-types/bound-lifetime-in-return-only.elision.stderr +++ b/tests/ui/associated-types/bound-lifetime-in-return-only.elision.stderr @@ -5,10 +5,15 @@ LL | fn elision(_: fn() -> &i32) { | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | fn elision(_: fn() -> &'static i32) { | +++++++ +help: instead, you are more likely to want to return an owned value + | +LL - fn elision(_: fn() -> &i32) { +LL + fn elision(_: fn() -> i32) { + | error: aborting due to 1 previous error diff --git a/tests/ui/c-variadic/variadic-ffi-6.stderr b/tests/ui/c-variadic/variadic-ffi-6.stderr index 1ceff570478..344bfed4b42 100644 --- a/tests/ui/c-variadic/variadic-ffi-6.stderr +++ b/tests/ui/c-variadic/variadic-ffi-6.stderr @@ -5,10 +5,19 @@ LL | ) -> &usize { | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | ) -> &'static usize { | +++++++ +help: instead, you are more likely to want to change one of the arguments to be borrowed... + | +LL | x: &usize, + | + +help: ...or alternatively, you might want to return an owned value + | +LL - ) -> &usize { +LL + ) -> usize { + | error: aborting due to 1 previous error diff --git a/tests/ui/foreign-fn-return-lifetime.fixed b/tests/ui/foreign-fn-return-lifetime.fixed deleted file mode 100644 index 143d6343d26..00000000000 --- a/tests/ui/foreign-fn-return-lifetime.fixed +++ /dev/null @@ -1,8 +0,0 @@ -// run-rustfix - -extern "C" { - pub fn g(_: &u8) -> &u8; // OK - pub fn f() -> &'static u8; //~ ERROR missing lifetime specifier -} - -fn main() {} diff --git a/tests/ui/foreign-fn-return-lifetime.rs b/tests/ui/foreign-fn-return-lifetime.rs index 76fe50a340a..35595bab36d 100644 --- a/tests/ui/foreign-fn-return-lifetime.rs +++ b/tests/ui/foreign-fn-return-lifetime.rs @@ -1,5 +1,3 @@ -// run-rustfix - extern "C" { pub fn g(_: &u8) -> &u8; // OK pub fn f() -> &u8; //~ ERROR missing lifetime specifier diff --git a/tests/ui/foreign-fn-return-lifetime.stderr b/tests/ui/foreign-fn-return-lifetime.stderr index 43edcbde35c..e24c0f23c35 100644 --- a/tests/ui/foreign-fn-return-lifetime.stderr +++ b/tests/ui/foreign-fn-return-lifetime.stderr @@ -1,14 +1,19 @@ error[E0106]: missing lifetime specifier - --> $DIR/foreign-fn-return-lifetime.rs:5:19 + --> $DIR/foreign-fn-return-lifetime.rs:3:19 | LL | pub fn f() -> &u8; | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | pub fn f() -> &'static u8; | +++++++ +help: instead, you are more likely to want to return an owned value + | +LL - pub fn f() -> &u8; +LL + pub fn f() -> u8; + | error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/issue-70304.stderr b/tests/ui/generic-associated-types/issue-70304.stderr index 99339e96859..9b02c1b0768 100644 --- a/tests/ui/generic-associated-types/issue-70304.stderr +++ b/tests/ui/generic-associated-types/issue-70304.stderr @@ -11,7 +11,7 @@ LL | fn create_doc() -> impl Document = DocCursorImpl<'_>> { | ^^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values | LL | fn create_doc() -> impl Document = DocCursorImpl<'static>> { | ~~~~~~~ diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr index 443ffeb55cd..a5982a5542a 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -5,7 +5,7 @@ LL | fn d() -> impl Fn() -> (impl Debug + '_) { | ^^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values | LL | fn d() -> impl Fn() -> (impl Debug + 'static) { | ~~~~~~~ diff --git a/tests/ui/issues/issue-13497.stderr b/tests/ui/issues/issue-13497.stderr index 236e6b48607..fb3de637a79 100644 --- a/tests/ui/issues/issue-13497.stderr +++ b/tests/ui/issues/issue-13497.stderr @@ -5,10 +5,14 @@ LL | &str | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | &'static str | +++++++ +help: instead, you are more likely to want to return an owned value + | +LL | String + | ~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/issue-26638.stderr b/tests/ui/lifetimes/issue-26638.stderr index e61158a5d4d..ee958686259 100644 --- a/tests/ui/lifetimes/issue-26638.stderr +++ b/tests/ui/lifetimes/issue-26638.stderr @@ -17,10 +17,18 @@ LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() } | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &'static str { iter() } | +++++++ +help: instead, you are more likely to want to change the argument to be borrowed... + | +LL | fn parse_type_2(iter: &fn(&u8)->&u8) -> &str { iter() } + | + +help: ...or alternatively, you might want to return an owned value + | +LL | fn parse_type_2(iter: fn(&u8)->&u8) -> String { iter() } + | ~~~~~~ error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:10:22 @@ -29,10 +37,14 @@ LL | fn parse_type_3() -> &str { unimplemented!() } | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | fn parse_type_3() -> &'static str { unimplemented!() } | +++++++ +help: instead, you are more likely to want to return an owned value + | +LL | fn parse_type_3() -> String { unimplemented!() } + | ~~~~~~ error[E0308]: mismatched types --> $DIR/issue-26638.rs:1:69 diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index 5eee953ef18..23ef36888f0 100644 --- a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -5,10 +5,15 @@ LL | fn f() -> &isize { | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | fn f() -> &'static isize { | +++++++ +help: instead, you are more likely to want to return an owned value + | +LL - fn f() -> &isize { +LL + fn f() -> isize { + | error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:7:33 @@ -41,10 +46,19 @@ LL | fn i(_x: isize) -> &isize { | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | fn i(_x: isize) -> &'static isize { | +++++++ +help: instead, you are more likely to want to change the argument to be borrowed... + | +LL | fn i(_x: &isize) -> &isize { + | + +help: ...or alternatively, you might want to return an owned value + | +LL - fn i(_x: isize) -> &isize { +LL + fn i(_x: isize) -> isize { + | error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:34:24 @@ -53,10 +67,19 @@ LL | fn j(_x: StaticStr) -> &isize { | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | fn j(_x: StaticStr) -> &'static isize { | +++++++ +help: instead, you are more likely to want to change the argument to be borrowed... + | +LL | fn j(_x: &StaticStr) -> &isize { + | + +help: ...or alternatively, you might want to return an owned value + | +LL - fn j(_x: StaticStr) -> &isize { +LL + fn j(_x: StaticStr) -> isize { + | error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:40:49 diff --git a/tests/ui/self/elision/nested-item.stderr b/tests/ui/self/elision/nested-item.stderr index 752fd82332c..7bad26fa133 100644 --- a/tests/ui/self/elision/nested-item.stderr +++ b/tests/ui/self/elision/nested-item.stderr @@ -21,10 +21,19 @@ LL | fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &() { | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &'static () { | +++++++ +help: instead, you are more likely to want to change the argument to be borrowed... + | +LL | fn wrap(self: &Wrap<{ fn bar(&self) {} }>) -> &() { + | + +help: ...or alternatively, you might want to return an owned value + | +LL - fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &() { +LL + fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> () { + | error[E0412]: cannot find type `Wrap` in this scope --> $DIR/nested-item.rs:5:15 diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr index 50806a67255..2dfaa731194 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -5,10 +5,19 @@ LL | fn g(mut x: impl Iterator) -> Option<&()> { x.next() } | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | fn g(mut x: impl Iterator) -> Option<&'static ()> { x.next() } | +++++++ +help: consider introducing a named lifetime parameter + | +LL | fn g<'a>(mut x: impl Iterator) -> Option<&'a ()> { x.next() } + | ++++ ~~~ ~~~ +help: alternatively, you might want to return an owned value + | +LL - fn g(mut x: impl Iterator) -> Option<&()> { x.next() } +LL + fn g(mut x: impl Iterator) -> Option<()> { x.next() } + | error[E0106]: missing lifetime specifier --> $DIR/impl-trait-missing-lifetime-gated.rs:19:60 @@ -17,10 +26,19 @@ LL | async fn i(mut x: impl Iterator) -> Option<&()> { x.next() | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | async fn i(mut x: impl Iterator) -> Option<&'static ()> { x.next() } | +++++++ +help: consider introducing a named lifetime parameter + | +LL | async fn i<'a>(mut x: impl Iterator) -> Option<&'a ()> { x.next() } + | ++++ ~~~ ~~~ +help: alternatively, you might want to return an owned value + | +LL - async fn i(mut x: impl Iterator) -> Option<&()> { x.next() } +LL + async fn i(mut x: impl Iterator) -> Option<()> { x.next() } + | error[E0106]: missing lifetime specifier --> $DIR/impl-trait-missing-lifetime-gated.rs:27:58 @@ -29,10 +47,19 @@ LL | fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() | ^^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values | LL | fn g(mut x: impl Iterator) -> Option<&'static ()> { x.next() } | ~~~~~~~ +help: consider introducing a named lifetime parameter + | +LL | fn g<'a>(mut x: impl Iterator) -> Option<&'a ()> { x.next() } + | ++++ ~~~ ~~~ +help: alternatively, you might want to return an owned value + | +LL - fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } +LL + fn g(mut x: impl Iterator) -> Option<()> { x.next() } + | error[E0106]: missing lifetime specifier --> $DIR/impl-trait-missing-lifetime-gated.rs:37:64 @@ -41,10 +68,19 @@ LL | async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.n | ^^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values | LL | async fn i(mut x: impl Iterator) -> Option<&'static ()> { x.next() } | ~~~~~~~ +help: consider introducing a named lifetime parameter + | +LL | async fn i<'a>(mut x: impl Iterator) -> Option<&'a ()> { x.next() } + | ++++ ~~~ ~~~ +help: alternatively, you might want to return an owned value + | +LL - async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } +LL + async fn i(mut x: impl Iterator) -> Option<()> { x.next() } + | error[E0106]: missing lifetime specifier --> $DIR/impl-trait-missing-lifetime-gated.rs:47:37 @@ -53,10 +89,19 @@ LL | fn g(mut x: impl Foo) -> Option<&()> { x.next() } | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | fn g(mut x: impl Foo) -> Option<&'static ()> { x.next() } | +++++++ +help: consider introducing a named lifetime parameter + | +LL | fn g<'a>(mut x: impl Foo) -> Option<&'a ()> { x.next() } + | ++++ ~~~ +help: alternatively, you might want to return an owned value + | +LL - fn g(mut x: impl Foo) -> Option<&()> { x.next() } +LL + fn g(mut x: impl Foo) -> Option<()> { x.next() } + | error[E0106]: missing lifetime specifier --> $DIR/impl-trait-missing-lifetime-gated.rs:58:41 @@ -65,10 +110,19 @@ LL | fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() } | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | fn g(mut x: impl Foo<()>) -> Option<&'static ()> { x.next() } | +++++++ +help: consider introducing a named lifetime parameter + | +LL | fn g<'a>(mut x: impl Foo<()>) -> Option<&'a ()> { x.next() } + | ++++ ~~~ +help: alternatively, you might want to return an owned value + | +LL - fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() } +LL + fn g(mut x: impl Foo<()>) -> Option<()> { x.next() } + | error[E0658]: anonymous lifetimes in `impl Trait` are unstable --> $DIR/impl-trait-missing-lifetime-gated.rs:6:35 diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr index 2c29cfa0b91..c1dbaae0649 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr @@ -5,10 +5,19 @@ LL | fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } | ^^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values | LL | fn g(mut x: impl Iterator) -> Option<&'static ()> { x.next() } | ~~~~~~~ +help: consider introducing a named lifetime parameter + | +LL | fn g<'a>(mut x: impl Iterator) -> Option<&'a ()> { x.next() } + | ++++ ~~~ ~~~ +help: alternatively, you might want to return an owned value + | +LL - fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } +LL + fn g(mut x: impl Iterator) -> Option<()> { x.next() } + | error[E0106]: missing lifetime specifier --> $DIR/impl-trait-missing-lifetime.rs:16:60 @@ -17,10 +26,19 @@ LL | async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next( | ^^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values | LL | async fn i(mut x: impl Iterator) -> Option<&'static ()> { x.next() } | ~~~~~~~ +help: consider introducing a named lifetime parameter + | +LL | async fn i<'a>(mut x: impl Iterator) -> Option<&'a ()> { x.next() } + | ++++ ~~~ ~~~ +help: alternatively, you might want to return an owned value + | +LL - async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } +LL + async fn i(mut x: impl Iterator) -> Option<()> { x.next() } + | error: lifetime may not live long enough --> $DIR/impl-trait-missing-lifetime.rs:16:69 diff --git a/tests/ui/suggestions/missing-lifetime-specifier.stderr b/tests/ui/suggestions/missing-lifetime-specifier.stderr index fa4bc2fa79d..e41f547ce9b 100644 --- a/tests/ui/suggestions/missing-lifetime-specifier.stderr +++ b/tests/ui/suggestions/missing-lifetime-specifier.stderr @@ -5,7 +5,7 @@ LL | static a: RefCell>>> = RefCell::new(HashMap:: | ^^^ expected 2 lifetime parameters | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values | LL | static a: RefCell>>>> = RefCell::new(HashMap::new()); | ++++++++++++++++++ @@ -32,7 +32,7 @@ LL | static b: RefCell>>> = RefCell::new(HashMap: | expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | static b: RefCell>>>> = RefCell::new(HashMap::new()); | +++++++ ++++++++++++++++++ @@ -59,7 +59,7 @@ LL | static c: RefCell>>>> = RefCell::new(Hash | ^ expected 2 lifetime parameters | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values | LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); | +++++++++++++++++ @@ -86,7 +86,7 @@ LL | static d: RefCell>>>> = RefCell::new(Has | expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); | +++++++ +++++++++++++++++ @@ -113,7 +113,7 @@ LL | static f: RefCell>>>> = RefCell | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | +++++++ diff --git a/tests/ui/suggestions/return-elided-lifetime.stderr b/tests/ui/suggestions/return-elided-lifetime.stderr index 273d95bc747..7bfffd30184 100644 --- a/tests/ui/suggestions/return-elided-lifetime.stderr +++ b/tests/ui/suggestions/return-elided-lifetime.stderr @@ -5,10 +5,15 @@ LL | fn f1() -> &i32 { loop {} } | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | fn f1() -> &'static i32 { loop {} } | +++++++ +help: instead, you are more likely to want to return an owned value + | +LL - fn f1() -> &i32 { loop {} } +LL + fn f1() -> i32 { loop {} } + | error[E0106]: missing lifetime specifiers --> $DIR/return-elided-lifetime.rs:8:14 @@ -19,7 +24,7 @@ LL | fn f1_() -> (&i32, &i32) { loop {} } | expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | fn f1_() -> (&'static i32, &'static i32) { loop {} } | +++++++ +++++++ @@ -31,10 +36,19 @@ LL | fn f2(a: i32, b: i32) -> &i32 { loop {} } | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | fn f2(a: i32, b: i32) -> &'static i32 { loop {} } | +++++++ +help: instead, you are more likely to want to change one of the arguments to be borrowed... + | +LL | fn f2(a: &i32, b: &i32) -> &i32 { loop {} } + | + + +help: ...or alternatively, you might want to return an owned value + | +LL - fn f2(a: i32, b: i32) -> &i32 { loop {} } +LL + fn f2(a: i32, b: i32) -> i32 { loop {} } + | error[E0106]: missing lifetime specifiers --> $DIR/return-elided-lifetime.rs:13:28 @@ -45,7 +59,7 @@ LL | fn f2_(a: i32, b: i32) -> (&i32, &i32) { loop {} } | expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` | LL | fn f2_(a: i32, b: i32) -> (&'static i32, &'static i32) { loop {} } | +++++++ +++++++ diff --git a/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr index 50401791eff..cd74d27dcb5 100644 --- a/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -28,7 +28,7 @@ LL | fn meh() -> Box Meh<'_>> | ^^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values | LL | fn meh() -> Box Meh<'static>> | ~~~~~~~