From 13c1daeb2f626b3923f7574226a089d95c8c7772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 16 Apr 2020 21:33:42 -0700 Subject: [PATCH 1/6] Tweak `'static` suggestion code Fix #71196. --- src/librustc_ast_lowering/path.rs | 5 +- src/librustc_resolve/late/diagnostics.rs | 185 +++++++------ src/librustc_resolve/late/lifetimes.rs | 52 +--- src/librustc_typeck/astconv.rs | 1 + ...nd-lifetime-in-binding-only.elision.stderr | 6 +- ...und-lifetime-in-return-only.elision.stderr | 6 +- .../async-await/issues/issue-63388-2.stderr | 6 +- src/test/ui/c-variadic/variadic-ffi-6.stderr | 6 +- src/test/ui/foreign-fn-return-lifetime.stderr | 6 +- ...rrect-explicit-lifetime-name-needed.stderr | 13 +- src/test/ui/issues/issue-13497.stderr | 6 +- src/test/ui/issues/issue-26638.stderr | 12 +- ...urn-type-requires-explicit-lifetime.stderr | 24 +- .../suggestions/missing-lifetime-specifier.rs | 65 +++++ .../missing-lifetime-specifier.stderr | 256 ++++++++++++++++++ .../return-without-lifetime.stderr | 19 +- .../underscore-lifetime-binders.stderr | 13 +- 17 files changed, 532 insertions(+), 149 deletions(-) create mode 100644 src/test/ui/suggestions/missing-lifetime-specifier.rs create mode 100644 src/test/ui/suggestions/missing-lifetime-specifier.stderr 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..5e03d4e114099 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -1034,101 +1034,110 @@ 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"); + err.span_label( + span, + &format!( + "expected {} lifetime parameter{}", + if count == 1 { "named".to_string() } else { count.to_string() }, + pluralize!(count) + ), + ); - 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..]))); - } + let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok(); + let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| { + err.span_suggestion_verbose( + span, + "consider using the named lifetime", + 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)); - } - _ => { - err.span_label(span, "expected lifetime parameter"); + introduce_suggestion.push((span, sugg.to_string())); + err.multipart_suggestion(&msg, introduce_suggestion, Applicability::MaybeIncorrect); + if should_break { + break; } } + }; + + 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)); + } + _ => {} } } } diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index defb2c06b32ca..41c798f9229e5 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -2388,51 +2388,26 @@ 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 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 { let mut m = String::new(); let len = params.len(); @@ -2482,29 +2457,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_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 19c8f540c5700..51e5a0113c6c6 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1729,6 +1729,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..7608c4a68f1ee 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 named 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..2e31a4f3abb2f 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 named 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..74f760d6c9286 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 named 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..0d491faa9d1e2 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 named 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..14153f302da84 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 named 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..3c5bdccd96657 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,21 @@ 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 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 named 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..8454c6be61dff 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 named 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..3049ea772f272 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 named 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 named 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..dae1e39018977 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 named 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 named 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 named 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 named 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/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..aeb1229d1746b --- /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 named 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 named 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 named 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 named 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 named 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 named 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 named 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 named 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 named 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 named 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 named 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 named 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 named 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 named 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..a93830edf3eea 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 named 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 named 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 named lifetime + | +LL | fn func2<'a>(_arg: &Thing<'a>) -> &'a () { unimplemented!() } + | ^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr index ada4551baefff..ffccd100cb09b 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 named 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 named lifetime + | +LL | fn meh() -> Box Meh<'static>> + | ^^^^^^^ error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:16:35 From 1f43fc020935aaf0ca545c1fca2ec7c2ae923f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 17 Apr 2020 10:46:22 -0700 Subject: [PATCH 2/6] Tweak wording --- src/librustc_resolve/late/diagnostics.rs | 19 +++++++++++-- ...nd-lifetime-in-binding-only.elision.stderr | 2 +- ...und-lifetime-in-return-only.elision.stderr | 2 +- .../async-await/issues/issue-63388-2.stderr | 2 +- src/test/ui/c-variadic/variadic-ffi-6.stderr | 2 +- src/test/ui/foreign-fn-return-lifetime.stderr | 2 +- ...rrect-explicit-lifetime-name-needed.stderr | 14 +++++++++- src/test/ui/issues/issue-13497.stderr | 2 +- src/test/ui/issues/issue-26638.stderr | 4 +-- ...urn-type-requires-explicit-lifetime.stderr | 8 +++--- .../missing-lifetime-specifier.stderr | 28 +++++++++---------- .../return-without-lifetime.stderr | 6 ++-- .../underscore-lifetime-binders.stderr | 4 +-- 13 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 5e03d4e114099..c25a3524dc108 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -1034,6 +1034,8 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { lifetime_names: &FxHashSet, params: &[ElisionFailureInfo], ) { + let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok(); + err.span_label( span, &format!( @@ -1043,11 +1045,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { ), ); - let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok(); let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| { err.span_suggestion_verbose( span, - "consider using the named lifetime", + &format!("consider using the `{}` lifetime", lifetime_names.iter().next().unwrap()), sugg, Applicability::MaybeIncorrect, ); @@ -1137,6 +1138,20 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { (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/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 7608c4a68f1ee..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 @@ -5,7 +5,7 @@ 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 named lifetime +help: consider using the `'static` lifetime | LL | fn elision &'static i32>() { | ^^^^^^^^ 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 2e31a4f3abb2f..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 @@ -5,7 +5,7 @@ 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 named lifetime +help: consider using the `'static` lifetime | LL | fn elision(_: fn() -> &'static i32) { | ^^^^^^^^ 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 74f760d6c9286..ca42263dfed7b 100644 --- a/src/test/ui/async-await/issues/issue-63388-2.stderr +++ b/src/test/ui/async-await/issues/issue-63388-2.stderr @@ -7,7 +7,7 @@ LL | ) -> &dyn Foo | ^ 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 named lifetime +help: consider using the `'a` lifetime | LL | ) -> &'a dyn Foo | ^^^ diff --git a/src/test/ui/c-variadic/variadic-ffi-6.stderr b/src/test/ui/c-variadic/variadic-ffi-6.stderr index 0d491faa9d1e2..4626a4bc2dcff 100644 --- a/src/test/ui/c-variadic/variadic-ffi-6.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-6.stderr @@ -5,7 +5,7 @@ LL | ) -> &usize { | ^ 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 named lifetime +help: consider using the `'static` lifetime | LL | ) -> &'static usize { | ^^^^^^^^ diff --git a/src/test/ui/foreign-fn-return-lifetime.stderr b/src/test/ui/foreign-fn-return-lifetime.stderr index 14153f302da84..feecb6d80e771 100644 --- a/src/test/ui/foreign-fn-return-lifetime.stderr +++ b/src/test/ui/foreign-fn-return-lifetime.stderr @@ -5,7 +5,7 @@ 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 named lifetime +help: consider using the `'static` lifetime | LL | pub fn f() -> &'static u8; | ^^^^^^^^ 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 3c5bdccd96657..321ce7eb34766 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 @@ -9,6 +9,18 @@ error[E0106]: missing lifetime specifier | LL | fn foo<'b, L: X<&'b Nested>>(); | ^ expected named lifetime parameter + | +note: these named lifetimes are available to use + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:12 + | +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:17 @@ -16,7 +28,7 @@ error[E0106]: missing lifetime specifier LL | fn bar<'b, L: X<&'b Nested>>(){} | ^ expected named lifetime parameter | -help: consider using the named lifetime +help: consider using the `'b` lifetime | LL | fn bar<'b, L: X<'b, &'b Nested>>(){} | ^^^ diff --git a/src/test/ui/issues/issue-13497.stderr b/src/test/ui/issues/issue-13497.stderr index 8454c6be61dff..a231f73d06729 100644 --- a/src/test/ui/issues/issue-13497.stderr +++ b/src/test/ui/issues/issue-13497.stderr @@ -5,7 +5,7 @@ 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 named lifetime +help: consider using the `'static` lifetime | LL | &'static str | ^^^^^^^^ diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr index 3049ea772f272..3df58d66d1f8e 100644 --- a/src/test/ui/issues/issue-26638.stderr +++ b/src/test/ui/issues/issue-26638.stderr @@ -17,7 +17,7 @@ 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 with an elided lifetime, but the lifetime cannot be derived from the arguments -help: consider using the named lifetime +help: consider using the `'static` lifetime | LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &'static str { iter() } | ^^^^^^^^ @@ -29,7 +29,7 @@ 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 named lifetime +help: consider using the `'static` lifetime | LL | fn parse_type_3() -> &'static str { unimplemented!() } | ^^^^^^^^ 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 dae1e39018977..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 @@ -5,7 +5,7 @@ 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 named lifetime +help: consider using the `'static` lifetime | LL | fn f() -> &'static isize { | ^^^^^^^^ @@ -41,7 +41,7 @@ LL | fn i(_x: isize) -> &isize { | ^ 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 named lifetime +help: consider using the `'static` lifetime | LL | fn i(_x: isize) -> &'static isize { | ^^^^^^^^ @@ -53,7 +53,7 @@ LL | fn j(_x: StaticStr) -> &isize { | ^ 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 named lifetime +help: consider using the `'static` lifetime | LL | fn j(_x: StaticStr) -> &'static isize { | ^^^^^^^^ @@ -65,7 +65,7 @@ LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize { | ^ 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 named lifetime +help: consider using the `'a` lifetime | LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &'a isize { | ^^^ diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.stderr b/src/test/ui/suggestions/missing-lifetime-specifier.stderr index aeb1229d1746b..6dd81961c4459 100644 --- a/src/test/ui/suggestions/missing-lifetime-specifier.stderr +++ b/src/test/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 named lifetime +help: consider using the `'static` lifetime | LL | static a: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,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 named lifetime +help: consider using the `'static` lifetime | LL | static a: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^^^^^ @@ -29,7 +29,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 named lifetime +help: consider using the `'static` lifetime | LL | static b: RefCell>>> = RefCell::new(HashMap::new()); | ^^^^^^^^ @@ -41,7 +41,7 @@ LL | static b: 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 named lifetime +help: consider using the `'static` lifetime | LL | static b: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^^^^^ @@ -53,7 +53,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 named lifetime +help: consider using the `'static` lifetime | LL | static b: RefCell>>> = RefCell::new(HashMap::new()); | ^^^^^^^^ @@ -65,7 +65,7 @@ LL | static b: 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 named lifetime +help: consider using the `'static` lifetime | LL | static b: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,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 named lifetime +help: consider using the `'static` lifetime | LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ @@ -89,7 +89,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 named lifetime +help: consider using the `'static` lifetime | LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ @@ -101,7 +101,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 named lifetime +help: consider using the `'static` lifetime | LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^ @@ -113,7 +113,7 @@ LL | static d: RefCell>>>> = RefCell::new(Has | ^ 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 named lifetime +help: consider using the `'static` lifetime | LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ @@ -125,7 +125,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 named lifetime +help: consider using the `'static` lifetime | LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^ @@ -137,7 +137,7 @@ LL | static d: RefCell>>>> = RefCell::new(Has | ^ 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 named lifetime +help: consider using the `'static` lifetime | LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ @@ -149,7 +149,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 named lifetime +help: consider using the `'static` lifetime | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^ @@ -161,7 +161,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 named lifetime +help: consider using the `'static` lifetime | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^ diff --git a/src/test/ui/suggestions/return-without-lifetime.stderr b/src/test/ui/suggestions/return-without-lifetime.stderr index a93830edf3eea..2a237d61f50fe 100644 --- a/src/test/ui/suggestions/return-without-lifetime.stderr +++ b/src/test/ui/suggestions/return-without-lifetime.stderr @@ -4,7 +4,7 @@ error[E0106]: missing lifetime specifier LL | struct Foo<'a>(&usize); | ^ expected named lifetime parameter | -help: consider using the named lifetime +help: consider using the `'a` lifetime | LL | struct Foo<'a>(&'a usize); | ^^^ @@ -16,7 +16,7 @@ LL | fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() } | --------- ^ 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 named lifetime +help: consider using the `'a` lifetime | LL | fn func1<'a>(_arg: &'a Thing) -> &'a () { unimplemented!() } | ^^^ @@ -28,7 +28,7 @@ LL | fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() } | ---------- ^ 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 named lifetime +help: consider using the `'a` lifetime | LL | fn func2<'a>(_arg: &Thing<'a>) -> &'a () { unimplemented!() } | ^^^ diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr index ffccd100cb09b..594cdd245b3ec 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -16,7 +16,7 @@ error[E0106]: missing lifetime specifier LL | struct Baz<'a>(&'_ &'a u8); | ^^ expected named lifetime parameter | -help: consider using the named lifetime +help: consider using the `'a` lifetime | LL | struct Baz<'a>(&'a &'a u8); | ^^ @@ -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 named lifetime +help: consider using the `'static` lifetime | LL | fn meh() -> Box Meh<'static>> | ^^^^^^^ From 322b2045f2c0cf3675957c3e6d287abab0da2e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 17 Apr 2020 12:26:32 -0700 Subject: [PATCH 3/6] Revert old span change --- src/librustc_typeck/astconv.rs | 12 +----------- .../ui/suggestions/missing-lifetime-specifier.stderr | 8 ++++---- .../unboxed-closure-feature-gate.stderr | 2 +- .../unboxed-closure-sugar-not-used-on-fn.stderr | 4 ++-- .../unboxed-closure-sugar-region.stderr | 2 +- ...ugar-wrong-number-number-type-parameters-3.stderr | 2 +- src/test/ui/unspecified-self-in-trait-ref.stderr | 2 +- 7 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 51e5a0113c6c6..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(), diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.stderr b/src/test/ui/suggestions/missing-lifetime-specifier.stderr index 6dd81961c4459..f5ff54cc916cb 100644 --- a/src/test/ui/suggestions/missing-lifetime-specifier.stderr +++ b/src/test/ui/suggestions/missing-lifetime-specifier.stderr @@ -218,13 +218,13 @@ 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 + | ^^^^^^^^^^^^^^^^^ 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 + | ^^^^^^^^^^^^^^^^^ 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 @@ -236,7 +236,7 @@ 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 + | ^^^^^^^^^^^^^^^^^ 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 @@ -248,7 +248,7 @@ 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 + | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments error: aborting due to 28 previous errors 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/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 From ad379cd7a63a0e4a8fad5a9acad4b704becbacca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 18 Apr 2020 16:07:29 -0700 Subject: [PATCH 4/6] review comment --- src/librustc_resolve/late/lifetimes.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 41c798f9229e5..d7d141a4c27a3 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -2390,6 +2390,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let mut err = self.report_missing_lifetime_specifiers(span, lifetime_refs.len()); if let Some(params) = error { + // 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")); } @@ -2408,7 +2409,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { &mut self, db: &mut DiagnosticBuilder<'_>, params: &[ElisionFailureInfo], - ) -> bool { + ) -> bool /* add `'static` lifetime to lifetime list */ { let mut m = String::new(); let len = params.len(); From 59c816d58be43acac39930f71da7cc29794a2e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 22 Apr 2020 12:42:02 -0700 Subject: [PATCH 5/6] fix test --- .../issue-65285-incorrect-explicit-lifetime-name-needed.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 321ce7eb34766..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 @@ -11,7 +11,7 @@ LL | fn foo<'b, L: X<&'b Nested>>(); | ^ expected named lifetime parameter | note: these named lifetimes are available to use - --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:12 + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:8:9 | LL | trait X<'a, K: 'a> { | ^^ From 25f8966b5a93dcd4a1f7e06907a63f7547ef2a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 22 Apr 2020 17:15:34 -0700 Subject: [PATCH 6/6] Sort `MultiSpan`s on creation --- src/librustc_span/lib.rs | 3 ++- src/test/ui/specialization/defaultimpl/validation.stderr | 4 ++-- .../ui/traits/negative-impls/negative-default-impls.stderr | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) 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/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/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 {} | ^^^^^^^ ^