From 37097fb4f7cc00ca54b5238bbc4f4af92540aa28 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 21 Apr 2020 21:48:54 -0600 Subject: [PATCH 01/13] Let compiletest recognize gdb 10.x git gdb has moved to version 10. My build prints this as its --version: GNU gdb (GDB) 10.0.50.20200420-git Unfortunately this conflicts with this comment in compiletest: // We limit major to 1 digit, otherwise, on openSUSE, we parse the openSUSE version This patch changes the version parsing to follow the GNU coding standard, which accounts for both the openSUSE case as well as handling gdb 10. My debuginfo test run now says: NOTE: compiletest thinks it is using GDB with native rust support NOTE: compiletest thinks it is using GDB version 10000050 ... where previously it failed to find that gdb 10 had rust support. --- src/tools/compiletest/src/main.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 028483b7d95b5..3a8a5491255a0 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -831,12 +831,28 @@ fn extract_gdb_version(full_version_line: &str) -> Option { // GDB versions look like this: "major.minor.patch?.yyyymmdd?", with both // of the ? sections being optional - // We will parse up to 3 digits for minor and patch, ignoring the date - // We limit major to 1 digit, otherwise, on openSUSE, we parse the openSUSE version + // We will parse up to 3 digits for each component, ignoring the date + + // We skip text in parentheses. This avoids accidentally parsing + // the openSUSE version, which looks like: + // GNU gdb (GDB; openSUSE Leap 15.0) 8.1 + // This particular form is documented in the GNU coding standards: + // https://www.gnu.org/prep/standards/html_node/_002d_002dversion.html#g_t_002d_002dversion // don't start parsing in the middle of a number let mut prev_was_digit = false; + let mut in_parens = false; for (pos, c) in full_version_line.char_indices() { + if in_parens { + if c == ')' { + in_parens = false; + } + continue; + } else if c == '(' { + in_parens = true; + continue; + } + if prev_was_digit || !c.is_digit(10) { prev_was_digit = c.is_digit(10); continue; @@ -876,7 +892,7 @@ fn extract_gdb_version(full_version_line: &str) -> Option { None => (line, None), }; - if major.len() != 1 || minor.is_empty() { + if minor.is_empty() { continue; } From 90b4a97efe2af42bd4e124ede1e802f47f1fbc08 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 22 Apr 2020 08:36:55 -0600 Subject: [PATCH 02/13] Fix compiletest version-parsing tests The compiletest version-parsing tests failed after the previous patch. However, I don't believe these tests are correct, in that I don't think RHEL or CentOS ever put the gdb version number into parentheses. Instead they display like: GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-119.el7 --- src/tools/compiletest/src/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/tests.rs b/src/tools/compiletest/src/tests.rs index 388ad75757f61..31c151d29e916 100644 --- a/src/tools/compiletest/src/tests.rs +++ b/src/tools/compiletest/src/tests.rs @@ -7,9 +7,9 @@ fn test_extract_gdb_version() { )*}}} test! { - 7000001: "GNU gdb (GDB) CentOS (7.0.1-45.el5.centos)", + 7000001: "GNU gdb (GDB) CentOS 7.0.1-45.el5.centos", - 7002000: "GNU gdb (GDB) Red Hat Enterprise Linux (7.2-90.el6)", + 7002000: "GNU gdb (GDB) Red Hat Enterprise Linux 7.2-90.el6", 7004000: "GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04", 7004001: "GNU gdb (GDB) 7.4.1-debian", 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 03/13] 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 04/13] 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 05/13] 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 06/13] 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 07/13] 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 08/13] 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 {} | ^^^^^^^ ^ From 90f11310224e9e2d5a27e3e4b8c5b1aaa1c0b980 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 23 Apr 2020 19:40:41 +0200 Subject: [PATCH 09/13] Miri Frame: use mir::Location to represent position in function --- src/librustc_mir/interpret/eval_context.rs | 50 +++++++++------------- src/librustc_mir/interpret/step.rs | 16 +++---- src/librustc_mir/interpret/terminator.rs | 4 +- 3 files changed, 29 insertions(+), 41 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index ae4ad49fe667f..02fce7dfb43c2 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -81,14 +81,9 @@ pub struct Frame<'mir, 'tcx, Tag = (), Extra = ()> { //////////////////////////////////////////////////////////////////////////////// // Current position within the function //////////////////////////////////////////////////////////////////////////////// - /// The block that is currently executed (or will be executed after the above call stacks - /// return). /// If this is `None`, we are unwinding and this function doesn't need any clean-up. /// Just continue the same as with `Resume`. - pub block: Option, - - /// The index of the currently evaluated statement. - pub stmt: usize, + pub loc: Option, } #[derive(Clone, Eq, PartialEq, Debug, HashStable)] // Miri debug-prints these @@ -168,8 +163,7 @@ impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> { return_to_block: self.return_to_block, return_place: self.return_place, locals: self.locals, - block: self.block, - stmt: self.stmt, + loc: self.loc, extra, } } @@ -178,10 +172,10 @@ impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> { impl<'mir, 'tcx, Tag, Extra> Frame<'mir, 'tcx, Tag, Extra> { /// Return the `SourceInfo` of the current instruction. pub fn current_source_info(&self) -> Option { - self.block.map(|block| { - let block = &self.body.basic_blocks()[block]; - if self.stmt < block.statements.len() { - block.statements[self.stmt].source_info + self.loc.map(|loc| { + let block = &self.body.basic_blocks()[loc.block]; + if loc.statement_index < block.statements.len() { + block.statements[loc.statement_index].source_info } else { block.terminator().source_info } @@ -615,14 +609,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // first push a stack frame so we have access to the local substs let pre_frame = Frame { body, - block: Some(mir::START_BLOCK), + loc: Some(mir::Location::START), return_to_block, return_place, // empty local array, we fill it in below, after we are inside the stack frame and // all methods actually know about the frame locals: IndexVec::new(), instance, - stmt: 0, extra: (), }; let frame = M::init_frame_extra(self, pre_frame)?; @@ -671,9 +664,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Jump to the given block. #[inline] pub fn go_to_block(&mut self, target: mir::BasicBlock) { - let frame = self.frame_mut(); - frame.block = Some(target); - frame.stmt = 0; + self.frame_mut().loc = Some(mir::Location { block: target, statement_index: 0 }); } /// *Return* to the given `target` basic block. @@ -695,9 +686,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// If `target` is `None`, that indicates the function does not need cleanup during /// unwinding, and we will just keep propagating that upwards. pub fn unwind_to_block(&mut self, target: Option) { - let frame = self.frame_mut(); - frame.block = target; - frame.stmt = 0; + self.frame_mut().loc = target.map(|block| mir::Location { block, statement_index: 0 }); } /// Pops the current frame from the stack, deallocating the @@ -724,9 +713,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Sanity check `unwinding`. assert_eq!( unwinding, - match self.frame().block { + match self.frame().loc { None => true, - Some(block) => self.body().basic_blocks()[block].is_cleanup, + Some(loc) => self.body().basic_blocks()[loc.block].is_cleanup, } ); @@ -987,13 +976,14 @@ where Tag: HashStable>, { fn hash_stable(&self, hcx: &mut StableHashingContext<'ctx>, hasher: &mut StableHasher) { - self.body.hash_stable(hcx, hasher); - self.instance.hash_stable(hcx, hasher); - self.return_to_block.hash_stable(hcx, hasher); - self.return_place.as_ref().map(|r| &**r).hash_stable(hcx, hasher); - self.locals.hash_stable(hcx, hasher); - self.block.hash_stable(hcx, hasher); - self.stmt.hash_stable(hcx, hasher); - self.extra.hash_stable(hcx, hasher); + // Exhaustive match on fields to make sure we forget no field. + let Frame { body, instance, return_to_block, return_place, locals, loc, extra } = self; + body.hash_stable(hcx, hasher); + instance.hash_stable(hcx, hasher); + return_to_block.hash_stable(hcx, hasher); + return_place.as_ref().map(|r| &**r).hash_stable(hcx, hasher); + locals.hash_stable(hcx, hasher); + loc.hash_stable(hcx, hasher); + extra.hash_stable(hcx, hasher); } } diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index aae708827b953..bb4c0156c88cf 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -46,8 +46,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(false); } - let block = match self.frame().block { - Some(block) => block, + let loc = match self.frame().loc { + Some(loc) => loc, None => { // We are unwinding and this fn has no cleanup code. // Just go on unwinding. @@ -56,13 +56,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(true); } }; - let stmt_id = self.frame().stmt; - let body = self.body(); - let basic_block = &body.basic_blocks()[block]; + let basic_block = &self.body().basic_blocks()[loc.block]; let old_frames = self.frame_idx(); - if let Some(stmt) = basic_block.statements.get(stmt_id) { + if let Some(stmt) = basic_block.statements.get(loc.statement_index) { assert_eq!(old_frames, self.frame_idx()); self.statement(stmt)?; return Ok(true); @@ -126,7 +124,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { LlvmInlineAsm { .. } => throw_unsup_format!("inline assembly is not supported"), } - self.stack_mut()[frame_idx].stmt += 1; + self.stack_mut()[frame_idx].loc.as_mut().unwrap().statement_index += 1; Ok(()) } @@ -279,8 +277,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.eval_terminator(terminator)?; if !self.stack().is_empty() { - if let Some(block) = self.frame().block { - info!("// executing {:?}", block); + if let Some(loc) = self.frame().loc { + info!("// executing {:?}", loc.block); } } Ok(()) diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 7157225e5c9bb..6ead962dcd869 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -53,7 +53,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Call { ref func, ref args, destination, ref cleanup, .. } => { let old_stack = self.frame_idx(); - let old_bb = self.frame().block; + let old_loc = self.frame().loc; let func = self.eval_operand(func, None)?; let (fn_val, abi) = match func.layout.ty.kind { ty::FnPtr(sig) => { @@ -80,7 +80,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.eval_fn_call(fn_val, abi, &args[..], ret, *cleanup)?; // Sanity-check that `eval_fn_call` either pushed a new frame or // did a jump to another block. - if self.frame_idx() == old_stack && self.frame().block == old_bb { + if self.frame_idx() == old_stack && self.frame().loc == old_loc { span_bug!(terminator.source_info.span, "evaluating this call made no progress"); } } From f1c30519f30e4c245e2b319fbb257ba2c59e8092 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 23 Apr 2020 19:48:35 +0200 Subject: [PATCH 10/13] libcore: more compact way to adjust test sizes for Miri --- src/libcore/tests/num/flt2dec/estimator.rs | 8 +++---- src/libcore/tests/num/flt2dec/random.rs | 26 +++++++++------------- src/libcore/tests/slice.rs | 12 +++------- 3 files changed, 16 insertions(+), 30 deletions(-) diff --git a/src/libcore/tests/num/flt2dec/estimator.rs b/src/libcore/tests/num/flt2dec/estimator.rs index 8ee06d895cae3..da203b5f3620e 100644 --- a/src/libcore/tests/num/flt2dec/estimator.rs +++ b/src/libcore/tests/num/flt2dec/estimator.rs @@ -52,12 +52,10 @@ fn test_estimate_scaling_factor() { assert_almost_eq!(estimate_scaling_factor(1, -1074), -323); assert_almost_eq!(estimate_scaling_factor(0x1fffffffffffff, 971), 309); - #[cfg(not(miri))] // Miri is too slow - let iter = -1074..972; - #[cfg(miri)] - let iter = (-1074..972).step_by(37); + // Miri is too slow + let step = if cfg!(miri) { 37 } else { 1 }; - for i in iter { + for i in (-1074..972).step_by(step) { let expected = super::ldexp_f64(1.0, i).log10().ceil(); assert_almost_eq!(estimate_scaling_factor(1, i as i16), expected as i16); } diff --git a/src/libcore/tests/num/flt2dec/random.rs b/src/libcore/tests/num/flt2dec/random.rs index 5b050a2c35631..0ebc0881f5223 100644 --- a/src/libcore/tests/num/flt2dec/random.rs +++ b/src/libcore/tests/num/flt2dec/random.rs @@ -138,13 +138,11 @@ where #[test] fn shortest_random_equivalence_test() { use core::num::flt2dec::strategy::dragon::format_shortest as fallback; - #[cfg(not(miri))] // Miri is too slow - const N: usize = 10_000; - #[cfg(miri)] - const N: usize = 10; + // Miri is too slow + let n = if cfg!(miri) { 10 } else { 10_000 }; - f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, N); - f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, N); + f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, n); + f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, n); } #[test] @@ -173,17 +171,15 @@ fn shortest_f64_hard_random_equivalence_test() { #[test] fn exact_f32_random_equivalence_test() { use core::num::flt2dec::strategy::dragon::format_exact as fallback; - #[cfg(not(miri))] // Miri is too slow - const N: usize = 1_000; - #[cfg(miri)] - const N: usize = 3; + // Miri is too slow + let n = if cfg!(miri) { 3 } else { 1_000 }; for k in 1..21 { f32_random_equivalence_test( |d, buf| format_exact_opt(d, buf, i16::MIN), |d, buf| fallback(d, buf, i16::MIN), k, - N, + n, ); } } @@ -191,17 +187,15 @@ fn exact_f32_random_equivalence_test() { #[test] fn exact_f64_random_equivalence_test() { use core::num::flt2dec::strategy::dragon::format_exact as fallback; - #[cfg(not(miri))] // Miri is too slow - const N: usize = 1_000; - #[cfg(miri)] - const N: usize = 3; + // Miri is too slow + let n = if cfg!(miri) { 3 } else { 1_000 }; for k in 1..21 { f64_random_equivalence_test( |d, buf| format_exact_opt(d, buf, i16::MIN), |d, buf| fallback(d, buf, i16::MIN), k, - N, + n, ); } } diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 9b9420cc13f85..54a585415bce2 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -1227,15 +1227,9 @@ fn sort_unstable() { use core::slice::heapsort; use rand::{rngs::StdRng, seq::SliceRandom, Rng, SeedableRng}; - #[cfg(not(miri))] // Miri is too slow - let large_range = 500..510; - #[cfg(not(miri))] // Miri is too slow - let rounds = 100; - - #[cfg(miri)] - let large_range = 0..0; // empty range - #[cfg(miri)] - let rounds = 1; + // Miri is too slow + let large_range = if cfg!(miri) { 0..0 } else { 500..510 }; + let rounds = if cfg!(miri) { 1 } else { 100 }; let mut v = [0; 600]; let mut tmp = [0; 600]; From eb1de2ff39de631e9fd880f1e066fbe119b23f99 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 23 Apr 2020 20:05:01 +0200 Subject: [PATCH 11/13] liballoc: more compact way to adjust test sizes for Miri --- src/liballoc/collections/vec_deque/tests.rs | 6 +-- src/liballoc/tests/binary_heap.rs | 8 ++-- src/liballoc/tests/btree/map.rs | 48 +++++++-------------- src/liballoc/tests/btree/set.rs | 6 +-- src/liballoc/tests/slice.rs | 24 +++-------- src/liballoc/tests/vec_deque.rs | 14 +++--- 6 files changed, 35 insertions(+), 71 deletions(-) diff --git a/src/liballoc/collections/vec_deque/tests.rs b/src/liballoc/collections/vec_deque/tests.rs index 8ef5ec78e056e..0a3f33003233f 100644 --- a/src/liballoc/collections/vec_deque/tests.rs +++ b/src/liballoc/collections/vec_deque/tests.rs @@ -386,10 +386,8 @@ fn test_vec_from_vecdeque() { assert!(vec.into_iter().eq(vd)); } - #[cfg(not(miri))] // Miri is too slow - let max_pwr = 7; - #[cfg(miri)] - let max_pwr = 5; + // Miri is too slow + let max_pwr = if cfg!(miri) { 5 } else { 7 }; for cap_pwr in 0..max_pwr { // Make capacity as a (2^x)-1, so that the ring size is 2^x diff --git a/src/liballoc/tests/binary_heap.rs b/src/liballoc/tests/binary_heap.rs index be5516f54f37b..057afd41824e7 100644 --- a/src/liballoc/tests/binary_heap.rs +++ b/src/liballoc/tests/binary_heap.rs @@ -409,16 +409,14 @@ fn panic_safe() { } let mut rng = thread_rng(); const DATASZ: usize = 32; - #[cfg(not(miri))] // Miri is too slow - const NTEST: usize = 10; - #[cfg(miri)] - const NTEST: usize = 1; + // Miri is too slow + let ntest = if cfg!(miri) { 1 } else { 10 }; // don't use 0 in the data -- we want to catch the zeroed-out case. let data = (1..=DATASZ).collect::>(); // since it's a fuzzy test, run several tries. - for _ in 0..NTEST { + for _ in 0..ntest { for i in 1..=DATASZ { DROP_COUNTER.store(0, Ordering::SeqCst); diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index 96b6c32a1fa8e..731a1b5f875b7 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -28,10 +28,8 @@ const MIN_INSERTS_HEIGHT_2: usize = NODE_CAPACITY + (NODE_CAPACITY + 1) * NODE_C #[test] fn test_basic_large() { let mut map = BTreeMap::new(); - #[cfg(not(miri))] // Miri is too slow - let size = 10000; - #[cfg(miri)] - let size = MIN_INSERTS_HEIGHT_2; + // Miri is too slow + let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 } else { 10000 }; assert_eq!(map.len(), 0); for i in 0..size { @@ -155,10 +153,8 @@ fn test_basic_small() { #[test] fn test_iter() { - #[cfg(not(miri))] // Miri is too slow - let size = 10000; - #[cfg(miri)] - let size = 200; + // Miri is too slow + let size = if cfg!(miri) { 200 } else { 10000 }; let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); @@ -180,10 +176,8 @@ fn test_iter() { #[test] fn test_iter_rev() { - #[cfg(not(miri))] // Miri is too slow - let size = 10000; - #[cfg(miri)] - let size = 200; + // Miri is too slow + let size = if cfg!(miri) { 200 } else { 10000 }; let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); @@ -289,10 +283,8 @@ fn test_values_mut() { #[test] fn test_iter_mixed() { - #[cfg(not(miri))] // Miri is too slow - let size = 10000; - #[cfg(miri)] - let size = 200; + // Miri is too slow + let size = if cfg!(miri) { 200 } else { 10000 }; let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); @@ -525,10 +517,8 @@ fn test_range_backwards_4() { #[test] fn test_range_1000() { - #[cfg(not(miri))] // Miri is too slow - let size = 1000; - #[cfg(miri)] - let size = MIN_INSERTS_HEIGHT_2 as u32; + // Miri is too slow + let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 as u32 } else { 1000 }; let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); fn test(map: &BTreeMap, size: u32, min: Bound<&u32>, max: Bound<&u32>) { @@ -566,10 +556,8 @@ fn test_range_borrowed_key() { #[test] fn test_range() { let size = 200; - #[cfg(not(miri))] // Miri is too slow - let step = 1; - #[cfg(miri)] - let step = 66; + // Miri is too slow + let step = if cfg!(miri) { 66 } else { 1 }; let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); for i in (0..size).step_by(step) { @@ -589,10 +577,8 @@ fn test_range() { #[test] fn test_range_mut() { let size = 200; - #[cfg(not(miri))] // Miri is too slow - let step = 1; - #[cfg(miri)] - let step = 66; + // Miri is too slow + let step = if cfg!(miri) { 66 } else { 1 }; let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); for i in (0..size).step_by(step) { @@ -1263,10 +1249,8 @@ fn test_split_off_empty_left() { #[test] fn test_split_off_large_random_sorted() { - #[cfg(not(miri))] // Miri is too slow - let mut data = rand_data(1529); - #[cfg(miri)] - let mut data = rand_data(529); + // Miri is too slow + let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) }; // special case with maximum height. data.sort(); diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs index 136018b9f7df5..75251ca0d51e9 100644 --- a/src/liballoc/tests/btree/set.rs +++ b/src/liballoc/tests/btree/set.rs @@ -621,10 +621,8 @@ fn test_split_off_empty_left() { #[test] fn test_split_off_large_random_sorted() { - #[cfg(not(miri))] // Miri is too slow - let mut data = rand_data(1529); - #[cfg(miri)] - let mut data = rand_data(529); + // Miri is too slow + let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) }; // special case with maximum height. data.sort(); diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index 8e49e6d8ebad9..75b76bb73ed9e 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -463,15 +463,9 @@ fn test_sort() { #[test] fn test_sort_stability() { - #[cfg(not(miri))] // Miri is too slow - let large_range = 500..510; - #[cfg(not(miri))] // Miri is too slow - let rounds = 10; - - #[cfg(miri)] - let large_range = 0..0; // empty range - #[cfg(miri)] - let rounds = 1; + // Miri is too slow + let large_range = if cfg!(miri) { 0..0 } else { 500..510 }; + let rounds = if cfg!(miri) { 1 } else { 10 }; for len in (2..25).chain(large_range) { for _ in 0..rounds { @@ -1727,15 +1721,9 @@ fn panic_safe() { let mut rng = thread_rng(); - #[cfg(not(miri))] // Miri is too slow - let lens = (1..20).chain(70..MAX_LEN); - #[cfg(not(miri))] // Miri is too slow - let moduli = &[5, 20, 50]; - - #[cfg(miri)] - let lens = 1..10; - #[cfg(miri)] - let moduli = &[5]; + // Miri is too slow + let lens = if cfg!(miri) { (1..10).chain(20..21) } else { (1..20).chain(70..MAX_LEN) }; + let moduli: &[u32] = if cfg!(miri) { &[5] } else { &[5, 20, 50] }; for len in lens { for &modulus in moduli { diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index c4b6a36bb0541..762dc4be44d62 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -954,16 +954,14 @@ fn test_append_permutations() { out } - #[cfg(not(miri))] // Miri is too slow - const MAX: usize = 5; - #[cfg(miri)] - const MAX: usize = 3; + // Miri is too slow + let max = if cfg!(miri) { 3 } else { 5 }; // Many different permutations of both the `VecDeque` getting appended to // and the one getting appended are generated to check `append`. // This ensures all 6 code paths of `append` are tested. - for src_push_back in 0..MAX { - for src_push_front in 0..MAX { + for src_push_back in 0..max { + for src_push_front in 0..max { // doesn't pop more values than are pushed for src_pop_back in 0..(src_push_back + src_push_front) { for src_pop_front in 0..(src_push_back + src_push_front - src_pop_back) { @@ -974,8 +972,8 @@ fn test_append_permutations() { src_pop_front, ); - for dst_push_back in 0..MAX { - for dst_push_front in 0..MAX { + for dst_push_back in 0..max { + for dst_push_front in 0..max { for dst_pop_back in 0..(dst_push_back + dst_push_front) { for dst_pop_front in 0..(dst_push_back + dst_push_front - dst_pop_back) From 6463ecfe766c60c6dd671725f0ac52e88004f6c9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 19 Apr 2020 12:32:21 +0200 Subject: [PATCH 12/13] miri-unleash tests: ensure they fire even with 'allow(const_err)' --- .../ui/consts/miri_unleashed/abi-mismatch.rs | 9 +- .../consts/miri_unleashed/abi-mismatch.stderr | 22 ++--- src/test/ui/consts/miri_unleashed/box.rs | 2 +- .../miri_unleashed/const_refers_to_static.rs | 30 +++--- .../const_refers_to_static.stderr | 91 ++++--------------- .../miri_unleashed/const_refers_to_static2.rs | 24 +++++ .../const_refers_to_static2.stderr | 39 ++++++++ src/test/ui/consts/miri_unleashed/drop.rs | 2 +- .../ui/consts/miri_unleashed/mutable_const.rs | 2 +- .../miri_unleashed/mutable_const.stderr | 2 +- .../consts/miri_unleashed/mutable_const2.rs | 2 +- .../consts/miri_unleashed/mutating_global.rs | 9 +- .../miri_unleashed/mutating_global.stderr | 30 +----- .../ui/consts/miri_unleashed/non_const_fn.rs | 14 +-- .../consts/miri_unleashed/non_const_fn.stderr | 36 ++------ 15 files changed, 140 insertions(+), 174 deletions(-) create mode 100644 src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs create mode 100644 src/test/ui/consts/miri_unleashed/const_refers_to_static2.stderr diff --git a/src/test/ui/consts/miri_unleashed/abi-mismatch.rs b/src/test/ui/consts/miri_unleashed/abi-mismatch.rs index d8e63b0bfb24e..a99e6327987f0 100644 --- a/src/test/ui/consts/miri_unleashed/abi-mismatch.rs +++ b/src/test/ui/consts/miri_unleashed/abi-mismatch.rs @@ -2,15 +2,20 @@ // compile-flags: -Z unleash-the-miri-inside-of-you #![feature(const_extern_fn)] +#![allow(const_err)] const extern "C" fn c_fn() {} const fn call_rust_fn(my_fn: extern "Rust" fn()) { - my_fn(); //~ ERROR any use of this value will cause an error + my_fn(); //~^ WARN skipping const checks + //~| ERROR could not evaluate static initializer + //~| NOTE calling a function with ABI C using caller ABI Rust + //~| NOTE inside `call_rust_fn` } -const VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) }); +static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) }); //~^ WARN skipping const checks +//~| NOTE inside `VAL` fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr index dba00d72ef036..674a293d2815e 100644 --- a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr +++ b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr @@ -1,29 +1,27 @@ warning: skipping const checks - --> $DIR/abi-mismatch.rs:9:5 + --> $DIR/abi-mismatch.rs:10:5 | LL | my_fn(); | ^^^^^^^ warning: skipping const checks - --> $DIR/abi-mismatch.rs:13:39 + --> $DIR/abi-mismatch.rs:17:40 | -LL | const VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: any use of this value will cause an error - --> $DIR/abi-mismatch.rs:9:5 +error[E0080]: could not evaluate static initializer + --> $DIR/abi-mismatch.rs:10:5 | LL | my_fn(); | ^^^^^^^ | | | calling a function with ABI C using caller ABI Rust - | inside `call_rust_fn` at $DIR/abi-mismatch.rs:9:5 - | inside `VAL` at $DIR/abi-mismatch.rs:13:17 + | inside `call_rust_fn` at $DIR/abi-mismatch.rs:10:5 ... -LL | const VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) }); - | -------------------------------------------------------------------------------------- - | - = note: `#[deny(const_err)]` on by default +LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) }); + | --------------------------------------------------------------------- inside `VAL` at $DIR/abi-mismatch.rs:17:18 error: aborting due to previous error; 2 warnings emitted +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/miri_unleashed/box.rs b/src/test/ui/consts/miri_unleashed/box.rs index 049727684d0eb..1b18470eded42 100644 --- a/src/test/ui/consts/miri_unleashed/box.rs +++ b/src/test/ui/consts/miri_unleashed/box.rs @@ -1,6 +1,6 @@ // compile-flags: -Zunleash-the-miri-inside-of-you #![feature(const_mut_refs, box_syntax)] -#![deny(const_err)] +#![allow(const_err)] use std::mem::ManuallyDrop; diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs index edbf0e02d8de2..11f4a30d1779b 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs @@ -1,39 +1,37 @@ +// build-fail // compile-flags: -Zunleash-the-miri-inside-of-you -#![warn(const_err)] +#![allow(const_err)] #![feature(const_raw_ptr_deref)] use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; -const REF_INTERIOR_MUT: &usize = { //~ ERROR undefined behavior to use this value - static FOO: AtomicUsize = AtomicUsize::new(0); - unsafe { &*(&FOO as *const _ as *const usize) } - //~^ WARN skipping const checks -}; +// These tests only cause an error when *using* the const. const MUTATE_INTERIOR_MUT: usize = { static FOO: AtomicUsize = AtomicUsize::new(0); - FOO.fetch_add(1, Ordering::Relaxed) //~ WARN any use of this value will cause an error + FOO.fetch_add(1, Ordering::Relaxed) //~^ WARN skipping const checks //~| WARN skipping const checks }; const READ_INTERIOR_MUT: usize = { static FOO: AtomicUsize = AtomicUsize::new(0); - unsafe { *(&FOO as *const _ as *const usize) } //~ WARN any use of this value will cause an err + unsafe { *(&FOO as *const _ as *const usize) } //~^ WARN skipping const checks }; static mut MUTABLE: u32 = 0; -const READ_MUT: u32 = unsafe { MUTABLE }; //~ WARN any use of this value will cause an error +const READ_MUT: u32 = unsafe { MUTABLE }; //~^ WARN skipping const checks //~| WARN skipping const checks -// ok some day perhaps -const READ_IMMUT: &usize = { //~ ERROR it is undefined behavior to use this value - static FOO: usize = 0; - &FOO - //~^ WARN skipping const checks -}; -fn main() {} +fn main() { + MUTATE_INTERIOR_MUT; + //~^ ERROR: erroneous constant used + READ_INTERIOR_MUT; + //~^ ERROR: erroneous constant used + READ_MUT; + //~^ ERROR: erroneous constant used +} diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr index 92e782612b253..788762808f13b 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr @@ -1,106 +1,51 @@ warning: skipping const checks - --> $DIR/const_refers_to_static.rs:11:18 - | -LL | unsafe { &*(&FOO as *const _ as *const usize) } - | ^^^ - -warning: skipping const checks - --> $DIR/const_refers_to_static.rs:17:5 + --> $DIR/const_refers_to_static.rs:14:5 | LL | FOO.fetch_add(1, Ordering::Relaxed) | ^^^ warning: skipping const checks - --> $DIR/const_refers_to_static.rs:17:5 + --> $DIR/const_refers_to_static.rs:14:5 | LL | FOO.fetch_add(1, Ordering::Relaxed) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: skipping const checks - --> $DIR/const_refers_to_static.rs:24:17 + --> $DIR/const_refers_to_static.rs:21:17 | LL | unsafe { *(&FOO as *const _ as *const usize) } | ^^^ warning: skipping const checks - --> $DIR/const_refers_to_static.rs:29:32 + --> $DIR/const_refers_to_static.rs:26:32 | LL | const READ_MUT: u32 = unsafe { MUTABLE }; | ^^^^^^^ warning: skipping const checks - --> $DIR/const_refers_to_static.rs:29:32 + --> $DIR/const_refers_to_static.rs:26:32 | LL | const READ_MUT: u32 = unsafe { MUTABLE }; | ^^^^^^^ -warning: skipping const checks - --> $DIR/const_refers_to_static.rs:36:6 +error[E0080]: erroneous constant used + --> $DIR/const_refers_to_static.rs:31:5 | -LL | &FOO - | ^^^ +LL | MUTATE_INTERIOR_MUT; + | ^^^^^^^^^^^^^^^^^^^ referenced constant has errors -error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static.rs:9:1 +error[E0080]: erroneous constant used + --> $DIR/const_refers_to_static.rs:33:5 | -LL | / const REF_INTERIOR_MUT: &usize = { -LL | | static FOO: AtomicUsize = AtomicUsize::new(0); -LL | | unsafe { &*(&FOO as *const _ as *const usize) } -LL | | -LL | | }; - | |__^ type validation failed: encountered a reference pointing to a static variable - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. +LL | READ_INTERIOR_MUT; + | ^^^^^^^^^^^^^^^^^ referenced constant has errors -warning: any use of this value will cause an error - --> $DIR/const_refers_to_static.rs:17:5 - | -LL | / const MUTATE_INTERIOR_MUT: usize = { -LL | | static FOO: AtomicUsize = AtomicUsize::new(0); -LL | | FOO.fetch_add(1, Ordering::Relaxed) - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `std::sync::atomic::AtomicUsize::fetch_add` -LL | | -LL | | -LL | | }; - | |__- - | -note: the lint level is defined here - --> $DIR/const_refers_to_static.rs:2:9 - | -LL | #![warn(const_err)] - | ^^^^^^^^^ - -warning: any use of this value will cause an error - --> $DIR/const_refers_to_static.rs:24:14 - | -LL | / const READ_INTERIOR_MUT: usize = { -LL | | static FOO: AtomicUsize = AtomicUsize::new(0); -LL | | unsafe { *(&FOO as *const _ as *const usize) } - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static -LL | | -LL | | }; - | |__- - -warning: any use of this value will cause an error - --> $DIR/const_refers_to_static.rs:29:32 - | -LL | const READ_MUT: u32 = unsafe { MUTABLE }; - | -------------------------------^^^^^^^--- - | | - | constant accesses static - -error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static.rs:34:1 - | -LL | / const READ_IMMUT: &usize = { -LL | | static FOO: usize = 0; -LL | | &FOO -LL | | -LL | | }; - | |__^ type validation failed: encountered a reference pointing to a static variable +error[E0080]: erroneous constant used + --> $DIR/const_refers_to_static.rs:35:5 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. +LL | READ_MUT; + | ^^^^^^^^ referenced constant has errors -error: aborting due to 2 previous errors; 10 warnings emitted +error: aborting due to 3 previous errors; 5 warnings emitted For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs new file mode 100644 index 0000000000000..2704f2a7d73c1 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs @@ -0,0 +1,24 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +#![allow(const_err)] + +#![feature(const_raw_ptr_deref)] + +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering; + +// These tests cause immediate error when *defining* the const. + +const REF_INTERIOR_MUT: &usize = { //~ ERROR undefined behavior to use this value + static FOO: AtomicUsize = AtomicUsize::new(0); + unsafe { &*(&FOO as *const _ as *const usize) } + //~^ WARN skipping const checks +}; + +// ok some day perhaps +const READ_IMMUT: &usize = { //~ ERROR it is undefined behavior to use this value + static FOO: usize = 0; + &FOO + //~^ WARN skipping const checks +}; + +fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.stderr new file mode 100644 index 0000000000000..2a233d63efef8 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.stderr @@ -0,0 +1,39 @@ +warning: skipping const checks + --> $DIR/const_refers_to_static2.rs:13:18 + | +LL | unsafe { &*(&FOO as *const _ as *const usize) } + | ^^^ + +warning: skipping const checks + --> $DIR/const_refers_to_static2.rs:20:6 + | +LL | &FOO + | ^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static2.rs:11:1 + | +LL | / const REF_INTERIOR_MUT: &usize = { +LL | | static FOO: AtomicUsize = AtomicUsize::new(0); +LL | | unsafe { &*(&FOO as *const _ as *const usize) } +LL | | +LL | | }; + | |__^ type validation failed: encountered a reference pointing to a static variable + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static2.rs:18:1 + | +LL | / const READ_IMMUT: &usize = { +LL | | static FOO: usize = 0; +LL | | &FOO +LL | | +LL | | }; + | |__^ type validation failed: encountered a reference pointing to a static variable + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error: aborting due to 2 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/miri_unleashed/drop.rs b/src/test/ui/consts/miri_unleashed/drop.rs index 2f39148d6972f..3b9208dd12609 100644 --- a/src/test/ui/consts/miri_unleashed/drop.rs +++ b/src/test/ui/consts/miri_unleashed/drop.rs @@ -1,6 +1,6 @@ // compile-flags: -Zunleash-the-miri-inside-of-you // error-pattern: calling non-const function ` as std::ops::Drop>::drop` -#![deny(const_err)] +#![allow(const_err)] use std::mem::ManuallyDrop; diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.rs b/src/test/ui/consts/miri_unleashed/mutable_const.rs index 972f59549ea74..5866f8b4f246f 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_const.rs +++ b/src/test/ui/consts/miri_unleashed/mutable_const.rs @@ -2,7 +2,7 @@ #![feature(const_raw_ptr_deref)] #![feature(const_mut_refs)] -#![deny(const_err)] +#![deny(const_err)] // FIXME: ICEs with allow! See #71316. use std::cell::UnsafeCell; diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.stderr b/src/test/ui/consts/miri_unleashed/mutable_const.stderr index 54a9eda214660..514c103263f35 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_const.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_const.stderr @@ -19,7 +19,7 @@ LL | | }; note: the lint level is defined here --> $DIR/mutable_const.rs:5:9 | -LL | #![deny(const_err)] +LL | #![deny(const_err)] // FIXME: ICEs with allow! See #71316. | ^^^^^^^^^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.rs b/src/test/ui/consts/miri_unleashed/mutable_const2.rs index 97af1f2f993c3..c5b880ba30920 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_const2.rs +++ b/src/test/ui/consts/miri_unleashed/mutable_const2.rs @@ -7,7 +7,7 @@ #![feature(const_raw_ptr_deref)] #![feature(const_mut_refs)] -#![deny(const_err)] +#![allow(const_err)] use std::cell::UnsafeCell; diff --git a/src/test/ui/consts/miri_unleashed/mutating_global.rs b/src/test/ui/consts/miri_unleashed/mutating_global.rs index acc6fb026cd69..902fe0aa1e7e4 100644 --- a/src/test/ui/consts/miri_unleashed/mutating_global.rs +++ b/src/test/ui/consts/miri_unleashed/mutating_global.rs @@ -1,14 +1,15 @@ // compile-flags: -Zunleash-the-miri-inside-of-you +#![allow(const_err)] // Make sure we cannot mutate globals. static mut GLOBAL: i32 = 0; -const MUTATING_GLOBAL: () = { +static MUTATING_GLOBAL: () = { unsafe { - GLOBAL = 99 //~ ERROR any use of this value will cause an error - //~^ WARN skipping const checks - //~| WARN skipping const checks + GLOBAL = 99 + //~^ ERROR could not evaluate static initializer + //~| NOTE modifying a static's initial value } }; diff --git a/src/test/ui/consts/miri_unleashed/mutating_global.stderr b/src/test/ui/consts/miri_unleashed/mutating_global.stderr index dd449d5da35ef..ba9dd56190ac1 100644 --- a/src/test/ui/consts/miri_unleashed/mutating_global.stderr +++ b/src/test/ui/consts/miri_unleashed/mutating_global.stderr @@ -1,29 +1,9 @@ -warning: skipping const checks - --> $DIR/mutating_global.rs:9:9 +error[E0080]: could not evaluate static initializer + --> $DIR/mutating_global.rs:10:9 | LL | GLOBAL = 99 - | ^^^^^^ + | ^^^^^^^^^^^ modifying a static's initial value from another static's initializer -warning: skipping const checks - --> $DIR/mutating_global.rs:9:9 - | -LL | GLOBAL = 99 - | ^^^^^^ - -error: any use of this value will cause an error - --> $DIR/mutating_global.rs:9:9 - | -LL | / const MUTATING_GLOBAL: () = { -LL | | unsafe { -LL | | GLOBAL = 99 - | | ^^^^^^^^^^^ modifying a static's initial value from another static's initializer -LL | | -LL | | -LL | | } -LL | | }; - | |__- - | - = note: `#[deny(const_err)]` on by default - -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/miri_unleashed/non_const_fn.rs b/src/test/ui/consts/miri_unleashed/non_const_fn.rs index cfb57d21ceec5..b401884139d9f 100644 --- a/src/test/ui/consts/miri_unleashed/non_const_fn.rs +++ b/src/test/ui/consts/miri_unleashed/non_const_fn.rs @@ -1,17 +1,13 @@ -// build-fail // compile-flags: -Zunleash-the-miri-inside-of-you -#![warn(const_err)] +#![allow(const_err)] // A test demonstrating that we prevent calling non-const fn during CTFE. fn foo() {} -const C: () = foo(); //~ WARN: skipping const checks -//~^ WARN any use of this value will cause an error +static C: () = foo(); //~ WARN: skipping const checks +//~^ ERROR could not evaluate static initializer +//~| NOTE calling non-const function `foo` -fn main() { - println!("{:?}", C); - //~^ ERROR: evaluation of constant expression failed - //~| WARN: erroneous constant used [const_err] -} +fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/non_const_fn.stderr b/src/test/ui/consts/miri_unleashed/non_const_fn.stderr index cc31c41164fe5..d20cd6d6f0b9e 100644 --- a/src/test/ui/consts/miri_unleashed/non_const_fn.stderr +++ b/src/test/ui/consts/miri_unleashed/non_const_fn.stderr @@ -1,35 +1,15 @@ warning: skipping const checks - --> $DIR/non_const_fn.rs:10:15 + --> $DIR/non_const_fn.rs:9:16 | -LL | const C: () = foo(); - | ^^^^^ +LL | static C: () = foo(); + | ^^^^^ -warning: any use of this value will cause an error - --> $DIR/non_const_fn.rs:10:15 +error[E0080]: could not evaluate static initializer + --> $DIR/non_const_fn.rs:9:16 | -LL | const C: () = foo(); - | --------------^^^^^- - | | - | calling non-const function `foo` - | -note: the lint level is defined here - --> $DIR/non_const_fn.rs:4:9 - | -LL | #![warn(const_err)] - | ^^^^^^^^^ - -error[E0080]: evaluation of constant expression failed - --> $DIR/non_const_fn.rs:14:22 - | -LL | println!("{:?}", C); - | ^ referenced constant has errors - -warning: erroneous constant used - --> $DIR/non_const_fn.rs:14:22 - | -LL | println!("{:?}", C); - | ^ referenced constant has errors +LL | static C: () = foo(); + | ^^^^^ calling non-const function `foo` -error: aborting due to previous error; 3 warnings emitted +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0080`. From 6b76b0e558d3d5b412b627e953a94e4a93a0ad2a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 22 Apr 2020 12:13:52 +0200 Subject: [PATCH 13/13] explain what we are testing in mutable_const --- src/test/ui/consts/miri_unleashed/mutable_const.rs | 12 ++++++++++-- .../ui/consts/miri_unleashed/mutable_const.stderr | 11 ++++++----- src/test/ui/consts/miri_unleashed/mutable_const2.rs | 2 +- .../consts/miri_unleashed/mutable_references_ice.rs | 2 +- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.rs b/src/test/ui/consts/miri_unleashed/mutable_const.rs index 5866f8b4f246f..5cc8808be5dc1 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_const.rs +++ b/src/test/ui/consts/miri_unleashed/mutable_const.rs @@ -1,8 +1,13 @@ // compile-flags: -Zunleash-the-miri-inside-of-you +// normalize-stderr-test "alloc[0-9]+" -> "allocN" #![feature(const_raw_ptr_deref)] #![feature(const_mut_refs)] -#![deny(const_err)] // FIXME: ICEs with allow! See #71316. +#![deny(const_err)] // The `allow` variant is tested by `mutable_const2`. +//~^ NOTE lint level +// Here we check that even though `MUTABLE_BEHIND_RAW` is created from a mutable +// allocation, we intern that allocation as *immutable* and reject writes to it. +// We avoid the `delay_span_bug` ICE by having compilation fail via the `deny` above. use std::cell::UnsafeCell; @@ -10,10 +15,13 @@ use std::cell::UnsafeCell; const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; //~^ WARN: skipping const checks -const MUTATING_BEHIND_RAW: () = { +const MUTATING_BEHIND_RAW: () = { //~ NOTE // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time. unsafe { *MUTABLE_BEHIND_RAW = 99 //~ ERROR any use of this value will cause an error + //~^ NOTE: which is read-only + // FIXME would be good to match more of the error message here, but looks like we + // normalize *after* checking the annoations here. } }; diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.stderr b/src/test/ui/consts/miri_unleashed/mutable_const.stderr index 514c103263f35..34993247fca80 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_const.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_const.stderr @@ -1,25 +1,26 @@ warning: skipping const checks - --> $DIR/mutable_const.rs:10:38 + --> $DIR/mutable_const.rs:15:38 | LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; | ^^^^^^^^^^^^^^^^^^^^ error: any use of this value will cause an error - --> $DIR/mutable_const.rs:16:9 + --> $DIR/mutable_const.rs:21:9 | LL | / const MUTATING_BEHIND_RAW: () = { LL | | // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time. LL | | unsafe { LL | | *MUTABLE_BEHIND_RAW = 99 - | | ^^^^^^^^^^^^^^^^^^^^^^^^ writing to alloc2 which is read-only + | | ^^^^^^^^^^^^^^^^^^^^^^^^ writing to allocN which is read-only +... | LL | | } LL | | }; | |__- | note: the lint level is defined here - --> $DIR/mutable_const.rs:5:9 + --> $DIR/mutable_const.rs:6:9 | -LL | #![deny(const_err)] // FIXME: ICEs with allow! See #71316. +LL | #![deny(const_err)] // The `allow` variant is tested by `mutable_const2`. | ^^^^^^^^^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.rs b/src/test/ui/consts/miri_unleashed/mutable_const2.rs index c5b880ba30920..c2c7fb18e2a63 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_const2.rs +++ b/src/test/ui/consts/miri_unleashed/mutable_const2.rs @@ -3,7 +3,7 @@ // rustc-env:RUST_BACKTRACE=0 // normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" // normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" -// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC" +// normalize-stderr-test "interpret/intern.rs:[0-9]+:[0-9]+" -> "interpret/intern.rs:LL:CC" #![feature(const_raw_ptr_deref)] #![feature(const_mut_refs)] diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_ice.rs b/src/test/ui/consts/miri_unleashed/mutable_references_ice.rs index 635cad81c9798..9d8d5f513c76b 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_references_ice.rs +++ b/src/test/ui/consts/miri_unleashed/mutable_references_ice.rs @@ -3,7 +3,7 @@ // rustc-env:RUST_BACKTRACE=0 // normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" // normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" -// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC" +// normalize-stderr-test "interpret/intern.rs:[0-9]+:[0-9]+" -> "interpret/intern.rs:LL:CC" #![allow(const_err)]