diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 3b689f03b43ba..8213a99a92d1e 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -19,7 +19,7 @@ use syntax::ast::{self, Ident, Path}; use syntax::util::lev_distance::find_best_match_for_name; use crate::imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver}; -use crate::lifetimes::{ElisionFailureInfo, HRLTSpanType, MissingLifetimeSpot}; +use crate::lifetimes::{ElisionFailureInfo, ForLifetimeSpanType, MissingLifetimeSpot}; use crate::path_names_to_string; use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind}; use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot}; @@ -1495,7 +1495,7 @@ crate fn add_missing_lifetime_specifiers_label( let should_break; introduce_suggestion.push(match missing { MissingLifetimeSpot::Generics(generics) => { - msg = "consider introducing a named lifetime parameter"; + msg = "consider introducing a named lifetime parameter".to_string(); should_break = true; match &generics.params { [] => (generics.span, "<'a>".to_string()), @@ -1503,15 +1503,27 @@ crate fn add_missing_lifetime_specifiers_label( } } MissingLifetimeSpot::HRLT { span, span_type } => { - msg = "consider introducing a higher-ranked lifetime"; + msg = format!( + "consider making the {} lifetime-generic with a new `'a` lifetime", + match span_type { + ForLifetimeSpanType::BoundEmpty + | ForLifetimeSpanType::BoundTail => "bound", + ForLifetimeSpanType::TypeEmpty | ForLifetimeSpanType::TypeTail => + "type", + } + ); should_break = false; err.note( "for more information on higher-ranked lifetimes, visit \ https://doc.rust-lang.org/nomicon/hrtb.html", ); let suggestion = match span_type { - HRLTSpanType::Empty => "for<'a> ", - HRLTSpanType::Tail => ", 'a", + ForLifetimeSpanType::BoundEmpty | ForLifetimeSpanType::TypeEmpty => { + "for<'a> " + } + ForLifetimeSpanType::BoundTail | ForLifetimeSpanType::TypeTail => { + ", 'a" + } }; (*span, suggestion.to_string()) } @@ -1528,7 +1540,7 @@ crate fn add_missing_lifetime_specifiers_label( } } introduce_suggestion.push((span, sugg.to_string())); - err.multipart_suggestion(msg, introduce_suggestion, Applicability::MaybeIncorrect); + err.multipart_suggestion(&msg, introduce_suggestion, Applicability::MaybeIncorrect); if should_break { break; } diff --git a/src/librustc_resolve/lifetimes.rs b/src/librustc_resolve/lifetimes.rs index 69deffe4a4c9a..9bb852b2093aa 100644 --- a/src/librustc_resolve/lifetimes.rs +++ b/src/librustc_resolve/lifetimes.rs @@ -155,12 +155,14 @@ struct NamedRegionMap { crate enum MissingLifetimeSpot<'tcx> { Generics(&'tcx hir::Generics<'tcx>), - HRLT { span: Span, span_type: HRLTSpanType }, + HRLT { span: Span, span_type: ForLifetimeSpanType }, } -crate enum HRLTSpanType { - Empty, - Tail, +crate enum ForLifetimeSpanType { + BoundEmpty, + BoundTail, + TypeEmpty, + TypeTail, } impl<'tcx> Into> for &'tcx hir::Generics<'tcx> { @@ -509,6 +511,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let next_early_index = self.next_early_index(); let was_in_fn_syntax = self.is_in_fn_syntax; self.is_in_fn_syntax = true; + let lifetime_span: Option = c + .generic_params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => Some(param.span), + _ => None, + }) + .last(); + let (span, span_type) = if let Some(span) = lifetime_span { + (span.shrink_to_hi(), ForLifetimeSpanType::TypeTail) + } else { + (ty.span.shrink_to_lo(), ForLifetimeSpanType::TypeEmpty) + }; + self.missing_named_lifetime_spots + .push(MissingLifetimeSpot::HRLT { span, span_type }); let scope = Scope::Binder { lifetimes: c .generic_params @@ -531,6 +548,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { this.check_lifetime_params(old_scope, &c.generic_params); intravisit::walk_ty(this, ty); }); + self.missing_named_lifetime_spots.pop(); self.is_in_fn_syntax = was_in_fn_syntax; } hir::TyKind::TraitObject(bounds, ref lifetime) => { @@ -1873,12 +1891,23 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { err.span_suggestion( *span, &format!( - "consider introducing a higher-ranked lifetime `{}` here", + "consider making the {} lifetime-generic with a new `{}` lifetime", + match span_type { + ForLifetimeSpanType::BoundEmpty + | ForLifetimeSpanType::BoundTail => "bound", + ForLifetimeSpanType::TypeEmpty + | ForLifetimeSpanType::TypeTail => "type", + }, lifetime_ref ), match span_type { - HRLTSpanType::Empty => format!("for<{}> ", lifetime_ref), - HRLTSpanType::Tail => format!(", {}", lifetime_ref), + ForLifetimeSpanType::TypeEmpty + | ForLifetimeSpanType::BoundEmpty => { + format!("for<{}> ", lifetime_ref) + } + ForLifetimeSpanType::TypeTail | ForLifetimeSpanType::BoundTail => { + format!(", {}", lifetime_ref) + } } .to_string(), Applicability::MaybeIncorrect, @@ -2487,13 +2516,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { params.iter().cloned().filter(|info| info.lifetime_count > 0).collect(); let elided_len = elided_params.len(); - let mut spans = vec![]; for (i, info) in elided_params.into_iter().enumerate() { let ElisionFailureInfo { parent, index, lifetime_count: n, have_bound_regions, span } = info; - spans.push(span); + db.span_label(span, ""); let help_name = if let Some(ident) = parent.and_then(|body| self.tcx.hir().body(body).params[index].pat.simple_ident()) { @@ -2524,14 +2552,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } - let help = |msg| { - if spans.is_empty() { - db.help(msg); - } else { - db.span_help(spans, msg); - } - }; - if len == 0 { db.help( "this function's return type contains a borrowed value, \ @@ -2539,7 +2559,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { ); self.suggest_lifetime(db, span, "consider giving it a 'static lifetime") } else if elided_len == 0 { - help( + db.help( "this function's return type contains a borrowed value with \ an elided lifetime, but the lifetime cannot be derived from \ the arguments", @@ -2547,14 +2567,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let msg = "consider giving it an explicit bounded or 'static lifetime"; self.suggest_lifetime(db, span, msg) } else if elided_len == 1 { - help(&format!( + db.help(&format!( "this function's return type contains a borrowed value, \ but the signature does not say which {} it is borrowed from", m )); true } else { - help(&format!( + db.help(&format!( "this function's return type contains a borrowed value, \ but the signature does not say whether it is borrowed from {}", m @@ -2816,8 +2836,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .contains(&Some(did)) { let (span, span_type) = match &trait_ref.bound_generic_params { - [] => (trait_ref.span.shrink_to_lo(), HRLTSpanType::Empty), - [.., bound] => (bound.span.shrink_to_hi(), HRLTSpanType::Tail), + [] => (trait_ref.span.shrink_to_lo(), ForLifetimeSpanType::BoundEmpty), + [.., bound] => (bound.span.shrink_to_hi(), ForLifetimeSpanType::BoundTail), }; self.missing_named_lifetime_spots .push(MissingLifetimeSpot::HRLT { span, span_type }); diff --git a/src/test/ui/async-await/issues/issue-63388-2.stderr b/src/test/ui/async-await/issues/issue-63388-2.stderr index a12c601b936af..9f51ced9c3f49 100644 --- a/src/test/ui/async-await/issues/issue-63388-2.stderr +++ b/src/test/ui/async-await/issues/issue-63388-2.stderr @@ -1,14 +1,12 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-63388-2.rs:12:10 | +LL | foo: &dyn Foo, bar: &'a dyn Foo + | -------- ----------- LL | ) -> &dyn Foo | ^ help: consider using the named lifetime: `&'a` | -help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar` - --> $DIR/issue-63388-2.rs:11:14 - | -LL | foo: &dyn Foo, bar: &'a dyn Foo - | ^^^^^^^^ ^^^^^^^^^^^ + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar` error: cannot infer an appropriate lifetime --> $DIR/issue-63388-2.rs:11:9 diff --git a/src/test/ui/generic/generic-extern-lifetime.stderr b/src/test/ui/generic/generic-extern-lifetime.stderr index 39372c9315831..5e25952390b2d 100644 --- a/src/test/ui/generic/generic-extern-lifetime.stderr +++ b/src/test/ui/generic/generic-extern-lifetime.stderr @@ -9,12 +9,24 @@ error[E0261]: use of undeclared lifetime name `'a` | LL | pub fn life4<'b>(x: for<'c> fn(&'a i32)); | ^^ undeclared lifetime + | + = note: for more information on higher-ranked lifetimes, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the type lifetime-generic with a new `'a` lifetime + | +LL | pub fn life4<'b>(x: for<'c, 'a> fn(&'a i32)); + | ^^^^ error[E0261]: use of undeclared lifetime name `'a` --> $DIR/generic-extern-lifetime.rs:11:38 | LL | pub fn life7<'b>() -> for<'c> fn(&'a i32); | ^^ undeclared lifetime + | + = note: for more information on higher-ranked lifetimes, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the type lifetime-generic with a new `'a` lifetime + | +LL | pub fn life7<'b>() -> for<'c, 'a> fn(&'a i32); + | ^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr index 7d71230e16210..5abaf3c3aefff 100644 --- a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr +++ b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr @@ -9,10 +9,18 @@ LL | let y: &'test u32 = x; error[E0261]: use of undeclared lifetime name `'test` --> $DIR/no_introducing_in_band_in_locals.rs:10:16 | -LL | fn bar() { - | - help: consider introducing lifetime `'test` here: `<'test>` LL | let y: fn(&'test u32) = foo2; | ^^^^^ undeclared lifetime + | + = note: for more information on higher-ranked lifetimes, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider introducing lifetime `'test` here + | +LL | fn bar<'test>() { + | ^^^^^^^ +help: consider making the type lifetime-generic with a new `'test` lifetime + | +LL | let y: for<'test> fn(&'test u32) = foo2; + | ^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-19707.stderr b/src/test/ui/issues/issue-19707.stderr index e84bfb969d4f9..398e97a6f207a 100644 --- a/src/test/ui/issues/issue-19707.stderr +++ b/src/test/ui/issues/issue-19707.stderr @@ -2,13 +2,14 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-19707.rs:3:28 | LL | type Foo = fn(&u8, &u8) -> &u8; - | ^ expected named lifetime parameter + | --- --- ^ expected named lifetime parameter | -help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 - --> $DIR/issue-19707.rs:3:15 + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 + = note: for more information on higher-ranked lifetimes, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the type lifetime-generic with a new `'a` lifetime | -LL | type Foo = fn(&u8, &u8) -> &u8; - | ^^^ ^^^ +LL | type Foo = for<'a> fn(&'a u8, &'a u8) -> &'a u8; + | ^^^^^^^ ^^^^^^ ^^^^^^ ^^^ help: consider introducing a named lifetime parameter | LL | type Foo<'a> = fn(&'a u8, &'a u8) -> &'a u8; @@ -18,15 +19,11 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-19707.rs:5:27 | LL | fn bar &u8>(f: &F) {} - | ^ expected named lifetime parameter + | --- --- ^ expected named lifetime parameter | -help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 - --> $DIR/issue-19707.rs:5:14 - | -LL | fn bar &u8>(f: &F) {} - | ^^^ ^^^ + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 = note: for more information on higher-ranked lifetimes, visit https://doc.rust-lang.org/nomicon/hrtb.html -help: consider introducing a higher-ranked lifetime +help: consider making the bound lifetime-generic with a new `'a` lifetime | LL | fn bar Fn(&'a u8, &'a u8) -> &'a u8>(f: &F) {} | ^^^^^^^ ^^^^^^ ^^^^^^ ^^^ diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr index 75cd5332fd9a4..1d8fbdc63c5e0 100644 --- a/src/test/ui/issues/issue-26638.stderr +++ b/src/test/ui/issues/issue-26638.stderr @@ -2,13 +2,9 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:1:62 | LL | fn parse_type(iter: Box+'static>) -> &str { iter.next() } - | ^ expected named lifetime parameter + | ------------------------------------ ^ expected named lifetime parameter | -help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from - --> $DIR/issue-26638.rs:1:21 - | -LL | fn parse_type(iter: Box+'static>) -> &str { iter.next() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from help: consider introducing a named lifetime parameter | LL | fn parse_type<'a>(iter: Box+'static>) -> &'a str { iter.next() } diff --git a/src/test/ui/issues/issue-30255.stderr b/src/test/ui/issues/issue-30255.stderr index 3c26365d5d168..ab43d4a3c6002 100644 --- a/src/test/ui/issues/issue-30255.stderr +++ b/src/test/ui/issues/issue-30255.stderr @@ -2,13 +2,9 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-30255.rs:9:24 | LL | fn f(a: &S, b: i32) -> &i32 { - | ^ expected named lifetime parameter + | -- ^ expected named lifetime parameter | -help: this function's return type contains a borrowed value, but the signature does not say which one of `a`'s 2 lifetimes it is borrowed from - --> $DIR/issue-30255.rs:9:9 - | -LL | fn f(a: &S, b: i32) -> &i32 { - | ^^ + = help: this function's return type contains a borrowed value, but the signature does not say which one of `a`'s 2 lifetimes it is borrowed from help: consider introducing a named lifetime parameter | LL | fn f<'a>(a: &'a S, b: i32) -> &'a i32 { @@ -18,13 +14,9 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-30255.rs:14:34 | LL | fn g(a: &S, b: bool, c: &i32) -> &i32 { - | ^ expected named lifetime parameter - | -help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `a`'s 2 lifetimes or `c` - --> $DIR/issue-30255.rs:14:9 + | -- ---- ^ expected named lifetime parameter | -LL | fn g(a: &S, b: bool, c: &i32) -> &i32 { - | ^^ ^^^^ + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `a`'s 2 lifetimes or `c` help: consider introducing a named lifetime parameter | LL | fn g<'a>(a: &'a S, b: bool, c: &'a i32) -> &'a i32 { @@ -34,13 +26,9 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-30255.rs:19:44 | LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 { - | ^ expected named lifetime parameter - | -help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a`, one of `c`'s 2 lifetimes, or `d` - --> $DIR/issue-30255.rs:19:9 + | ----- -- ---- ^ expected named lifetime parameter | -LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 { - | ^^^^^ ^^ ^^^^ + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a`, one of `c`'s 2 lifetimes, or `d` help: consider introducing a named lifetime parameter | LL | fn h<'a>(a: &'a bool, b: bool, c: &'a S, d: &'a i32) -> &'a i32 { diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index b81ce552b3908..461c1832e9af9 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -10,13 +10,9 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:7:33 | LL | fn g(_x: &isize, _y: &isize) -> &isize { - | ^ expected named lifetime parameter + | ------ ------ ^ expected named lifetime parameter | -help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_x` or `_y` - --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:7:10 - | -LL | fn g(_x: &isize, _y: &isize) -> &isize { - | ^^^^^^ ^^^^^^ + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_x` or `_y` help: consider introducing a named lifetime parameter | LL | fn g<'a>(_x: &'a isize, _y: &'a isize) -> &'a isize { @@ -26,13 +22,9 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:19 | LL | fn h(_x: &Foo) -> &isize { - | ^ expected named lifetime parameter + | ---- ^ expected named lifetime parameter | -help: this function's return type contains a borrowed value, but the signature does not say which one of `_x`'s 2 lifetimes it is borrowed from - --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:10 - | -LL | fn h(_x: &Foo) -> &isize { - | ^^^^ + = help: this function's return type contains a borrowed value, but the signature does not say which one of `_x`'s 2 lifetimes it is borrowed from help: consider introducing a named lifetime parameter | LL | fn h<'a>(_x: &'a Foo) -> &'a isize { diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr index 47b048a7a9779..c1fcab2409f64 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr @@ -2,13 +2,9 @@ error[E0106]: missing lifetime specifier --> $DIR/ex1b-return-no-names-if-else.rs:1:29 | LL | fn foo(x: &i32, y: &i32) -> &i32 { - | ^ expected named lifetime parameter + | ---- ---- ^ expected named lifetime parameter | -help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` - --> $DIR/ex1b-return-no-names-if-else.rs:1:11 - | -LL | fn foo(x: &i32, y: &i32) -> &i32 { - | ^^^^ ^^^^ + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` help: consider introducing a named lifetime parameter | LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { diff --git a/src/test/ui/regions/regions-name-undeclared.stderr b/src/test/ui/regions/regions-name-undeclared.stderr index 498667abe36d9..e139e3f425189 100644 --- a/src/test/ui/regions/regions-name-undeclared.stderr +++ b/src/test/ui/regions/regions-name-undeclared.stderr @@ -94,7 +94,7 @@ help: consider introducing lifetime `'b` here | LL | fn fn_types<'b>(a: &'a isize, | ^^^^ -help: consider introducing a higher-ranked lifetime `'b` here +help: consider making the bound lifetime-generic with a new `'b` lifetime | LL | b: Box FnOnce(&'a isize, | ^^^^ @@ -110,7 +110,7 @@ help: consider introducing lifetime `'b` here | LL | fn fn_types<'b>(a: &'a isize, | ^^^^ -help: consider introducing a higher-ranked lifetime `'b` here +help: consider making the bound lifetime-generic with a new `'b` lifetime | LL | b: Box FnOnce(&'a isize, | ^^^^ diff --git a/src/test/ui/rfc1623-2.rs b/src/test/ui/rfc1623-2.rs new file mode 100644 index 0000000000000..35a2ef10c2e3c --- /dev/null +++ b/src/test/ui/rfc1623-2.rs @@ -0,0 +1,13 @@ +#![allow(dead_code)] + +fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 { + a +} + +// the boundaries of elision +static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = +//~^ ERROR missing lifetime specifier [E0106] + &(non_elidable as fn(&u8, &u8) -> &u8); + //~^ ERROR missing lifetime specifier [E0106] + +fn main() {} diff --git a/src/test/ui/rfc1623-2.stderr b/src/test/ui/rfc1623-2.stderr new file mode 100644 index 0000000000000..c927ad9e0ba4b --- /dev/null +++ b/src/test/ui/rfc1623-2.stderr @@ -0,0 +1,29 @@ +error[E0106]: missing lifetime specifier + --> $DIR/rfc1623-2.rs:8:42 + | +LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = + | --- --- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 + = note: for more information on higher-ranked lifetimes, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the type lifetime-generic with a new `'a` lifetime + | +LL | static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 = + | ^^^^^^^ ^^^^^^ ^^^^^^ ^^^ + +error[E0106]: missing lifetime specifier + --> $DIR/rfc1623-2.rs:10:39 + | +LL | &(non_elidable as fn(&u8, &u8) -> &u8); + | --- --- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 + = note: for more information on higher-ranked lifetimes, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the type lifetime-generic with a new `'a` lifetime + | +LL | &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8); + | ^^^^^^^ ^^^^^^ ^^^^^^ ^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/rfc1623.rs b/src/test/ui/rfc1623.rs index ebb4d56af9eec..55f5d0b94dcb0 100644 --- a/src/test/ui/rfc1623.rs +++ b/src/test/ui/rfc1623.rs @@ -4,11 +4,10 @@ fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 { a } -// the boundaries of elision -static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = -//~^ ERROR missing lifetime specifier [E0106] - &(non_elidable as fn(&u8, &u8) -> &u8); - //~^ ERROR missing lifetime specifier [E0106] +// The incorrect case without `for<'a>` is tested for in `rfc1623-2.rs` +static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 = + &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8); + struct SomeStruct<'x, 'y, 'z: 'x> { foo: &'x Foo<'z>, @@ -20,10 +19,12 @@ fn id(t: T) -> T { t } -static SOME_STRUCT: &SomeStruct = SomeStruct { +static SOME_STRUCT: &SomeStruct = SomeStruct { //~ ERROR mismatched types foo: &Foo { bools: &[false, true] }, bar: &Bar { bools: &[true, true] }, f: &id, + //~^ ERROR type mismatch in function arguments + //~| ERROR type mismatch resolving }; // very simple test for a 'static static with default lifetime diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.stderr index aabe088d63ca6..ca956004ef76f 100644 --- a/src/test/ui/rfc1623.stderr +++ b/src/test/ui/rfc1623.stderr @@ -1,27 +1,46 @@ -error[E0106]: missing lifetime specifier - --> $DIR/rfc1623.rs:8:42 +error[E0308]: mismatched types + --> $DIR/rfc1623.rs:22:35 | -LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = - | ^ expected named lifetime parameter +LL | static SOME_STRUCT: &SomeStruct = SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | +LL | | }; + | |_^ expected `&SomeStruct<'static, 'static, 'static>`, found struct `SomeStruct` | -help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 - --> $DIR/rfc1623.rs:8:29 +help: consider borrowing here | -LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = - | ^^^ ^^^ +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { +LL | foo: &Foo { bools: &[false, true] }, +LL | bar: &Bar { bools: &[true, true] }, +LL | f: &id, +LL | +LL | + ... -error[E0106]: missing lifetime specifier - --> $DIR/rfc1623.rs:10:39 +error[E0631]: type mismatch in function arguments + --> $DIR/rfc1623.rs:25:8 | -LL | &(non_elidable as fn(&u8, &u8) -> &u8); - | ^ expected named lifetime parameter +LL | fn id(t: T) -> T { + | ------------------- found signature of `fn(_) -> _` +... +LL | f: &id, + | ^^^ expected signature of `for<'a, 'b> fn(&'a Foo<'b>) -> _` | -help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 - --> $DIR/rfc1623.rs:10:26 + = note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` + +error[E0271]: type mismatch resolving `for<'a, 'b> _ {id::<_>} as std::ops::FnOnce<(&'a Foo<'b>,)>>::Output == &'a Foo<'b>` + --> $DIR/rfc1623.rs:25:8 + | +LL | f: &id, + | ^^^ expected bound lifetime parameter 'a, found concrete lifetime | -LL | &(non_elidable as fn(&u8, &u8) -> &u8); - | ^^^ ^^^ + = note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0271, E0308, E0631. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr b/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr index 858f23f1362cc..66913a3c544b3 100644 --- a/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr +++ b/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr @@ -9,7 +9,7 @@ help: consider introducing lifetime `'a` here | LL | struct S1<'a, F: Fn(&i32, &i32) -> &'a i32>(F); | ^^^ -help: consider introducing a higher-ranked lifetime `'a` here +help: consider making the bound lifetime-generic with a new `'a` lifetime | LL | struct S1 Fn(&i32, &i32) -> &'a i32>(F); | ^^^^^^^ @@ -18,15 +18,11 @@ error[E0106]: missing lifetime specifier --> $DIR/fn-missing-lifetime-in-item.rs:2:32 | LL | struct S2 &i32>(F); - | ^ expected named lifetime parameter + | ---- ---- ^ expected named lifetime parameter | -help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 - --> $DIR/fn-missing-lifetime-in-item.rs:2:17 - | -LL | struct S2 &i32>(F); - | ^^^^ ^^^^ + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 = note: for more information on higher-ranked lifetimes, visit https://doc.rust-lang.org/nomicon/hrtb.html -help: consider introducing a higher-ranked lifetime +help: consider making the bound lifetime-generic with a new `'a` lifetime | LL | struct S2 Fn(&'a i32, &'a i32) -> &'a i32>(F); | ^^^^^^^ ^^^^^^^ ^^^^^^^ ^^^ diff --git a/src/test/ui/suggestions/return-without-lifetime.stderr b/src/test/ui/suggestions/return-without-lifetime.stderr index 3b7936c5f44b6..ce3b1748da435 100644 --- a/src/test/ui/suggestions/return-without-lifetime.stderr +++ b/src/test/ui/suggestions/return-without-lifetime.stderr @@ -8,25 +8,17 @@ error[E0106]: missing lifetime specifier --> $DIR/return-without-lifetime.rs:5:34 | LL | fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() } - | ^ help: consider using the named lifetime: `&'a` + | --------- ^ help: consider using the named lifetime: `&'a` | -help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from - --> $DIR/return-without-lifetime.rs:5:20 - | -LL | fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() } - | ^^^^^^^^^ + = help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from error[E0106]: missing lifetime specifier --> $DIR/return-without-lifetime.rs:7:35 | LL | fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() } - | ^ help: consider using the named lifetime: `&'a` + | ---------- ^ help: consider using the named lifetime: `&'a` | -help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from - --> $DIR/return-without-lifetime.rs:7:20 - | -LL | fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() } - | ^^^^^^^^^^ + = help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from error: aborting due to 3 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr index 2431e8ece3807..1719a99d421d0 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr @@ -2,13 +2,9 @@ error[E0106]: missing lifetime specifier --> $DIR/unboxed-closure-sugar-lifetime-elision.rs:26:39 | LL | let _: dyn Foo(&isize, &usize) -> &usize; - | ^ expected named lifetime parameter + | ------ ------ ^ expected named lifetime parameter | -help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 - --> $DIR/unboxed-closure-sugar-lifetime-elision.rs:26:20 - | -LL | let _: dyn Foo(&isize, &usize) -> &usize; - | ^^^^^^ ^^^^^^ + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 help: consider introducing a named lifetime parameter | LL | fn main<'a>() { diff --git a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr index 0e410e25ecf25..8d2c82e59edc1 100644 --- a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr +++ b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr @@ -2,13 +2,9 @@ error[E0106]: missing lifetime specifier --> $DIR/in-fn-return-illegal.rs:5:30 | LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } } - | ^^ expected named lifetime parameter + | ---- ---- ^^ expected named lifetime parameter | -help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` - --> $DIR/in-fn-return-illegal.rs:5:11 - | -LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } } - | ^^^^ ^^^^ + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` help: consider introducing a named lifetime parameter | LL | fn foo<'a>(x: &'a u32, y: &'a u32) -> &'a u32 { loop { } } diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr index d0eda1b615381..c7cda38e47691 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -28,13 +28,9 @@ error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:16:35 | LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } - | ^^ expected named lifetime parameter + | ------ ------ ^^ expected named lifetime parameter | -help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or `y` - --> $DIR/underscore-lifetime-binders.rs:16:12 - | -LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } - | ^^^^^^ ^^^^^^ + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or `y` help: consider introducing a named lifetime parameter | LL | fn foo2<'a>(_: &'a u8, y: &'a u8) -> &'a u8 { y }