diff --git a/src/librustc_ast_lowering/path.rs b/src/librustc_ast_lowering/path.rs index dde734756517c..cf6dde813096b 100644 --- a/src/librustc_ast_lowering/path.rs +++ b/src/librustc_ast_lowering/path.rs @@ -273,7 +273,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .next(); if !generic_args.parenthesized && !has_lifetimes { generic_args.args = self - .elided_path_lifetimes(path_span, expected_lifetimes) + .elided_path_lifetimes( + first_generic_span.map(|s| s.shrink_to_lo()).unwrap_or(segment.ident.span), + expected_lifetimes, + ) .map(GenericArg::Lifetime) .chain(generic_args.args.into_iter()) .collect(); diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index e7fa88bff97d5..c25a3524dc108 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -1034,101 +1034,125 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { lifetime_names: &FxHashSet, params: &[ElisionFailureInfo], ) { - if count > 1 { - err.span_label(span, format!("expected {} lifetime parameters", count)); - } else { - let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok(); - let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| { - err.span_suggestion( - span, - "consider using the named lifetime", - sugg, - Applicability::MaybeIncorrect, - ); - }; - let suggest_new = |err: &mut DiagnosticBuilder<'_>, sugg: &str| { - err.span_label(span, "expected named lifetime parameter"); + let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok(); - for missing in self.missing_named_lifetime_spots.iter().rev() { - let mut introduce_suggestion = vec![]; - let msg; - let should_break; - introduce_suggestion.push(match missing { - MissingLifetimeSpot::Generics(generics) => { - msg = "consider introducing a named lifetime parameter".to_string(); - should_break = true; - if let Some(param) = generics.params.iter().find(|p| match p.kind { - hir::GenericParamKind::Type { - synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), - .. - } => false, - _ => true, - }) { - (param.span.shrink_to_lo(), "'a, ".to_string()) - } else { - (generics.span, "<'a>".to_string()) - } - } - MissingLifetimeSpot::HigherRanked { span, span_type } => { - msg = format!( - "consider making the {} lifetime-generic with a new `'a` lifetime", - span_type.descr(), - ); - should_break = false; - err.note( - "for more information on higher-ranked polymorphism, visit \ - https://doc.rust-lang.org/nomicon/hrtb.html", - ); - (*span, span_type.suggestion("'a")) - } - }); - for param in params { - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) - { - if snippet.starts_with('&') && !snippet.starts_with("&'") { - introduce_suggestion - .push((param.span, format!("&'a {}", &snippet[1..]))); - } else if snippet.starts_with("&'_ ") { - introduce_suggestion - .push((param.span, format!("&'a {}", &snippet[4..]))); - } + err.span_label( + span, + &format!( + "expected {} lifetime parameter{}", + if count == 1 { "named".to_string() } else { count.to_string() }, + pluralize!(count) + ), + ); + + let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| { + err.span_suggestion_verbose( + span, + &format!("consider using the `{}` lifetime", lifetime_names.iter().next().unwrap()), + sugg, + Applicability::MaybeIncorrect, + ); + }; + let suggest_new = |err: &mut DiagnosticBuilder<'_>, sugg: &str| { + for missing in self.missing_named_lifetime_spots.iter().rev() { + let mut introduce_suggestion = vec![]; + let msg; + let should_break; + introduce_suggestion.push(match missing { + MissingLifetimeSpot::Generics(generics) => { + msg = "consider introducing a named lifetime parameter".to_string(); + should_break = true; + if let Some(param) = generics.params.iter().find(|p| match p.kind { + hir::GenericParamKind::Type { + synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), + .. + } => false, + _ => true, + }) { + (param.span.shrink_to_lo(), "'a, ".to_string()) + } else { + (generics.span, "<'a>".to_string()) } } - introduce_suggestion.push((span, sugg.to_string())); - err.multipart_suggestion( - &msg, - introduce_suggestion, - Applicability::MaybeIncorrect, - ); - if should_break { - break; + MissingLifetimeSpot::HigherRanked { span, span_type } => { + msg = format!( + "consider making the {} lifetime-generic with a new `'a` lifetime", + span_type.descr(), + ); + should_break = false; + err.note( + "for more information on higher-ranked polymorphism, visit \ + https://doc.rust-lang.org/nomicon/hrtb.html", + ); + (*span, span_type.suggestion("'a")) + } + }); + for param in params { + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) { + if snippet.starts_with('&') && !snippet.starts_with("&'") { + introduce_suggestion + .push((param.span, format!("&'a {}", &snippet[1..]))); + } else if snippet.starts_with("&'_ ") { + introduce_suggestion + .push((param.span, format!("&'a {}", &snippet[4..]))); + } } } - }; - - match (lifetime_names.len(), lifetime_names.iter().next(), snippet.as_deref()) { - (1, Some(name), Some("&")) => { - suggest_existing(err, format!("&{} ", name)); - } - (1, Some(name), Some("'_")) => { - suggest_existing(err, name.to_string()); - } - (1, Some(name), Some(snippet)) if !snippet.ends_with('>') => { - suggest_existing(err, format!("{}<{}>", snippet, name)); - } - (0, _, Some("&")) => { - suggest_new(err, "&'a "); - } - (0, _, Some("'_")) => { - suggest_new(err, "'a"); - } - (0, _, Some(snippet)) if !snippet.ends_with('>') => { - suggest_new(err, &format!("{}<'a>", snippet)); + introduce_suggestion.push((span, sugg.to_string())); + err.multipart_suggestion(&msg, introduce_suggestion, Applicability::MaybeIncorrect); + if should_break { + break; } - _ => { - err.span_label(span, "expected lifetime parameter"); + } + }; + + match (lifetime_names.len(), lifetime_names.iter().next(), snippet.as_deref()) { + (1, Some(name), Some("&")) => { + suggest_existing(err, format!("&{} ", name)); + } + (1, Some(name), Some("'_")) => { + suggest_existing(err, name.to_string()); + } + (1, Some(name), Some("")) => { + suggest_existing(err, format!("{}, ", name).repeat(count)); + } + (1, Some(name), Some(snippet)) if !snippet.ends_with('>') => { + suggest_existing( + err, + format!( + "{}<{}>", + snippet, + std::iter::repeat(name.to_string()) + .take(count) + .collect::>() + .join(", ") + ), + ); + } + (0, _, Some("&")) if count == 1 => { + suggest_new(err, "&'a "); + } + (0, _, Some("'_")) if count == 1 => { + suggest_new(err, "'a"); + } + (0, _, Some(snippet)) if !snippet.ends_with('>') && count == 1 => { + suggest_new(err, &format!("{}<'a>", snippet)); + } + (n, ..) if n > 1 => { + let spans: Vec = lifetime_names.iter().map(|lt| lt.span).collect(); + err.span_note(spans, "these named lifetimes are available to use"); + if Some("") == snippet.as_deref() { + // This happens when we have `Foo` where we point at the space before `T`, + // but this can be confusing so we give a suggestion with placeholders. + err.span_suggestion_verbose( + span, + "consider using one of the available lifetimes here", + "'lifetime, ".repeat(count), + Applicability::HasPlaceholders, + ); } } + _ => {} } } } diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 0d12bf08747fa..295770b382fba 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -2388,52 +2388,28 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { }; let mut err = self.report_missing_lifetime_specifiers(span, lifetime_refs.len()); - let mut add_label = true; if let Some(params) = error { - if lifetime_refs.len() == 1 { - add_label = add_label && self.report_elision_failure(&mut err, params, span); + // If there's no lifetime available, suggest `'static`. + if self.report_elision_failure(&mut err, params) && lifetime_names.is_empty() { + lifetime_names.insert(ast::Ident::from_str("'static")); } } - if add_label { - self.add_missing_lifetime_specifiers_label( - &mut err, - span, - lifetime_refs.len(), - &lifetime_names, - error.map(|p| &p[..]).unwrap_or(&[]), - ); - } - + self.add_missing_lifetime_specifiers_label( + &mut err, + span, + lifetime_refs.len(), + &lifetime_names, + error.map(|p| &p[..]).unwrap_or(&[]), + ); err.emit(); } - fn suggest_lifetime(&self, db: &mut DiagnosticBuilder<'_>, span: Span, msg: &str) -> bool { - match self.tcx.sess.source_map().span_to_snippet(span) { - Ok(ref snippet) => { - let (sugg, applicability) = if snippet == "&" { - ("&'static ".to_owned(), Applicability::MachineApplicable) - } else if snippet == "'_" { - ("'static".to_owned(), Applicability::MachineApplicable) - } else { - (format!("{} + 'static", snippet), Applicability::MaybeIncorrect) - }; - db.span_suggestion(span, msg, sugg, applicability); - false - } - Err(_) => { - db.help(msg); - true - } - } - } - fn report_elision_failure( &mut self, db: &mut DiagnosticBuilder<'_>, params: &[ElisionFailureInfo], - span: Span, - ) -> bool { + ) -> bool /* add `'static` lifetime to lifetime list */ { let mut m = String::new(); let len = params.len(); @@ -2482,29 +2458,28 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { "this function's return type contains a borrowed value, \ but there is no value for it to be borrowed from", ); - self.suggest_lifetime(db, span, "consider giving it a 'static lifetime") + true } else if elided_len == 0 { db.help( "this function's return type contains a borrowed value with \ an elided lifetime, but the lifetime cannot be derived from \ the arguments", ); - let msg = "consider giving it an explicit bounded or 'static lifetime"; - self.suggest_lifetime(db, span, msg) + true } else if elided_len == 1 { 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 + false } else { db.help(&format!( "this function's return type contains a borrowed value, \ but the signature does not say whether it is borrowed from {}", m )); - true + false } } diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 85a870ae34c11..e8252d96350db 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -657,7 +657,8 @@ impl MultiSpan { MultiSpan { primary_spans: vec![primary_span], span_labels: vec![] } } - pub fn from_spans(vec: Vec) -> MultiSpan { + pub fn from_spans(mut vec: Vec) -> MultiSpan { + vec.sort(); MultiSpan { primary_spans: vec, span_labels: vec![] } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 19c8f540c5700..7c6abd8def690 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1017,18 +1017,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1); - let path_span = if let [segment] = &trait_ref.path.segments[..] { - // FIXME: `trait_ref.path.span` can point to a full path with multiple - // segments, even though `trait_ref.path.segments` is of length `1`. Work - // around that bug here, even though it should be fixed elsewhere. - // This would otherwise cause an invalid suggestion. For an example, look at - // `src/test/ui/issues/issue-28344.rs`. - segment.ident.span - } else { - trait_ref.path.span - }; let (substs, assoc_bindings, arg_count_correct) = self.create_substs_for_ast_trait_ref( - path_span, + trait_ref.path.span, trait_def_id, self_ty, trait_ref.path.segments.last().unwrap(), @@ -1729,6 +1719,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ast_region_to_region(lifetime, None) } else { self.re_infer(None, span).unwrap_or_else(|| { + // FIXME: these can be redundant with E0106, but not always. struct_span_err!( tcx.sess, span, diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr index 2745e44ac0cfc..00f44129cc8b7 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr +++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr @@ -2,9 +2,13 @@ error[E0106]: missing lifetime specifier --> $DIR/bound-lifetime-in-binding-only.rs:52:23 | LL | fn elision &i32>() { - | ^ help: consider giving it a 'static lifetime: `&'static` + | ^ 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 + | +LL | fn elision &'static i32>() { + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr index 96f0cb85c8c4c..a5242707c7105 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr +++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr @@ -2,9 +2,13 @@ error[E0106]: missing lifetime specifier --> $DIR/bound-lifetime-in-return-only.rs:34:23 | LL | fn elision(_: fn() -> &i32) { - | ^ help: consider giving it a 'static lifetime: `&'static` + | ^ 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 + | +LL | fn elision(_: fn() -> &'static i32) { + | ^^^^^^^^ error: aborting due to previous error 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 6edb9e63d480a..ca42263dfed7b 100644 --- a/src/test/ui/async-await/issues/issue-63388-2.stderr +++ b/src/test/ui/async-await/issues/issue-63388-2.stderr @@ -4,9 +4,13 @@ error[E0106]: missing lifetime specifier LL | foo: &dyn Foo, bar: &'a dyn Foo | -------- ----------- LL | ) -> &dyn Foo - | ^ help: consider using the named lifetime: `&'a` + | ^ 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 `foo` or `bar` +help: consider using the `'a` lifetime + | +LL | ) -> &'a dyn Foo + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/c-variadic/variadic-ffi-6.stderr b/src/test/ui/c-variadic/variadic-ffi-6.stderr index 882e7f89f2a0d..4626a4bc2dcff 100644 --- a/src/test/ui/c-variadic/variadic-ffi-6.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-6.stderr @@ -2,9 +2,13 @@ error[E0106]: missing lifetime specifier --> $DIR/variadic-ffi-6.rs:7:6 | LL | ) -> &usize { - | ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static` + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +help: consider using the `'static` lifetime + | +LL | ) -> &'static usize { + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/foreign-fn-return-lifetime.stderr b/src/test/ui/foreign-fn-return-lifetime.stderr index 575da18f24043..feecb6d80e771 100644 --- a/src/test/ui/foreign-fn-return-lifetime.stderr +++ b/src/test/ui/foreign-fn-return-lifetime.stderr @@ -2,9 +2,13 @@ error[E0106]: missing lifetime specifier --> $DIR/foreign-fn-return-lifetime.rs:5:19 | LL | pub fn f() -> &u8; - | ^ help: consider giving it a 'static lifetime: `&'static` + | ^ 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 + | +LL | pub fn f() -> &'static u8; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr index 9f410c0dbbbd2..1106a06782280 100644 --- a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr +++ b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr @@ -5,16 +5,33 @@ LL | fn should_error() where T : Into<&u32> {} | ^ explicit lifetime name needed here error[E0106]: missing lifetime specifier - --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:19 + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:21 | LL | fn foo<'b, L: X<&'b Nested>>(); - | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | ^ expected named lifetime parameter + | +note: these named lifetimes are available to use + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:8:9 + | +LL | trait X<'a, K: 'a> { + | ^^ +LL | fn foo<'b, L: X<&'b Nested>>(); + | ^^ +help: consider using one of the available lifetimes here + | +LL | fn foo<'b, L: X<'lifetime, &'b Nested>>(); + | ^^^^^^^^^^ error[E0106]: missing lifetime specifier - --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:13:15 + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:13:17 | LL | fn bar<'b, L: X<&'b Nested>>(){} - | ^^^^^^^^^^^^^^^^^^ expected lifetime parameter + | ^ expected named lifetime parameter + | +help: consider using the `'b` lifetime + | +LL | fn bar<'b, L: X<'b, &'b Nested>>(){} + | ^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-13497.stderr b/src/test/ui/issues/issue-13497.stderr index b72f0277052b9..a231f73d06729 100644 --- a/src/test/ui/issues/issue-13497.stderr +++ b/src/test/ui/issues/issue-13497.stderr @@ -2,9 +2,13 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-13497.rs:2:5 | LL | &str - | ^ help: consider giving it a 'static lifetime: `&'static` + | ^ 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 + | +LL | &'static str + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr index 1d8fbdc63c5e0..3df58d66d1f8e 100644 --- a/src/test/ui/issues/issue-26638.stderr +++ b/src/test/ui/issues/issue-26638.stderr @@ -14,17 +14,25 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:4:40 | LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() } - | ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static` + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +help: consider using the `'static` lifetime + | +LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &'static str { iter() } + | ^^^^^^^^ error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:7:22 | LL | fn parse_type_3() -> &str { unimplemented!() } - | ^ help: consider giving it a 'static lifetime: `&'static` + | ^ 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 + | +LL | fn parse_type_3() -> &'static str { unimplemented!() } + | ^^^^^^^^ error: aborting due to 3 previous errors 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 461c1832e9af9..5809b5bd661e0 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 @@ -2,9 +2,13 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:2:11 | LL | fn f() -> &isize { - | ^ help: consider giving it a 'static lifetime: `&'static` + | ^ 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 + | +LL | fn f() -> &'static isize { + | ^^^^^^^^ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:7:33 @@ -34,25 +38,37 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:21:20 | LL | fn i(_x: isize) -> &isize { - | ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static` + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +help: consider using the `'static` lifetime + | +LL | fn i(_x: isize) -> &'static isize { + | ^^^^^^^^ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:34:24 | LL | fn j(_x: StaticStr) -> &isize { - | ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static` + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +help: consider using the `'static` lifetime + | +LL | fn j(_x: StaticStr) -> &'static isize { + | ^^^^^^^^ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:40:49 | LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize { - | ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static` + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +help: consider using the `'a` lifetime + | +LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &'a isize { + | ^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr index 9bf59bd4f636a..254eaf51a646b 100644 --- a/src/test/ui/specialization/defaultimpl/validation.stderr +++ b/src/test/ui/specialization/defaultimpl/validation.stderr @@ -25,13 +25,13 @@ LL | default impl !Send for Z {} | default because of this error[E0750]: negative impls cannot be default impls - --> $DIR/validation.rs:10:14 + --> $DIR/validation.rs:10:1 | LL | default impl !Send for Z {} | ^^^^^^^ ^ error[E0750]: negative impls cannot be default impls - --> $DIR/validation.rs:14:14 + --> $DIR/validation.rs:14:1 | LL | default impl !Tr for S {} | ^^^^^^^ ^ diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.rs b/src/test/ui/suggestions/missing-lifetime-specifier.rs new file mode 100644 index 0000000000000..b09c1879d7015 --- /dev/null +++ b/src/test/ui/suggestions/missing-lifetime-specifier.rs @@ -0,0 +1,65 @@ +#![allow(bare_trait_objects)] +use std::collections::HashMap; +use std::cell::RefCell; + +pub union Foo<'t, 'k> { + i: &'t i64, + f: &'k f64, +} +trait Bar<'t, 'k> {} + +pub union Qux<'t, 'k, I> { + i: &'t I, + f: &'k I, +} +trait Tar<'t, 'k, I> {} + +thread_local! { + static a: RefCell>>> = RefCell::new(HashMap::new()); + //~^ ERROR missing lifetime specifier + //~| ERROR missing lifetime specifier +} +thread_local! { + static b: RefCell>>> = RefCell::new(HashMap::new()); + //~^ ERROR missing lifetime specifier + //~| ERROR missing lifetime specifier + //~| ERROR missing lifetime specifier + //~| ERROR missing lifetime specifier + //~| ERROR the lifetime bound for this object type cannot be deduced from context + //~| ERROR the lifetime bound for this object type cannot be deduced from context +} +thread_local! { + static c: RefCell>>>> = RefCell::new(HashMap::new()); + //~^ ERROR missing lifetime specifier + //~| ERROR missing lifetime specifier +} +thread_local! { + static d: RefCell>>>> = RefCell::new(HashMap::new()); + //~^ ERROR missing lifetime specifier + //~| ERROR missing lifetime specifier + //~| ERROR missing lifetime specifier + //~| ERROR missing lifetime specifier + //~| ERROR the lifetime bound for this object type cannot be deduced from context + //~| ERROR the lifetime bound for this object type cannot be deduced from context +} + +thread_local! { + static e: RefCell>>>> = RefCell::new(HashMap::new()); + //~^ ERROR wrong number of lifetime arguments: expected 2, found 1 + //~| ERROR wrong number of lifetime arguments: expected 2, found 1 + //~| ERROR wrong number of lifetime arguments: expected 2, found 1 + //~| ERROR wrong number of lifetime arguments: expected 2, found 1 +} +thread_local! { + static f: RefCell>>>> = RefCell::new(HashMap::new()); + //~^ ERROR the lifetime bound for this object type cannot be deduced from context + //~| ERROR the lifetime bound for this object type cannot be deduced from context + //~| ERROR wrong number of lifetime arguments: expected 2, found 1 + //~| ERROR wrong number of lifetime arguments: expected 2, found 1 + //~| ERROR wrong number of lifetime arguments: expected 2, found 1 + //~| ERROR wrong number of lifetime arguments: expected 2, found 1 + //~| ERROR missing lifetime specifier + //~| ERROR missing lifetime specifier +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.stderr b/src/test/ui/suggestions/missing-lifetime-specifier.stderr new file mode 100644 index 0000000000000..f5ff54cc916cb --- /dev/null +++ b/src/test/ui/suggestions/missing-lifetime-specifier.stderr @@ -0,0 +1,256 @@ +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:18:44 + | +LL | static a: RefCell>>> = RefCell::new(HashMap::new()); + | ^^^ 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 + | +LL | static a: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:18:44 + | +LL | static a: RefCell>>> = RefCell::new(HashMap::new()); + | ^^^ 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 + | +LL | static a: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-specifier.rs:23:44 + | +LL | static b: RefCell>>> = RefCell::new(HashMap::new()); + | ^ 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 + | +LL | static b: RefCell>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:23:45 + | +LL | static b: RefCell>>> = RefCell::new(HashMap::new()); + | ^^^ 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 + | +LL | static b: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-specifier.rs:23:44 + | +LL | static b: RefCell>>> = RefCell::new(HashMap::new()); + | ^ 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 + | +LL | static b: RefCell>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:23:45 + | +LL | static b: RefCell>>> = RefCell::new(HashMap::new()); + | ^^^ 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 + | +LL | static b: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:32:48 + | +LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); + | ^ 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 + | +LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:32:48 + | +LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); + | ^ 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 + | +LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^ + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-specifier.rs:37:44 + | +LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | ^ 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 + | +LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:37:49 + | +LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | ^ 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 + | +LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^ + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-specifier.rs:37:44 + | +LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | ^ 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 + | +LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:37:49 + | +LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | ^ 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 + | +LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^ + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-specifier.rs:54:44 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^ 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 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^ + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-specifier.rs:54:44 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^ 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 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^ + +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/missing-lifetime-specifier.rs:23:45 + | +LL | static b: RefCell>>> = RefCell::new(HashMap::new()); + | ^^^ + +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/missing-lifetime-specifier.rs:23:45 + | +LL | static b: RefCell>>> = RefCell::new(HashMap::new()); + | ^^^ + +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/missing-lifetime-specifier.rs:37:45 + | +LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^ + +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/missing-lifetime-specifier.rs:37:45 + | +LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^ + +error[E0107]: wrong number of lifetime arguments: expected 2, found 1 + --> $DIR/missing-lifetime-specifier.rs:47:44 + | +LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments + +error[E0107]: wrong number of lifetime arguments: expected 2, found 1 + --> $DIR/missing-lifetime-specifier.rs:47:44 + | +LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments + +error[E0107]: wrong number of lifetime arguments: expected 2, found 1 + --> $DIR/missing-lifetime-specifier.rs:47:44 + | +LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments + +error[E0107]: wrong number of lifetime arguments: expected 2, found 1 + --> $DIR/missing-lifetime-specifier.rs:47:44 + | +LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments + +error[E0107]: wrong number of lifetime arguments: expected 2, found 1 + --> $DIR/missing-lifetime-specifier.rs:54:45 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments + +error[E0107]: wrong number of lifetime arguments: expected 2, found 1 + --> $DIR/missing-lifetime-specifier.rs:54:45 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments + +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/missing-lifetime-specifier.rs:54:45 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^ + +error[E0107]: wrong number of lifetime arguments: expected 2, found 1 + --> $DIR/missing-lifetime-specifier.rs:54:45 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments + +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/missing-lifetime-specifier.rs:54:45 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^ + +error[E0107]: wrong number of lifetime arguments: expected 2, found 1 + --> $DIR/missing-lifetime-specifier.rs:54:45 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments + +error: aborting due to 28 previous errors + +Some errors have detailed explanations: E0106, E0107. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/return-without-lifetime.stderr b/src/test/ui/suggestions/return-without-lifetime.stderr index ce3b1748da435..2a237d61f50fe 100644 --- a/src/test/ui/suggestions/return-without-lifetime.stderr +++ b/src/test/ui/suggestions/return-without-lifetime.stderr @@ -2,23 +2,36 @@ error[E0106]: missing lifetime specifier --> $DIR/return-without-lifetime.rs:2:16 | LL | struct Foo<'a>(&usize); - | ^ help: consider using the named lifetime: `&'a` + | ^ expected named lifetime parameter + | +help: consider using the `'a` lifetime + | +LL | struct Foo<'a>(&'a usize); + | ^^^ 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` + | --------- ^ expected named lifetime parameter | = 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 +help: consider using the `'a` lifetime + | +LL | fn func1<'a>(_arg: &'a Thing) -> &'a () { unimplemented!() } + | ^^^ 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` + | ---------- ^ expected named lifetime parameter | = 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 +help: consider using the `'a` lifetime + | +LL | fn func2<'a>(_arg: &Thing<'a>) -> &'a () { unimplemented!() } + | ^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/traits/negative-impls/negative-default-impls.stderr b/src/test/ui/traits/negative-impls/negative-default-impls.stderr index d2423d01a9afa..a70bbe6b948d1 100644 --- a/src/test/ui/traits/negative-impls/negative-default-impls.stderr +++ b/src/test/ui/traits/negative-impls/negative-default-impls.stderr @@ -1,5 +1,5 @@ error[E0750]: negative impls cannot be default impls - --> $DIR/negative-default-impls.rs:8:14 + --> $DIR/negative-default-impls.rs:8:1 | LL | default impl !MyTrait for u32 {} | ^^^^^^^ ^ diff --git a/src/test/ui/unboxed-closures/unboxed-closure-feature-gate.stderr b/src/test/ui/unboxed-closures/unboxed-closure-feature-gate.stderr index 7af9c57a8300a..b824d160d7160 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-feature-gate.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-feature-gate.stderr @@ -2,7 +2,7 @@ error[E0658]: parenthetical notation is only stable when used with `Fn`-family t --> $DIR/unboxed-closure-feature-gate.rs:13:20 | LL | let x: Box; - | ^^^ + | ^^^^^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr index 9a3bdd2bd5ea4..9da36906d5542 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr @@ -2,7 +2,7 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje --> $DIR/unboxed-closure-sugar-not-used-on-fn.rs:3:17 | LL | fn bar1(x: &dyn Fn<(), Output=()>) { - | ^^ help: use parenthetical notation instead: `Fn() -> ()` + | ^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn() -> ()` | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable @@ -11,7 +11,7 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje --> $DIR/unboxed-closure-sugar-not-used-on-fn.rs:7:28 | LL | fn bar2(x: &T) where T: Fn<()> { - | ^^ help: use parenthetical notation instead: `Fn() -> ()` + | ^^^^^^ help: use parenthetical notation instead: `Fn() -> ()` | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr index b92f054498b68..e9d51983a7a48 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr @@ -2,7 +2,7 @@ error[E0107]: wrong number of lifetime arguments: expected 1, found 0 --> $DIR/unboxed-closure-sugar-region.rs:30:51 | LL | fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) { - | ^^^ expected 1 lifetime argument + | ^^^^^^^^^^ expected 1 lifetime argument error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr index f482098cbffcb..f42ac38d370d5 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr @@ -2,7 +2,7 @@ error[E0107]: wrong number of type arguments: expected 3, found 1 --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:16 | LL | fn foo(_: &dyn Three()) - | ^^^^^ expected 3 type arguments + | ^^^^^^^ expected 3 type arguments error[E0220]: associated type `Output` not found for `Three<(), [type error], [type error]>` --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:16 diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr index ada4551baefff..594cdd245b3ec 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -14,15 +14,24 @@ error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:2:17 | LL | struct Baz<'a>(&'_ &'a u8); - | ^^ help: consider using the named lifetime: `'a` + | ^^ expected named lifetime parameter + | +help: consider using the `'a` lifetime + | +LL | struct Baz<'a>(&'a &'a u8); + | ^^ error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:10:33 | LL | fn meh() -> Box Meh<'_>> - | ^^ help: consider giving it a 'static lifetime: `'static` + | ^^ 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 + | +LL | fn meh() -> Box Meh<'static>> + | ^^^^^^^ error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:16:35 diff --git a/src/test/ui/unspecified-self-in-trait-ref.stderr b/src/test/ui/unspecified-self-in-trait-ref.stderr index e057a7842b2aa..9310b3d7ede00 100644 --- a/src/test/ui/unspecified-self-in-trait-ref.stderr +++ b/src/test/ui/unspecified-self-in-trait-ref.stderr @@ -31,7 +31,7 @@ LL | | } | |_- type parameter `A` must be specified for this ... LL | let e = Bar::::lol(); - | ^^^ missing reference to `A` + | ^^^^^^^^^^^^^^^^^ missing reference to `A` | = note: because of the default `Self` reference, type parameters must be specified on object types