From d64aea65ad3b994ed0e1503f836d82a9896ab468 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 15 Nov 2021 20:40:29 +0100 Subject: [PATCH 01/14] Fix `non-constant value` ICE (#90878) This also fixes the same suggestion, which was kind of broken, because it just searched for the last occurence of `const` to replace with a `let`. This works great in some cases, but when there is no const and a leading space to the file, it doesn't work and panic with overflow because it thought that it had found a const. I also changed the suggestion to only trigger if the `const` and the non-constant value are on the same line, because if they aren't, the suggestion is very likely to be wrong. Also don't trigger the suggestion if the found `const` is on line 0, because that triggers the ICE. --- compiler/rustc_resolve/src/diagnostics.rs | 16 +++++++++- compiler/rustc_span/src/lib.rs | 1 + src/test/ui/consts/issue-90878-2.rs | 12 ++++++++ src/test/ui/consts/issue-90878-2.stderr | 30 +++++++++++++++++++ src/test/ui/consts/issue-90878.rs | 4 +++ src/test/ui/consts/issue-90878.stderr | 11 +++++++ .../ui/consts/non-const-value-in-const.rs | 7 +++++ .../ui/consts/non-const-value-in-const.stderr | 20 +++++++++++++ 8 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/consts/issue-90878-2.rs create mode 100644 src/test/ui/consts/issue-90878-2.stderr create mode 100644 src/test/ui/consts/issue-90878.rs create mode 100644 src/test/ui/consts/issue-90878.stderr create mode 100644 src/test/ui/consts/non-const-value-in-const.rs create mode 100644 src/test/ui/consts/non-const-value-in-const.stderr diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index c46a18e51031a..e9680aae3f89d 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -450,9 +450,23 @@ impl<'a> Resolver<'a> { // let foo =... // ^^^ given this Span // ------- get this Span to have an applicable suggestion + + // edit: + // only do this if the const and usage of the non-constant value are on the same line + // the further the two are apart, the higher the chance of the suggestion being wrong + // also make sure that this line isn't the first one (ICE #90878) + let sp = self.session.source_map().span_extend_to_prev_str(ident.span, current, true); - if sp.lo().0 == 0 { + + let is_first_line = self + .session + .source_map() + .lookup_line(sp.lo()) + .map(|file_and_line| file_and_line.line == 0) + .unwrap_or(true); + + if sp.lo().0 == 0 || self.session.source_map().is_multiline(sp) || is_first_line { err.span_label(ident.span, &format!("this would need to be a `{}`", sugg)); } else { let sp = sp.with_lo(BytePos(sp.lo().0 - current.len() as u32)); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index dfc64f37e4c46..1445c59710cc3 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1935,6 +1935,7 @@ pub struct Loc { #[derive(Debug)] pub struct SourceFileAndLine { pub sf: Lrc, + /// Index of line, starting from 0. pub line: usize, } #[derive(Debug)] diff --git a/src/test/ui/consts/issue-90878-2.rs b/src/test/ui/consts/issue-90878-2.rs new file mode 100644 index 0000000000000..7e3f18cc9d593 --- /dev/null +++ b/src/test/ui/consts/issue-90878-2.rs @@ -0,0 +1,12 @@ + #![l=|x|[b;x ]] //~ ERROR unexpected token: `|x| [b; x]` +//~^ ERROR cannot find attribute `l` in this scope +//~^^ ERROR attempt to use a non-constant value in a constant [E0435] +//~^^^ ERROR cannot find value `b` in this scope [E0425] + +// notice the space at the start, +// we can't attach any attributes to this file because it needs to be at the start + +// this example has been slightly modified (adding ]] at the end), so that it actually works here +// it still produces the same issue though + +fn main() {} diff --git a/src/test/ui/consts/issue-90878-2.stderr b/src/test/ui/consts/issue-90878-2.stderr new file mode 100644 index 0000000000000..9e167424995a7 --- /dev/null +++ b/src/test/ui/consts/issue-90878-2.stderr @@ -0,0 +1,30 @@ +error: unexpected token: `|x| [b; x]` + --> $DIR/issue-90878-2.rs:1:7 + | +LL | #![l=|x|[b;x ]] + | ^^^^^^^^^ + +error: cannot find attribute `l` in this scope + --> $DIR/issue-90878-2.rs:1:5 + | +LL | #![l=|x|[b;x ]] + | ^ + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-90878-2.rs:1:13 + | +LL | #![l=|x|[b;x ]] + | - ^ + | | + | this would need to be a `const` + +error[E0425]: cannot find value `b` in this scope + --> $DIR/issue-90878-2.rs:1:11 + | +LL | #![l=|x|[b;x ]] + | ^ help: a local variable with a similar name exists: `x` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0425, E0435. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/consts/issue-90878.rs b/src/test/ui/consts/issue-90878.rs new file mode 100644 index 0000000000000..43f6fe5f3800d --- /dev/null +++ b/src/test/ui/consts/issue-90878.rs @@ -0,0 +1,4 @@ + fn main() { + |x: usize| [0; x]; //~ ERROR attempt to use a non-constant value in a constant [E0435] + // (note the space before "fn") +} diff --git a/src/test/ui/consts/issue-90878.stderr b/src/test/ui/consts/issue-90878.stderr new file mode 100644 index 0000000000000..c038fc622d468 --- /dev/null +++ b/src/test/ui/consts/issue-90878.stderr @@ -0,0 +1,11 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-90878.rs:2:20 + | +LL | |x: usize| [0; x]; + | - ^ + | | + | this would need to be a `const` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0435`. diff --git a/src/test/ui/consts/non-const-value-in-const.rs b/src/test/ui/consts/non-const-value-in-const.rs new file mode 100644 index 0000000000000..1a20b1e09d7be --- /dev/null +++ b/src/test/ui/consts/non-const-value-in-const.rs @@ -0,0 +1,7 @@ +fn main() { + let x = 5; + const Y: i32 = x; //~ ERROR attempt to use a non-constant value in a constant [E0435] + + let x = 5; + let _ = [0; x]; //~ ERROR attempt to use a non-constant value in a constant [E0435] +} diff --git a/src/test/ui/consts/non-const-value-in-const.stderr b/src/test/ui/consts/non-const-value-in-const.stderr new file mode 100644 index 0000000000000..0ce4b4b705334 --- /dev/null +++ b/src/test/ui/consts/non-const-value-in-const.stderr @@ -0,0 +1,20 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/non-const-value-in-const.rs:3:20 + | +LL | const Y: i32 = x; + | ------- ^ non-constant value + | | + | help: consider using `let` instead of `const`: `let Y` + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/non-const-value-in-const.rs:6:17 + | +LL | let x = 5; + | ----- help: consider using `const` instead of `let`: `const x` +... +LL | let _ = [0; x]; + | ^ non-constant value + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0435`. From 483cff7ed3a3121e6644bbcb9011a762cf871d97 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 4 Nov 2021 17:55:25 +0100 Subject: [PATCH 02/14] Add SourceMap::indentation_before. --- compiler/rustc_span/src/source_map.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 74958c4984962..7414d201f511d 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -593,14 +593,19 @@ impl SourceMap { } pub fn span_to_margin(&self, sp: Span) -> Option { - match self.span_to_prev_source(sp) { - Err(_) => None, - Ok(source) => { - let last_line = source.rsplit_once('\n').unwrap_or(("", &source)).1; + Some(self.indentation_before(sp)?.len()) + } - Some(last_line.len() - last_line.trim_start().len()) - } - } + pub fn indentation_before(&self, sp: Span) -> Option { + self.span_to_source(sp, |src, start_index, _| { + let before = &src[..start_index]; + let last_line = before.rsplit_once('\n').map_or(before, |(_, last)| last); + Ok(last_line + .split_once(|c: char| !c.is_whitespace()) + .map_or(last_line, |(indent, _)| indent) + .to_string()) + }) + .ok() } /// Returns the source snippet as `String` before the given `Span`. From 453e2423e6238283acae39007741e0b122fdb191 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 4 Nov 2021 17:56:04 +0100 Subject: [PATCH 03/14] Improve suggestion for unit Option/Result at the end of a block. --- compiler/rustc_typeck/src/check/demand.rs | 45 +++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 9bbe525914728..fbbaf9eeef9b5 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -199,6 +199,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } + // If the expression is of type () and it's the return expression of a block, + // we suggest adding a separate return expression instead. + // (To avoid things like suggesting `Ok(while .. { .. })`.) + if expr_ty.is_unit() { + if let Some(hir::Node::Block(&hir::Block { + span: block_span, expr: Some(e), .. + })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id)) + { + if e.hir_id == expr.hir_id { + if let Some(span) = expr.span.find_ancestor_inside(block_span) { + let return_suggestions = + if self.tcx.is_diagnostic_item(sym::Result, expected_adt.did) { + vec!["Ok(())".to_string()] + } else if self.tcx.is_diagnostic_item(sym::Option, expected_adt.did) + { + vec!["None".to_string(), "Some(())".to_string()] + } else { + return; + }; + if let Some(indent) = + self.tcx.sess.source_map().indentation_before(span.shrink_to_lo()) + { + // Add a semicolon, except after `}`. + let semicolon = + match self.tcx.sess.source_map().span_to_snippet(span) { + Ok(s) if s.ends_with('}') => "", + _ => ";", + }; + err.multipart_suggestions( + "try adding an expression at the end of the block", + return_suggestions.into_iter().map(|r| { + vec![( + span.shrink_to_hi(), + format!("{}\n{}{}", semicolon, indent, r), + )] + }), + Applicability::MaybeIncorrect, + ); + } + return; + } + } + } + } + let mut compatible_variants = expected_adt .variants .iter() From b331b6608265f98eea8c3fa85dd67d3156c88ead Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 4 Nov 2021 17:57:03 +0100 Subject: [PATCH 04/14] Improve compatible enum variant suggestions. --- compiler/rustc_typeck/src/check/demand.rs | 40 +++++++++++++++-------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index fbbaf9eeef9b5..1e43d8fc2bdbf 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -244,7 +244,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let mut compatible_variants = expected_adt + let compatible_variants: Vec = expected_adt .variants .iter() .filter(|variant| variant.fields.len() == 1) @@ -265,19 +265,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None } }) - .peekable(); + .collect(); - if compatible_variants.peek().is_some() { - if let Ok(expr_text) = self.tcx.sess.source_map().span_to_snippet(expr.span) { - let suggestions = compatible_variants.map(|v| format!("{}({})", v, expr_text)); - let msg = "try using a variant of the expected enum"; - err.span_suggestions( - expr.span, - msg, - suggestions, - Applicability::MaybeIncorrect, - ); - } + if let [variant] = &compatible_variants[..] { + // Just a single matching variant. + err.multipart_suggestion( + &format!("try wrapping the expression in `{}`", variant), + vec![ + (expr.span.shrink_to_lo(), format!("{}(", variant)), + (expr.span.shrink_to_hi(), ")".to_string()), + ], + Applicability::MaybeIncorrect, + ); + } else if compatible_variants.len() > 1 { + // More than one matching variant. + err.multipart_suggestions( + &format!( + "try wrapping the expression in a variant of `{}`", + self.tcx.def_path_str(expected_adt.did) + ), + compatible_variants.into_iter().map(|variant| { + vec![ + (expr.span.shrink_to_lo(), format!("{}(", variant)), + (expr.span.shrink_to_hi(), ")".to_string()), + ] + }), + Applicability::MaybeIncorrect, + ); } } } From 48777561ca67abcd259c870f8da28d0062ce6857 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 4 Nov 2021 17:57:30 +0100 Subject: [PATCH 05/14] Update tests. --- src/test/ui/did_you_mean/issue-42764.rs | 2 +- src/test/ui/did_you_mean/issue-42764.stderr | 8 ++++---- .../fully-qualified-type-name1.stderr | 9 +++++---- .../fully-qualified-type-name4.stderr | 9 +++++---- ...51632-try-desugar-incompatible-types.stderr | 4 ++-- src/test/ui/mismatched_types/abridged.stderr | 18 ++++++++++-------- .../ui/pattern/pat-type-err-let-stmt.stderr | 10 ++++++---- ...t-full-enum-variant-for-local-module.stderr | 10 ++++++---- src/test/ui/typeck/issue-46112.stderr | 9 +++++---- 9 files changed, 44 insertions(+), 35 deletions(-) diff --git a/src/test/ui/did_you_mean/issue-42764.rs b/src/test/ui/did_you_mean/issue-42764.rs index 700f8128a939a..6da640b2b7c76 100644 --- a/src/test/ui/did_you_mean/issue-42764.rs +++ b/src/test/ui/did_you_mean/issue-42764.rs @@ -10,7 +10,7 @@ fn main() { let n: usize = 42; this_function_expects_a_double_option(n); //~^ ERROR mismatched types - //~| HELP try using a variant of the expected enum + //~| HELP try wrapping the expression in a variant of `DoubleOption` } diff --git a/src/test/ui/did_you_mean/issue-42764.stderr b/src/test/ui/did_you_mean/issue-42764.stderr index bc8a93757a599..dbe46704b9320 100644 --- a/src/test/ui/did_you_mean/issue-42764.stderr +++ b/src/test/ui/did_you_mean/issue-42764.stderr @@ -6,12 +6,12 @@ LL | this_function_expects_a_double_option(n); | = note: expected enum `DoubleOption<_>` found type `usize` -help: try using a variant of the expected enum +help: try wrapping the expression in a variant of `DoubleOption` | -LL | this_function_expects_a_double_option(DoubleOption::AlternativeSome(n)); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LL | this_function_expects_a_double_option(DoubleOption::FirstSome(n)); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++++++ + +LL | this_function_expects_a_double_option(DoubleOption::AlternativeSome(n)); + | ++++++++++++++++++++++++++++++ + error[E0308]: mismatched types --> $DIR/issue-42764.rs:27:33 diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr index b5018b47b7bf7..03fb299b39cd2 100644 --- a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr +++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr @@ -2,13 +2,14 @@ error[E0308]: mismatched types --> $DIR/fully-qualified-type-name1.rs:5:9 | LL | x = 5; - | ^ - | | - | expected enum `Option`, found integer - | help: try using a variant of the expected enum: `Some(5)` + | ^ expected enum `Option`, found integer | = note: expected enum `Option` found type `{integer}` +help: try wrapping the expression in `Some` + | +LL | x = Some(5); + | +++++ + error: aborting due to previous error diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr index b9574e3975816..778b13f24cf56 100644 --- a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr +++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr @@ -4,13 +4,14 @@ error[E0308]: mismatched types LL | fn bar(x: usize) -> Option { | ------------- expected `Option` because of return type LL | return x; - | ^ - | | - | expected enum `Option`, found `usize` - | help: try using a variant of the expected enum: `Some(x)` + | ^ expected enum `Option`, found `usize` | = note: expected enum `Option` found type `usize` +help: try wrapping the expression in `Some` + | +LL | return Some(x); + | +++++ + error: aborting due to previous error diff --git a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr index 0f61e03c3b58f..15d2ef3fce8da 100644 --- a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr +++ b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr @@ -12,10 +12,10 @@ help: try removing this `?` LL - missing_discourses()? LL + missing_discourses() | -help: try using a variant of the expected enum +help: try wrapping the expression in `Ok` | LL | Ok(missing_discourses()?) - | + | +++ + error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index db4e8589291b7..ff1a836c9aec0 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -26,13 +26,14 @@ error[E0308]: mismatched types LL | fn b() -> Option { | ----------- expected `Option` because of return type LL | Foo { bar: 1 } - | ^^^^^^^^^^^^^^ - | | - | expected enum `Option`, found struct `Foo` - | help: try using a variant of the expected enum: `Some(Foo { bar: 1 })` + | ^^^^^^^^^^^^^^ expected enum `Option`, found struct `Foo` | = note: expected enum `Option` found struct `Foo` +help: try wrapping the expression in `Some` + | +LL | Some(Foo { bar: 1 }) + | +++++ + error[E0308]: mismatched types --> $DIR/abridged.rs:28:5 @@ -40,13 +41,14 @@ error[E0308]: mismatched types LL | fn c() -> Result { | ---------------- expected `Result` because of return type LL | Foo { bar: 1 } - | ^^^^^^^^^^^^^^ - | | - | expected enum `Result`, found struct `Foo` - | help: try using a variant of the expected enum: `Ok(Foo { bar: 1 })` + | ^^^^^^^^^^^^^^ expected enum `Result`, found struct `Foo` | = note: expected enum `Result` found struct `Foo` +help: try wrapping the expression in `Ok` + | +LL | Ok(Foo { bar: 1 }) + | +++ + error[E0308]: mismatched types --> $DIR/abridged.rs:39:5 diff --git a/src/test/ui/pattern/pat-type-err-let-stmt.stderr b/src/test/ui/pattern/pat-type-err-let-stmt.stderr index 4b4fb08928327..090bd67117eab 100644 --- a/src/test/ui/pattern/pat-type-err-let-stmt.stderr +++ b/src/test/ui/pattern/pat-type-err-let-stmt.stderr @@ -2,14 +2,16 @@ error[E0308]: mismatched types --> $DIR/pat-type-err-let-stmt.rs:6:29 | LL | let Ok(0): Option = 42u8; - | ---------- ^^^^ - | | | - | | expected enum `Option`, found `u8` - | | help: try using a variant of the expected enum: `Some(42u8)` + | ---------- ^^^^ expected enum `Option`, found `u8` + | | | expected due to this | = note: expected enum `Option` found type `u8` +help: try wrapping the expression in `Some` + | +LL | let Ok(0): Option = Some(42u8); + | +++++ + error[E0308]: mismatched types --> $DIR/pat-type-err-let-stmt.rs:6:9 diff --git a/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr b/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr index 22a0ce1e91d72..9b6dba7e9e75b 100644 --- a/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr +++ b/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr @@ -2,14 +2,16 @@ error[E0308]: mismatched types --> $DIR/suggest-full-enum-variant-for-local-module.rs:9:28 | LL | let _: option::O<()> = (); - | ------------- ^^ - | | | - | | expected enum `O`, found `()` - | | help: try using a variant of the expected enum: `option::O::Some(())` + | ------------- ^^ expected enum `O`, found `()` + | | | expected due to this | = note: expected enum `O<()>` found unit type `()` +help: try wrapping the expression in `option::O::Some` + | +LL | let _: option::O<()> = option::O::Some(()); + | ++++++++++++++++ + error: aborting due to previous error diff --git a/src/test/ui/typeck/issue-46112.stderr b/src/test/ui/typeck/issue-46112.stderr index ec05fbe580ede..39bff88e7f81a 100644 --- a/src/test/ui/typeck/issue-46112.stderr +++ b/src/test/ui/typeck/issue-46112.stderr @@ -2,13 +2,14 @@ error[E0308]: mismatched types --> $DIR/issue-46112.rs:9:21 | LL | fn main() { test(Ok(())); } - | ^^ - | | - | expected enum `Option`, found `()` - | help: try using a variant of the expected enum: `Some(())` + | ^^ expected enum `Option`, found `()` | = note: expected enum `Option<()>` found unit type `()` +help: try wrapping the expression in `Some` + | +LL | fn main() { test(Ok(Some(()))); } + | +++++ + error: aborting due to previous error From 5a25751c1e5328930743bef8c1f688ed7c69938b Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 4 Nov 2021 17:57:40 +0100 Subject: [PATCH 06/14] Add new tests for compatible variant diagnostics. --- .../ui/did_you_mean/compatible-variants.rs | 43 ++++++ .../did_you_mean/compatible-variants.stderr | 137 ++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 src/test/ui/did_you_mean/compatible-variants.rs create mode 100644 src/test/ui/did_you_mean/compatible-variants.stderr diff --git a/src/test/ui/did_you_mean/compatible-variants.rs b/src/test/ui/did_you_mean/compatible-variants.rs new file mode 100644 index 0000000000000..fb6b6a5673d90 --- /dev/null +++ b/src/test/ui/did_you_mean/compatible-variants.rs @@ -0,0 +1,43 @@ +enum Hey { + A(A), + B(B), +} + +fn f() {} + +fn a() -> Option<()> { + while false { + //~^ ERROR mismatched types + f(); + } + //~^ HELP try adding an expression +} + +fn b() -> Result<(), ()> { + f() + //~^ ERROR mismatched types + //~| HELP try adding an expression +} + +fn main() { + let _: Option<()> = while false {}; + //~^ ERROR mismatched types + //~| HELP try wrapping + let _: Option<()> = { + while false {} + //~^ ERROR mismatched types + //~| HELP try adding an expression + }; + let _: Result = 1; + //~^ ERROR mismatched types + //~| HELP try wrapping + let _: Option = 1; + //~^ ERROR mismatched types + //~| HELP try wrapping + let _: Hey = 1; + //~^ ERROR mismatched types + //~| HELP try wrapping + let _: Hey = false; + //~^ ERROR mismatched types + //~| HELP try wrapping +} diff --git a/src/test/ui/did_you_mean/compatible-variants.stderr b/src/test/ui/did_you_mean/compatible-variants.stderr new file mode 100644 index 0000000000000..e77949687fcb2 --- /dev/null +++ b/src/test/ui/did_you_mean/compatible-variants.stderr @@ -0,0 +1,137 @@ +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:9:5 + | +LL | fn a() -> Option<()> { + | ---------- expected `Option<()>` because of return type +LL | / while false { +LL | | +LL | | f(); +LL | | } + | |_____^ expected enum `Option`, found `()` + | + = note: expected enum `Option<()>` + found unit type `()` +help: try adding an expression at the end of the block + | +LL ~ } +LL + None + | +LL ~ } +LL + Some(()) + | + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:17:5 + | +LL | fn b() -> Result<(), ()> { + | -------------- expected `Result<(), ()>` because of return type +LL | f() + | ^^^ expected enum `Result`, found `()` + | + = note: expected enum `Result<(), ()>` + found unit type `()` +help: try adding an expression at the end of the block + | +LL ~ f(); +LL + Ok(()) + | + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:23:25 + | +LL | let _: Option<()> = while false {}; + | ---------- ^^^^^^^^^^^^^^ expected enum `Option`, found `()` + | | + | expected due to this + | + = note: expected enum `Option<()>` + found unit type `()` +help: try wrapping the expression in `Some` + | +LL | let _: Option<()> = Some(while false {}); + | +++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:27:9 + | +LL | while false {} + | ^^^^^^^^^^^^^^ expected enum `Option`, found `()` + | + = note: expected enum `Option<()>` + found unit type `()` +help: try adding an expression at the end of the block + | +LL ~ while false {} +LL + None + | +LL ~ while false {} +LL + Some(()) + | + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:31:31 + | +LL | let _: Result = 1; + | ---------------- ^ expected enum `Result`, found integer + | | + | expected due to this + | + = note: expected enum `Result` + found type `{integer}` +help: try wrapping the expression in a variant of `Result` + | +LL | let _: Result = Ok(1); + | +++ + +LL | let _: Result = Err(1); + | ++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:34:26 + | +LL | let _: Option = 1; + | ----------- ^ expected enum `Option`, found integer + | | + | expected due to this + | + = note: expected enum `Option` + found type `{integer}` +help: try wrapping the expression in `Some` + | +LL | let _: Option = Some(1); + | +++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:37:28 + | +LL | let _: Hey = 1; + | ------------- ^ expected enum `Hey`, found integer + | | + | expected due to this + | + = note: expected enum `Hey` + found type `{integer}` +help: try wrapping the expression in a variant of `Hey` + | +LL | let _: Hey = Hey::A(1); + | +++++++ + +LL | let _: Hey = Hey::B(1); + | +++++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:40:29 + | +LL | let _: Hey = false; + | -------------- ^^^^^ expected enum `Hey`, found `bool` + | | + | expected due to this + | + = note: expected enum `Hey` + found type `bool` +help: try wrapping the expression in `Hey::B` + | +LL | let _: Hey = Hey::B(false); + | +++++++ + + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0308`. From 09e4a75f294a9b058bd908c98df38dd41e68f6ff Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 4 Nov 2021 18:12:09 +0100 Subject: [PATCH 07/14] Use span_suggestions instead of multipart_suggestions. --- compiler/rustc_typeck/src/check/demand.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 1e43d8fc2bdbf..ece2d7b4f3793 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -227,14 +227,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(s) if s.ends_with('}') => "", _ => ";", }; - err.multipart_suggestions( + err.span_suggestions( + span.shrink_to_hi(), "try adding an expression at the end of the block", - return_suggestions.into_iter().map(|r| { - vec![( - span.shrink_to_hi(), - format!("{}\n{}{}", semicolon, indent, r), - )] - }), + return_suggestions + .into_iter() + .map(|r| format!("{}\n{}{}", semicolon, indent, r)), Applicability::MaybeIncorrect, ); } From b66fb641da92ea4c9d1c5b0d52ea273cbc21f76e Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 16 Nov 2021 19:57:12 +0100 Subject: [PATCH 08/14] Update test output. --- src/test/ui/suggestions/boxed-variant-field.rs | 2 +- src/test/ui/suggestions/boxed-variant-field.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/ui/suggestions/boxed-variant-field.rs b/src/test/ui/suggestions/boxed-variant-field.rs index d8f7fac151356..9b9e70a675fb1 100644 --- a/src/test/ui/suggestions/boxed-variant-field.rs +++ b/src/test/ui/suggestions/boxed-variant-field.rs @@ -9,7 +9,7 @@ fn foo(x: Ty) -> Ty { Ty::List(elem) => foo(elem), //~^ ERROR mismatched types //~| HELP try dereferencing the `Box` - //~| HELP try using a variant of the expected enum + //~| HELP try wrapping } } diff --git a/src/test/ui/suggestions/boxed-variant-field.stderr b/src/test/ui/suggestions/boxed-variant-field.stderr index d4ccb2ca490bc..e865b993a4c17 100644 --- a/src/test/ui/suggestions/boxed-variant-field.stderr +++ b/src/test/ui/suggestions/boxed-variant-field.stderr @@ -10,10 +10,10 @@ help: try dereferencing the `Box` | LL | Ty::List(elem) => foo(*elem), | + -help: try using a variant of the expected enum +help: try wrapping the expression in `Ty::List` | LL | Ty::List(elem) => foo(Ty::List(elem)), - | ~~~~~~~~~~~~~~ + | +++++++++ + error: aborting due to previous error From 7c7f58d5b7b5b453fde743bb058aa5770a37e57f Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Tue, 16 Nov 2021 22:16:47 +0100 Subject: [PATCH 09/14] Fix case where ICE #90878 was still triggered by a leading newline I cannot provide a test for that thanks to tidy. --- compiler/rustc_resolve/src/diagnostics.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index e9680aae3f89d..2e4cb4ff7270d 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -454,22 +454,20 @@ impl<'a> Resolver<'a> { // edit: // only do this if the const and usage of the non-constant value are on the same line // the further the two are apart, the higher the chance of the suggestion being wrong - // also make sure that this line isn't the first one (ICE #90878) + // also make sure that the pos for the suggestion is not 0 (ICE #90878) let sp = self.session.source_map().span_extend_to_prev_str(ident.span, current, true); - let is_first_line = self - .session - .source_map() - .lookup_line(sp.lo()) - .map(|file_and_line| file_and_line.line == 0) - .unwrap_or(true); + let pos_for_suggestion = sp.lo().0.saturating_sub(current.len() as u32); - if sp.lo().0 == 0 || self.session.source_map().is_multiline(sp) || is_first_line { + if sp.lo().0 == 0 + || pos_for_suggestion == 0 + || self.session.source_map().is_multiline(sp) + { err.span_label(ident.span, &format!("this would need to be a `{}`", sugg)); } else { - let sp = sp.with_lo(BytePos(sp.lo().0 - current.len() as u32)); + let sp = sp.with_lo(BytePos(pos_for_suggestion)); err.span_suggestion( sp, &format!("consider using `{}` instead of `{}`", sugg, current), From bf10c88fbd15c6ca1254a0100ec76d464f665f86 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 17 Nov 2021 14:45:17 +0100 Subject: [PATCH 10/14] Make scrollbar in the sidebar always visible for visual consistency --- src/librustdoc/html/static/css/rustdoc.css | 2 +- src/librustdoc/html/static/css/themes/ayu.css | 4 ++-- src/librustdoc/html/static/css/themes/dark.css | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 89a763ef6d707..9d7f5f173216b 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -303,7 +303,7 @@ nav.sub { left: 0; top: 0; bottom: 0; - overflow: auto; + overflow-y: scroll; } /* Improve the scrollbar display on firefox */ diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index ba7fb3b5456a5..91ede47c156b8 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -70,11 +70,11 @@ pre, .rustdoc.source .example-wrap { /* Improve the scrollbar display on firefox */ * { - scrollbar-color: #5c6773 transparent; + scrollbar-color: #5c6773 #24292f; } .sidebar { - scrollbar-color: #5c6773 transparent; + scrollbar-color: #5c6773 #24292f; } /* Improve the scrollbar display on webkit-based browsers */ diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 77ac217e6f41d..74a4fe45a3d1b 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -44,7 +44,7 @@ pre, .rustdoc.source .example-wrap { scrollbar-color: rgb(64, 65, 67) #717171; } .sidebar { - scrollbar-color: rgba(32,34,37,.6) transparent; + scrollbar-color: rgba(32,34,37,.6) #5a5a5a; } /* Improve the scrollbar display on webkit-based browsers */ From 495d8ed246ec659127ee646b55e0ea7874ecb82f Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 17 Nov 2021 22:22:48 +0100 Subject: [PATCH 11/14] tidy-ignore-leading-newlines --- src/tools/tidy/src/style.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 022a3dfde8217..6ece94771401d 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -266,6 +266,8 @@ pub fn check(path: &Path, bad: &mut bool) { contains_ignore_directive(can_contain, &contents, "end-whitespace"); let mut skip_trailing_newlines = contains_ignore_directive(can_contain, &contents, "trailing-newlines"); + let mut skip_leading_newlines = + contains_ignore_directive(can_contain, &contents, "leading-newlines"); let mut skip_copyright = contains_ignore_directive(can_contain, &contents, "copyright"); let mut leading_new_lines = false; let mut trailing_new_lines = 0; @@ -350,7 +352,10 @@ pub fn check(path: &Path, bad: &mut bool) { } } if leading_new_lines { - tidy_error!(bad, "{}: leading newline", file.display()); + let mut err = |_| { + tidy_error!(bad, "{}: leading newline", file.display()); + }; + suppressible_tidy_err!(err, skip_leading_newlines, "mising leading newline"); } let mut err = |msg: &str| { tidy_error!(bad, "{}: {}", file.display(), msg); @@ -395,6 +400,9 @@ pub fn check(path: &Path, bad: &mut bool) { if let Directive::Ignore(false) = skip_trailing_newlines { tidy_error!(bad, "{}: ignoring trailing newlines unnecessarily", file.display()); } + if let Directive::Ignore(false) = skip_leading_newlines { + tidy_error!(bad, "{}: ignoring leading newlines unnecessarily", file.display()); + } if let Directive::Ignore(false) = skip_copyright { tidy_error!(bad, "{}: ignoring copyright unnecessarily", file.display()); } From 96c37c8a6a4bbfe34a81754e174bfc2e41d194f6 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 17 Nov 2021 22:24:42 +0100 Subject: [PATCH 12/14] Add a test with a leading newline for ICE #90878 --- src/test/ui/consts/issue-90878-3.rs | 6 ++++++ src/test/ui/consts/issue-90878-3.stderr | 11 +++++++++++ 2 files changed, 17 insertions(+) create mode 100644 src/test/ui/consts/issue-90878-3.rs create mode 100644 src/test/ui/consts/issue-90878-3.stderr diff --git a/src/test/ui/consts/issue-90878-3.rs b/src/test/ui/consts/issue-90878-3.rs new file mode 100644 index 0000000000000..0e36646eb49f5 --- /dev/null +++ b/src/test/ui/consts/issue-90878-3.rs @@ -0,0 +1,6 @@ + +fn main() { + |x: usize| [0; x]; //~ ERROR attempt to use a non-constant value in a constant [E0435] + // (note the newline before "fn") +} +// ignore-tidy-leading-newlines diff --git a/src/test/ui/consts/issue-90878-3.stderr b/src/test/ui/consts/issue-90878-3.stderr new file mode 100644 index 0000000000000..1bcc0eb37877b --- /dev/null +++ b/src/test/ui/consts/issue-90878-3.stderr @@ -0,0 +1,11 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-90878-3.rs:3:20 + | +LL | |x: usize| [0; x]; + | - ^ + | | + | this would need to be a `const` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0435`. From f6392a16142425cdb7520440583262ffb374b0d5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 16 Nov 2021 16:16:23 -0800 Subject: [PATCH 13/14] Print output ty for opaque future ty --- compiler/rustc_middle/src/ty/print/pretty.rs | 66 +++++++++++++++---- .../ui/async-await/async-fn-nonsend.stderr | 4 +- .../dont-suggest-missing-await.stderr | 2 +- src/test/ui/async-await/generator-desc.stderr | 4 +- src/test/ui/async-await/issue-61076.rs | 8 +-- src/test/ui/async-await/issue-61076.stderr | 14 ++-- .../ui/async-await/issue-64130-1-sync.stderr | 2 +- .../ui/async-await/issue-64130-2-send.stderr | 2 +- .../ui/async-await/issue-64130-3-other.rs | 8 +-- .../ui/async-await/issue-64130-3-other.stderr | 8 +-- .../issue-64130-non-send-future-diags.stderr | 2 +- src/test/ui/async-await/issue-68112.stderr | 10 +-- src/test/ui/async-await/issue-71137.stderr | 2 +- .../issue-74497-lifetime-in-opaque.stderr | 2 +- src/test/ui/async-await/issue-84841.stderr | 4 +- .../ui/async-await/issues/issue-67893.stderr | 2 +- .../suggest-missing-await-closure.stderr | 2 +- .../async-await/suggest-missing-await.stderr | 14 ++-- .../ui/impl-trait/issues/issue-78722.stderr | 4 +- .../ui/parser/fn-header-semantic-fail.stderr | 4 +- ...0736-async-fn-no-body-def-collector.stderr | 2 +- ...rg-where-it-should-have-been-called.stderr | 6 +- src/test/ui/suggestions/issue-72766.stderr | 4 +- src/test/ui/suggestions/issue-81839.stderr | 2 +- .../match-prev-arm-needing-semi.rs | 2 +- .../match-prev-arm-needing-semi.stderr | 10 +-- .../ui/suggestions/opaque-type-error.stderr | 4 +- 27 files changed, 119 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 5d9e7aaf72f8e..c8e898c684957 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -649,30 +649,74 @@ pub trait PrettyPrinter<'tcx>: let mut first = true; let mut is_sized = false; + let mut is_future = false; + let mut future_output_ty = None; + p!("impl"); for (predicate, _) in bounds { let predicate = predicate.subst(self.tcx(), substs); let bound_predicate = predicate.kind(); - if let ty::PredicateKind::Trait(pred) = bound_predicate.skip_binder() { - let trait_ref = bound_predicate.rebind(pred.trait_ref); - // Don't print +Sized, but rather +?Sized if absent. - if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() { - is_sized = true; - continue; + + match bound_predicate.skip_binder() { + ty::PredicateKind::Projection(projection_predicate) => { + let Some(future_trait) = self.tcx().lang_items().future_trait() else { continue }; + let future_output_def_id = + self.tcx().associated_item_def_ids(future_trait)[0]; + + if projection_predicate.projection_ty.item_def_id + == future_output_def_id + { + // We don't account for multiple `Future::Output = Ty` contraints. + is_future = true; + future_output_ty = Some(projection_predicate.ty); + } } + ty::PredicateKind::Trait(pred) => { + let trait_ref = bound_predicate.rebind(pred.trait_ref); + // Don't print +Sized, but rather +?Sized if absent. + if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() + { + is_sized = true; + continue; + } - p!( - write("{}", if first { " " } else { "+" }), - print(trait_ref.print_only_trait_path()) - ); - first = false; + if Some(trait_ref.def_id()) + == self.tcx().lang_items().future_trait() + { + is_future = true; + continue; + } + + p!( + write("{}", if first { " " } else { "+" }), + print(trait_ref.print_only_trait_path()) + ); + + first = false; + } + _ => {} } } + + if is_future { + p!(write("{}Future", if first { " " } else { "+" })); + first = false; + + if let Some(future_output_ty) = future_output_ty { + // Don't print projection types, which we (unfortunately) see often + // in the error outputs involving async blocks. + if !matches!(future_output_ty.kind(), ty::Projection(_)) { + p!(""); + } + } + } + if !is_sized { p!(write("{}?Sized", if first { " " } else { "+" })); } else if first { p!(" Sized"); } + Ok(self) }); } diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index baaab7fee679d..bf7ab148e23df 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | assert_send(local_dropped_before_await()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:24:5 | @@ -27,7 +27,7 @@ error: future cannot be sent between threads safely LL | assert_send(non_send_temporary_in_match()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:33:20 | diff --git a/src/test/ui/async-await/dont-suggest-missing-await.stderr b/src/test/ui/async-await/dont-suggest-missing-await.stderr index 76bbad26c8026..289a567209c49 100644 --- a/src/test/ui/async-await/dont-suggest-missing-await.stderr +++ b/src/test/ui/async-await/dont-suggest-missing-await.stderr @@ -10,7 +10,7 @@ note: while checking the return type of the `async fn` LL | async fn make_u32() -> u32 { | ^^^ checked the `Output` of this `async fn`, found opaque type = note: expected type `u32` - found opaque type `impl Future` + found opaque type `impl Future` help: consider `await`ing on the `Future` | LL | take_u32(x.await) diff --git a/src/test/ui/async-await/generator-desc.stderr b/src/test/ui/async-await/generator-desc.stderr index d75e927696e10..79834ed7ec1a8 100644 --- a/src/test/ui/async-await/generator-desc.stderr +++ b/src/test/ui/async-await/generator-desc.stderr @@ -25,8 +25,8 @@ note: while checking the return type of the `async fn` | LL | async fn two() {} | ^ checked the `Output` of this `async fn`, found opaque type - = note: expected opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:5:16>) - found opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:6:16>) + = note: expected opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:5:16>) + found opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:6:16>) = help: consider `await`ing on both `Future`s = note: distinct uses of `impl Trait` result in different opaque types diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs index 220f0774e2d54..a35baf1694cac 100644 --- a/src/test/ui/async-await/issue-61076.rs +++ b/src/test/ui/async-await/issue-61076.rs @@ -40,8 +40,8 @@ async fn foo() -> Result<(), ()> { async fn bar() -> Result<(), ()> { foo()?; //~ ERROR the `?` operator can only be applied to values that implement `Try` - //~^ NOTE the `?` operator cannot be applied to type `impl Future` - //~| HELP the trait `Try` is not implemented for `impl Future` + //~^ NOTE the `?` operator cannot be applied to type `impl Future>` + //~| HELP the trait `Try` is not implemented for `impl Future>` //~| NOTE required by `branch` //~| HELP consider `await`ing on the `Future` //~| NOTE in this expansion of desugaring of operator `?` @@ -84,7 +84,7 @@ async fn baz() -> Result<(), ()> { //~| NOTE field not available in `impl Future` struct_().method(); //~ ERROR no method named - //~^ NOTE method not found in `impl Future` + //~^ NOTE method not found in `impl Future` //~| HELP consider `await`ing on the `Future` Ok(()) } @@ -93,7 +93,7 @@ async fn match_() { match tuple() { //~ HELP consider `await`ing on the `Future` Tuple(_) => {} //~ ERROR mismatched types //~^ NOTE expected opaque type, found struct `Tuple` - //~| NOTE expected opaque type `impl Future` + //~| NOTE expected opaque type `impl Future` } } diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr index 60b5bfa53d77f..9878ea2ae693b 100644 --- a/src/test/ui/async-await/issue-61076.stderr +++ b/src/test/ui/async-await/issue-61076.stderr @@ -2,9 +2,9 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try --> $DIR/issue-61076.rs:42:5 | LL | foo()?; - | ^^^^^^ the `?` operator cannot be applied to type `impl Future` + | ^^^^^^ the `?` operator cannot be applied to type `impl Future>` | - = help: the trait `Try` is not implemented for `impl Future` + = help: the trait `Try` is not implemented for `impl Future>` note: required by `branch` --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL | @@ -32,7 +32,7 @@ help: consider `await`ing on the `Future` LL | t.await?; | ++++++ -error[E0609]: no field `0` on type `impl Future` +error[E0609]: no field `0` on type `impl Future` --> $DIR/issue-61076.rs:78:26 | LL | let _: i32 = tuple().0; @@ -43,7 +43,7 @@ help: consider `await`ing on the `Future` and access the field of its `Output` LL | let _: i32 = tuple().await.0; | ++++++ -error[E0609]: no field `a` on type `impl Future` +error[E0609]: no field `a` on type `impl Future` --> $DIR/issue-61076.rs:82:28 | LL | let _: i32 = struct_().a; @@ -54,11 +54,11 @@ help: consider `await`ing on the `Future` and access the field of its `Output` LL | let _: i32 = struct_().await.a; | ++++++ -error[E0599]: no method named `method` found for opaque type `impl Future` in the current scope +error[E0599]: no method named `method` found for opaque type `impl Future` in the current scope --> $DIR/issue-61076.rs:86:15 | LL | struct_().method(); - | ^^^^^^ method not found in `impl Future` + | ^^^^^^ method not found in `impl Future` | help: consider `await`ing on the `Future` and calling the method on its `Output` | @@ -76,7 +76,7 @@ note: while checking the return type of the `async fn` | LL | async fn tuple() -> Tuple { | ^^^^^ checked the `Output` of this `async fn`, expected opaque type - = note: expected opaque type `impl Future` + = note: expected opaque type `impl Future` found struct `Tuple` help: consider `await`ing on the `Future` | diff --git a/src/test/ui/async-await/issue-64130-1-sync.stderr b/src/test/ui/async-await/issue-64130-1-sync.stderr index 12e4bfc3d48b6..010611fae4381 100644 --- a/src/test/ui/async-await/issue-64130-1-sync.stderr +++ b/src/test/ui/async-await/issue-64130-1-sync.stderr @@ -4,7 +4,7 @@ error: future cannot be shared between threads safely LL | is_sync(bar()); | ^^^^^ future returned by `bar` is not `Sync` | - = help: within `impl Future`, the trait `Sync` is not implemented for `Foo` + = help: within `impl Future`, the trait `Sync` is not implemented for `Foo` note: future is not `Sync` as this value is used across an await --> $DIR/issue-64130-1-sync.rs:15:5 | diff --git a/src/test/ui/async-await/issue-64130-2-send.stderr b/src/test/ui/async-await/issue-64130-2-send.stderr index 9c94b8da8929a..bb598b53594e9 100644 --- a/src/test/ui/async-await/issue-64130-2-send.stderr +++ b/src/test/ui/async-await/issue-64130-2-send.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | is_send(bar()); | ^^^^^ future returned by `bar` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Foo` + = help: within `impl Future`, the trait `Send` is not implemented for `Foo` note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-2-send.rs:15:5 | diff --git a/src/test/ui/async-await/issue-64130-3-other.rs b/src/test/ui/async-await/issue-64130-3-other.rs index 7f2e3db6d60f2..52801c35ba3d3 100644 --- a/src/test/ui/async-await/issue-64130-3-other.rs +++ b/src/test/ui/async-await/issue-64130-3-other.rs @@ -5,22 +5,22 @@ // This tests the the unspecialized async-await-specific error when futures don't implement an // auto trait (which is not Send or Sync) due to some type that was captured. -auto trait Qux { } +auto trait Qux {} struct Foo; impl !Qux for Foo {} -fn is_qux(t: T) { } +fn is_qux(t: T) {} async fn bar() { let x = Foo; baz().await; } -async fn baz() { } +async fn baz() {} fn main() { is_qux(bar()); - //~^ ERROR the trait bound `Foo: Qux` is not satisfied in `impl Future` + //~^ ERROR the trait bound `Foo: Qux` is not satisfied in `impl Future` } diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr index 3dd1239e23dbe..4de7929e18149 100644 --- a/src/test/ui/async-await/issue-64130-3-other.stderr +++ b/src/test/ui/async-await/issue-64130-3-other.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl Future` +error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl Future` --> $DIR/issue-64130-3-other.rs:24:12 | LL | async fn bar() { - | - within this `impl Future` + | - within this `impl Future` ... LL | is_qux(bar()); - | ^^^^^ within `impl Future`, the trait `Qux` is not implemented for `Foo` + | ^^^^^ within `impl Future`, the trait `Qux` is not implemented for `Foo` | note: future does not implement `Qux` as this value is used across an await --> $DIR/issue-64130-3-other.rs:18:5 @@ -19,7 +19,7 @@ LL | } note: required by a bound in `is_qux` --> $DIR/issue-64130-3-other.rs:14:14 | -LL | fn is_qux(t: T) { } +LL | fn is_qux(t: T) {} | ^^^ required by this bound in `is_qux` error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr index a373ba6aa7136..8eedb3597330e 100644 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | is_send(foo()); | ^^^^^ future returned by `foo` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, u32>` + = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, u32>` note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-non-send-future-diags.rs:17:5 | diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.stderr index 6b8e49a21a670..9682a7055e93c 100644 --- a/src/test/ui/async-await/issue-68112.stderr +++ b/src/test/ui/async-await/issue-68112.stderr @@ -9,7 +9,7 @@ note: future is not `Send` as it awaits another future which is not `Send` --> $DIR/issue-68112.rs:31:17 | LL | let _ = non_send_fut.await; - | ^^^^^^^^^^^^ await occurs here on type `impl Future`, which is not `Send` + | ^^^^^^^^^^^^ await occurs here on type `impl Future>>`, which is not `Send` note: required by a bound in `require_send` --> $DIR/issue-68112.rs:11:25 | @@ -27,7 +27,7 @@ note: future is not `Send` as it awaits another future which is not `Send` --> $DIR/issue-68112.rs:40:17 | LL | let _ = make_non_send_future1().await; - | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl Future`, which is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl Future>>`, which is not `Send` note: required by a bound in `require_send` --> $DIR/issue-68112.rs:11:25 | @@ -45,9 +45,9 @@ LL | require_send(send_fut); = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36]` = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>` = note: required because it appears within the type `impl Future` - = note: required because it appears within the type `impl Future` - = note: required because it appears within the type `impl Future` - = note: required because it appears within the type `{ResumeTy, impl Future, (), i32, Ready}` + = note: required because it appears within the type `impl Future>>` + = note: required because it appears within the type `impl Future>>` + = note: required because it appears within the type `{ResumeTy, impl Future>>, (), i32, Ready}` = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6]` = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>` = note: required because it appears within the type `impl Future` diff --git a/src/test/ui/async-await/issue-71137.stderr b/src/test/ui/async-await/issue-71137.stderr index 3cc800f96c20d..dddea12162a0b 100644 --- a/src/test/ui/async-await/issue-71137.stderr +++ b/src/test/ui/async-await/issue-71137.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | fake_spawn(wrong_mutex()); | ^^^^^^^^^^^^^ future returned by `wrong_mutex` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, i32>` + = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, i32>` note: future is not `Send` as this value is used across an await --> $DIR/issue-71137.rs:14:5 | diff --git a/src/test/ui/async-await/issue-74497-lifetime-in-opaque.stderr b/src/test/ui/async-await/issue-74497-lifetime-in-opaque.stderr index 89fe1abb3656b..4427014ae3bf9 100644 --- a/src/test/ui/async-await/issue-74497-lifetime-in-opaque.stderr +++ b/src/test/ui/async-await/issue-74497-lifetime-in-opaque.stderr @@ -4,7 +4,7 @@ error: lifetime may not live long enough LL | let _ = foo(|x| bar(x)); | -- ^^^^^^ returning this value requires that `'1` must outlive `'2` | || - | |return type of closure `impl Future` contains a lifetime `'2` + | |return type of closure `impl Future` contains a lifetime `'2` | has type `&'1 u8` error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-84841.stderr b/src/test/ui/async-await/issue-84841.stderr index e28ba74eb6339..7b6084c49a0f8 100644 --- a/src/test/ui/async-await/issue-84841.stderr +++ b/src/test/ui/async-await/issue-84841.stderr @@ -2,9 +2,9 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try --> $DIR/issue-84841.rs:9:5 | LL | test()?; - | ^^^^^^^ the `?` operator cannot be applied to type `impl Future` + | ^^^^^^^ the `?` operator cannot be applied to type `impl Future` | - = help: the trait `Try` is not implemented for `impl Future` + = help: the trait `Try` is not implemented for `impl Future` note: required by `branch` --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL | diff --git a/src/test/ui/async-await/issues/issue-67893.stderr b/src/test/ui/async-await/issues/issue-67893.stderr index ee32a1a9e4fbb..0aa0d5d7ccdde 100644 --- a/src/test/ui/async-await/issues/issue-67893.stderr +++ b/src/test/ui/async-await/issues/issue-67893.stderr @@ -4,7 +4,7 @@ error: generator cannot be sent between threads safely LL | g(issue_67893::run()) | ^^^^^^^^^^^^^^^^^^ generator is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, ()>` + = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, ()>` note: required by a bound in `g` --> $DIR/issue-67893.rs:6:14 | diff --git a/src/test/ui/async-await/suggest-missing-await-closure.stderr b/src/test/ui/async-await/suggest-missing-await-closure.stderr index 630ae4b539f99..d951c8ed094e7 100644 --- a/src/test/ui/async-await/suggest-missing-await-closure.stderr +++ b/src/test/ui/async-await/suggest-missing-await-closure.stderr @@ -10,7 +10,7 @@ note: while checking the return type of the `async fn` LL | async fn make_u32() -> u32 { | ^^^ checked the `Output` of this `async fn`, found opaque type = note: expected type `u32` - found opaque type `impl Future` + found opaque type `impl Future` help: consider `await`ing on the `Future` | LL | take_u32(x.await) diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr index aefe3096fd9b2..bea50b3bfc036 100644 --- a/src/test/ui/async-await/suggest-missing-await.stderr +++ b/src/test/ui/async-await/suggest-missing-await.stderr @@ -10,7 +10,7 @@ note: while checking the return type of the `async fn` LL | async fn make_u32() -> u32 { | ^^^ checked the `Output` of this `async fn`, found opaque type = note: expected type `u32` - found opaque type `impl Future` + found opaque type `impl Future` help: consider `await`ing on the `Future` | LL | take_u32(x.await) @@ -28,7 +28,7 @@ note: while checking the return type of the `async fn` LL | async fn dummy() {} | ^ checked the `Output` of this `async fn`, found opaque type = note: expected unit type `()` - found opaque type `impl Future` + found opaque type `impl Future` help: consider `await`ing on the `Future` | LL | dummy().await @@ -53,7 +53,7 @@ LL | | LL | | }; | |_____- `if` and `else` have incompatible types | - = note: expected type `impl Future` + = note: expected type `impl Future` found unit type `()` help: consider `await`ing on the `Future` | @@ -66,9 +66,9 @@ error[E0308]: `match` arms have incompatible types LL | let _x = match 0usize { | ______________- LL | | 0 => dummy(), - | | ------- this is found to be of type `impl Future` + | | ------- this is found to be of type `impl Future` LL | | 1 => dummy(), - | | ------- this is found to be of type `impl Future` + | | ------- this is found to be of type `impl Future` LL | | 2 => dummy().await, | | ^^^^^^^^^^^^^ expected opaque type, found `()` LL | | @@ -80,7 +80,7 @@ note: while checking the return type of the `async fn` | LL | async fn dummy() {} | ^ checked the `Output` of this `async fn`, expected opaque type - = note: expected opaque type `impl Future` + = note: expected opaque type `impl Future` found unit type `()` help: consider `await`ing on the `Future` | @@ -99,7 +99,7 @@ note: while checking the return type of the `async fn` | LL | async fn dummy() {} | ^ checked the `Output` of this `async fn`, expected opaque type - = note: expected opaque type `impl Future` + = note: expected opaque type `impl Future` found unit type `()` help: consider `await`ing on the `Future` | diff --git a/src/test/ui/impl-trait/issues/issue-78722.stderr b/src/test/ui/impl-trait/issues/issue-78722.stderr index 5e432e7649604..86bde9a0cddab 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.stderr +++ b/src/test/ui/impl-trait/issues/issue-78722.stderr @@ -14,8 +14,8 @@ LL | let f: F = async { 1 }; LL | pub const fn from_generator(gen: T) -> impl Future | ------------------------------- the found opaque type | - = note: expected opaque type `impl Future` (opaque type at <$DIR/issue-78722.rs:5:10>) - found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) + = note: expected opaque type `impl Future` + found opaque type `impl Future` = note: distinct uses of `impl Trait` result in different opaque types error: aborting due to previous error diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr index 0adfa5b47a3e2..75c60a0ea2a39 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.stderr +++ b/src/test/ui/parser/fn-header-semantic-fail.stderr @@ -194,7 +194,7 @@ LL | async fn ft1() {} | = note: while checking the return type of the `async fn` = note: expected fn pointer `fn()` - found fn pointer `fn() -> impl Future` + found fn pointer `fn() -> impl Future` error[E0053]: method `ft5` has an incompatible type for trait --> $DIR/fn-header-semantic-fail.rs:33:48 @@ -210,7 +210,7 @@ LL | const async unsafe extern "C" fn ft5() {} | = note: while checking the return type of the `async fn` = note: expected fn pointer `unsafe extern "C" fn()` - found fn pointer `unsafe extern "C" fn() -> impl Future` + found fn pointer `unsafe extern "C" fn() -> impl Future` error: aborting due to 20 previous errors diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr index 4025b5030dc0f..50446bb659b0c 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr @@ -58,7 +58,7 @@ LL | async fn associated(); | = note: while checking the return type of the `async fn` = note: expected fn pointer `fn()` - found fn pointer `fn() -> impl Future` + found fn pointer `fn() -> impl Future` error: aborting due to 6 previous errors diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index 78ebb3d6bfc24..4759ebea0e9b7 100644 --- a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -1,15 +1,15 @@ -error[E0277]: `fn() -> impl Future {foo}` is not a future +error[E0277]: `fn() -> impl Future {foo}` is not a future --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:10:9 | LL | async fn foo() {} | --- consider calling this function ... LL | bar(foo); - | --- ^^^ `fn() -> impl Future {foo}` is not a future + | --- ^^^ `fn() -> impl Future {foo}` is not a future | | | required by a bound introduced by this call | - = help: the trait `Future` is not implemented for `fn() -> impl Future {foo}` + = help: the trait `Future` is not implemented for `fn() -> impl Future {foo}` note: required by a bound in `bar` --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 | diff --git a/src/test/ui/suggestions/issue-72766.stderr b/src/test/ui/suggestions/issue-72766.stderr index 43ba35d0205bd..cb47d589bee5c 100644 --- a/src/test/ui/suggestions/issue-72766.stderr +++ b/src/test/ui/suggestions/issue-72766.stderr @@ -2,9 +2,9 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try --> $DIR/issue-72766.rs:14:5 | LL | SadGirl {}.call()?; - | ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future` + | ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future>` | - = help: the trait `Try` is not implemented for `impl Future` + = help: the trait `Try` is not implemented for `impl Future>` note: required by `branch` --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL | diff --git a/src/test/ui/suggestions/issue-81839.stderr b/src/test/ui/suggestions/issue-81839.stderr index 1e0aa9ce40d18..0b1c41b837f6a 100644 --- a/src/test/ui/suggestions/issue-81839.stderr +++ b/src/test/ui/suggestions/issue-81839.stderr @@ -20,7 +20,7 @@ note: while checking the return type of the `async fn` LL | pub async fn answer_str(&self, _s: &str) -> Test { | ^^^^ checked the `Output` of this `async fn`, found opaque type = note: expected type `()` - found opaque type `impl Future` + found opaque type `impl Future` error: aborting due to previous error diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs index 990a4469764f0..6aa93a24d2f04 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs @@ -55,7 +55,7 @@ async fn async_different_futures() { //~| HELP consider `await`ing on both `Future`s false => async_dummy2(), //~ ERROR `match` arms have incompatible types //~^ NOTE expected opaque type, found a different opaque type - //~| NOTE expected type `impl Future` + //~| NOTE expected type `impl Future` //~| NOTE distinct uses of `impl Trait` result in different opaque types }; } diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr index a8f7f3cb17779..b55c51b92809a 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr @@ -21,7 +21,7 @@ note: while checking the return type of the `async fn` LL | async fn async_dummy() {} | ^ checked the `Output` of this `async fn`, found opaque type = note: expected type `()` - found opaque type `impl Future` + found opaque type `impl Future` help: consider `await`ing on the `Future` | LL | false => async_dummy().await, @@ -55,7 +55,7 @@ note: while checking the return type of the `async fn` LL | async fn async_dummy2() {} | ^ checked the `Output` of this `async fn`, found opaque type = note: expected type `()` - found opaque type `impl Future` + found opaque type `impl Future` help: consider `await`ing on the `Future` | LL | false => async_dummy2().await, @@ -74,7 +74,7 @@ error[E0308]: `match` arms have incompatible types LL | let _ = match true { | _____________- LL | | true => async_dummy(), - | | ------------- this is found to be of type `impl Future` + | | ------------- this is found to be of type `impl Future` LL | | LL | | false => async_dummy2(), | | ^^^^^^^^^^^^^^ expected opaque type, found a different opaque type @@ -88,8 +88,8 @@ note: while checking the return type of the `async fn` | LL | async fn async_dummy2() {} | ^ checked the `Output` of this `async fn`, found opaque type - = note: expected type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>) - found opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:19:25>) + = note: expected type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>) + found opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:19:25>) = note: distinct uses of `impl Trait` result in different opaque types help: consider `await`ing on both `Future`s | diff --git a/src/test/ui/suggestions/opaque-type-error.stderr b/src/test/ui/suggestions/opaque-type-error.stderr index 851073734515d..e065e0aaa8e06 100644 --- a/src/test/ui/suggestions/opaque-type-error.stderr +++ b/src/test/ui/suggestions/opaque-type-error.stderr @@ -13,8 +13,8 @@ LL | | thing_two() LL | | }.await | |_____- `if` and `else` have incompatible types | - = note: expected type `impl Future` (opaque type at <$DIR/opaque-type-error.rs:8:19>) - found opaque type `impl Future` (opaque type at <$DIR/opaque-type-error.rs:12:19>) + = note: expected type `impl Future>` (opaque type at <$DIR/opaque-type-error.rs:8:19>) + found opaque type `impl Future>` (opaque type at <$DIR/opaque-type-error.rs:12:19>) = note: distinct uses of `impl Trait` result in different opaque types help: consider `await`ing on both `Future`s | From 33ab5123e2ac51e312f72e2d689aa57a8483c2ac Mon Sep 17 00:00:00 2001 From: Ken Matsui <26405363+ken-matsui@users.noreply.github.com> Date: Sat, 6 Nov 2021 04:43:55 +0900 Subject: [PATCH 14/14] Clarify error messages caused by re-exporting `pub(crate)` visibility to outside --- compiler/rustc_resolve/src/imports.rs | 50 ++-- src/test/ui/error-codes/E0365.rs | 2 +- src/test/ui/error-codes/E0365.stderr | 4 +- src/test/ui/modules/issue-56411.rs | 2 +- src/test/ui/modules/issue-56411.stderr | 4 +- src/test/ui/privacy/crate-private-reexport.rs | 66 ++++++ .../ui/privacy/crate-private-reexport.stderr | 220 ++++++++++++++++++ .../ui/privacy/private-variant-reexport.rs | 6 +- .../privacy/private-variant-reexport.stderr | 8 +- .../ui/rust-2018/uniform-paths/macro-rules.rs | 2 +- .../uniform-paths/macro-rules.stderr | 2 +- 11 files changed, 334 insertions(+), 32 deletions(-) create mode 100644 src/test/ui/privacy/crate-private-reexport.rs create mode 100644 src/test/ui/privacy/crate-private-reexport.stderr diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 936ab81914a99..bee3662183b6a 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1180,11 +1180,17 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut reexport_error = None; let mut any_successful_reexport = false; + let mut crate_private_reexport = false; self.r.per_ns(|this, ns| { if let Ok(binding) = source_bindings[ns].get() { let vis = import.vis.get(); if !binding.vis.is_at_least(vis, &*this) { reexport_error = Some((ns, binding)); + if let ty::Visibility::Restricted(binding_def_id) = binding.vis { + if binding_def_id.is_top_level_module() { + crate_private_reexport = true; + } + } } else { any_successful_reexport = true; } @@ -1207,24 +1213,34 @@ impl<'a, 'b> ImportResolver<'a, 'b> { import.span, &msg, ); - } else if ns == TypeNS { - struct_span_err!( - self.r.session, - import.span, - E0365, - "`{}` is private, and cannot be re-exported", - ident - ) - .span_label(import.span, format!("re-export of private `{}`", ident)) - .note(&format!("consider declaring type or module `{}` with `pub`", ident)) - .emit(); } else { - let msg = format!("`{}` is private, and cannot be re-exported", ident); - let note_msg = - format!("consider marking `{}` as `pub` in the imported module", ident,); - struct_span_err!(self.r.session, import.span, E0364, "{}", &msg) - .span_note(import.span, ¬e_msg) - .emit(); + let error_msg = if crate_private_reexport { + format!( + "`{}` is only public within the crate, and cannot be re-exported outside", + ident + ) + } else { + format!("`{}` is private, and cannot be re-exported", ident) + }; + + if ns == TypeNS { + let label_msg = if crate_private_reexport { + format!("re-export of crate public `{}`", ident) + } else { + format!("re-export of private `{}`", ident) + }; + + struct_span_err!(self.r.session, import.span, E0365, "{}", error_msg) + .span_label(import.span, label_msg) + .note(&format!("consider declaring type or module `{}` with `pub`", ident)) + .emit(); + } else { + let note_msg = + format!("consider marking `{}` as `pub` in the imported module", ident); + struct_span_err!(self.r.session, import.span, E0364, "{}", error_msg) + .span_note(import.span, ¬e_msg) + .emit(); + } } } diff --git a/src/test/ui/error-codes/E0365.rs b/src/test/ui/error-codes/E0365.rs index f12ff96bb8aee..464109247c9ba 100644 --- a/src/test/ui/error-codes/E0365.rs +++ b/src/test/ui/error-codes/E0365.rs @@ -3,6 +3,6 @@ mod foo { } pub use foo as foo2; -//~^ ERROR `foo` is private, and cannot be re-exported [E0365] +//~^ ERROR `foo` is only public within the crate, and cannot be re-exported outside [E0365] fn main() {} diff --git a/src/test/ui/error-codes/E0365.stderr b/src/test/ui/error-codes/E0365.stderr index c8fc59f8ba958..5bfcf1394d9fe 100644 --- a/src/test/ui/error-codes/E0365.stderr +++ b/src/test/ui/error-codes/E0365.stderr @@ -1,8 +1,8 @@ -error[E0365]: `foo` is private, and cannot be re-exported +error[E0365]: `foo` is only public within the crate, and cannot be re-exported outside --> $DIR/E0365.rs:5:9 | LL | pub use foo as foo2; - | ^^^^^^^^^^^ re-export of private `foo` + | ^^^^^^^^^^^ re-export of crate public `foo` | = note: consider declaring type or module `foo` with `pub` diff --git a/src/test/ui/modules/issue-56411.rs b/src/test/ui/modules/issue-56411.rs index 163651a7ef607..0a20f5fe98562 100644 --- a/src/test/ui/modules/issue-56411.rs +++ b/src/test/ui/modules/issue-56411.rs @@ -5,7 +5,7 @@ macro_rules! import { mod $name; pub use self::$name; //~^ ERROR the name `issue_56411_aux` is defined multiple times - //~| ERROR `issue_56411_aux` is private, and cannot be re-exported + //~| ERROR `issue_56411_aux` is only public within the crate, and cannot be re-exported outside )* } diff --git a/src/test/ui/modules/issue-56411.stderr b/src/test/ui/modules/issue-56411.stderr index 5ab4542b0402b..6732a8a3d7324 100644 --- a/src/test/ui/modules/issue-56411.stderr +++ b/src/test/ui/modules/issue-56411.stderr @@ -15,11 +15,11 @@ LL | import!(("issue-56411-aux.rs", issue_56411_aux)); = note: `issue_56411_aux` must be defined only once in the type namespace of this module = note: this error originates in the macro `import` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0365]: `issue_56411_aux` is private, and cannot be re-exported +error[E0365]: `issue_56411_aux` is only public within the crate, and cannot be re-exported outside --> $DIR/issue-56411.rs:6:21 | LL | pub use self::$name; - | ^^^^^^^^^^^ re-export of private `issue_56411_aux` + | ^^^^^^^^^^^ re-export of crate public `issue_56411_aux` ... LL | import!(("issue-56411-aux.rs", issue_56411_aux)); | ------------------------------------------------ in this macro invocation diff --git a/src/test/ui/privacy/crate-private-reexport.rs b/src/test/ui/privacy/crate-private-reexport.rs new file mode 100644 index 0000000000000..fa4f88666d864 --- /dev/null +++ b/src/test/ui/privacy/crate-private-reexport.rs @@ -0,0 +1,66 @@ +fn f1() {} +enum E1 { V } +struct S1 { + #[rustfmt::skip] + bar: i32, +} +mod m1 { + pub use ::f1; //~ ERROR `f1` is only public within the crate, and cannot be re-exported outside + pub use ::S1; //~ ERROR `S1` is only public within the crate, and cannot be re-exported outside + pub use ::E1; //~ ERROR `E1` is only public within the crate, and cannot be re-exported outside + pub use ::E1::V; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside +} + +pub(crate) fn f2() {} +pub(crate) enum E2 { + V +} +pub(crate) struct S2 { + #[rustfmt::skip] + bar: i32, +} +mod m2 { + pub use ::f2; //~ ERROR `f2` is only public within the crate, and cannot be re-exported outside + pub use ::S2; //~ ERROR `S2` is only public within the crate, and cannot be re-exported outside + pub use ::E2; //~ ERROR `E2` is only public within the crate, and cannot be re-exported outside + pub use ::E2::V; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside +} + +mod m3 { + pub(crate) fn f3() {} + pub(crate) enum E3 { + V + } + pub(crate) struct S3 { + #[rustfmt::skip] + bar: i32, + } +} +pub use m3::f3; //~ ERROR `f3` is only public within the crate, and cannot be re-exported outside +pub use m3::S3; //~ ERROR `S3` is only public within the crate, and cannot be re-exported outside +pub use m3::E3; //~ ERROR `E3` is only public within the crate, and cannot be re-exported outside +pub use m3::E3::V; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside + +pub(self) fn f4() {} +pub use ::f4 as f5; //~ ERROR `f4` is only public within the crate, and cannot be re-exported outside + +pub mod m10 { + pub mod m { + pub(super) fn f6() {} + pub(crate) fn f7() {} + pub(in crate::m10) fn f8() {} + } + pub use self::m::f6; //~ ERROR `f6` is private, and cannot be re-exported + pub use self::m::f7; //~ ERROR `f7` is only public within the crate, and cannot be re-exported outside + pub use self::m::f8; //~ ERROR `f8` is private, and cannot be re-exported +} +pub use m10::m::f6; //~ ERROR function `f6` is private +pub use m10::m::f7; //~ ERROR `f7` is only public within the crate, and cannot be re-exported outside +pub use m10::m::f8; //~ ERROR function `f8` is private + +pub mod m11 { + pub(self) fn f9() {} +} +pub use m11::f9; //~ ERROR function `f9` is private + +fn main() {} diff --git a/src/test/ui/privacy/crate-private-reexport.stderr b/src/test/ui/privacy/crate-private-reexport.stderr new file mode 100644 index 0000000000000..66e11e8210771 --- /dev/null +++ b/src/test/ui/privacy/crate-private-reexport.stderr @@ -0,0 +1,220 @@ +error[E0364]: `f1` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:8:13 + | +LL | pub use ::f1; + | ^^^^ + | +note: consider marking `f1` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:8:13 + | +LL | pub use ::f1; + | ^^^^ + +error[E0365]: `S1` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:9:13 + | +LL | pub use ::S1; + | ^^^^ re-export of crate public `S1` + | + = note: consider declaring type or module `S1` with `pub` + +error[E0365]: `E1` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:10:13 + | +LL | pub use ::E1; + | ^^^^ re-export of crate public `E1` + | + = note: consider declaring type or module `E1` with `pub` + +error[E0364]: `V` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:11:13 + | +LL | pub use ::E1::V; + | ^^^^^^^ + | +note: consider marking `V` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:11:13 + | +LL | pub use ::E1::V; + | ^^^^^^^ + +error[E0364]: `f2` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:23:13 + | +LL | pub use ::f2; + | ^^^^ + | +note: consider marking `f2` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:23:13 + | +LL | pub use ::f2; + | ^^^^ + +error[E0365]: `S2` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:24:13 + | +LL | pub use ::S2; + | ^^^^ re-export of crate public `S2` + | + = note: consider declaring type or module `S2` with `pub` + +error[E0365]: `E2` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:25:13 + | +LL | pub use ::E2; + | ^^^^ re-export of crate public `E2` + | + = note: consider declaring type or module `E2` with `pub` + +error[E0364]: `V` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:26:13 + | +LL | pub use ::E2::V; + | ^^^^^^^ + | +note: consider marking `V` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:26:13 + | +LL | pub use ::E2::V; + | ^^^^^^^ + +error[E0364]: `f3` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:39:9 + | +LL | pub use m3::f3; + | ^^^^^^ + | +note: consider marking `f3` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:39:9 + | +LL | pub use m3::f3; + | ^^^^^^ + +error[E0365]: `S3` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:40:9 + | +LL | pub use m3::S3; + | ^^^^^^ re-export of crate public `S3` + | + = note: consider declaring type or module `S3` with `pub` + +error[E0365]: `E3` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:41:9 + | +LL | pub use m3::E3; + | ^^^^^^ re-export of crate public `E3` + | + = note: consider declaring type or module `E3` with `pub` + +error[E0364]: `V` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:42:9 + | +LL | pub use m3::E3::V; + | ^^^^^^^^^ + | +note: consider marking `V` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:42:9 + | +LL | pub use m3::E3::V; + | ^^^^^^^^^ + +error[E0364]: `f4` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:45:9 + | +LL | pub use ::f4 as f5; + | ^^^^^^^^^^ + | +note: consider marking `f4` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:45:9 + | +LL | pub use ::f4 as f5; + | ^^^^^^^^^^ + +error[E0364]: `f6` is private, and cannot be re-exported + --> $DIR/crate-private-reexport.rs:53:13 + | +LL | pub use self::m::f6; + | ^^^^^^^^^^^ + | +note: consider marking `f6` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:53:13 + | +LL | pub use self::m::f6; + | ^^^^^^^^^^^ + +error[E0364]: `f7` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:54:13 + | +LL | pub use self::m::f7; + | ^^^^^^^^^^^ + | +note: consider marking `f7` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:54:13 + | +LL | pub use self::m::f7; + | ^^^^^^^^^^^ + +error[E0364]: `f8` is private, and cannot be re-exported + --> $DIR/crate-private-reexport.rs:55:13 + | +LL | pub use self::m::f8; + | ^^^^^^^^^^^ + | +note: consider marking `f8` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:55:13 + | +LL | pub use self::m::f8; + | ^^^^^^^^^^^ + +error[E0364]: `f7` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:58:9 + | +LL | pub use m10::m::f7; + | ^^^^^^^^^^ + | +note: consider marking `f7` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:58:9 + | +LL | pub use m10::m::f7; + | ^^^^^^^^^^ + +error[E0603]: function `f6` is private + --> $DIR/crate-private-reexport.rs:57:17 + | +LL | pub use m10::m::f6; + | ^^ private function + | +note: the function `f6` is defined here + --> $DIR/crate-private-reexport.rs:49:9 + | +LL | pub(super) fn f6() {} + | ^^^^^^^^^^^^^^^^^^ + +error[E0603]: function `f8` is private + --> $DIR/crate-private-reexport.rs:59:17 + | +LL | pub use m10::m::f8; + | ^^ private function + | +note: the function `f8` is defined here + --> $DIR/crate-private-reexport.rs:51:9 + | +LL | pub(in crate::m10) fn f8() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0603]: function `f9` is private + --> $DIR/crate-private-reexport.rs:64:14 + | +LL | pub use m11::f9; + | ^^ private function + | +note: the function `f9` is defined here + --> $DIR/crate-private-reexport.rs:62:5 + | +LL | pub(self) fn f9() {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 20 previous errors + +Some errors have detailed explanations: E0364, E0365, E0603. +For more information about an error, try `rustc --explain E0364`. diff --git a/src/test/ui/privacy/private-variant-reexport.rs b/src/test/ui/privacy/private-variant-reexport.rs index ce1b0d321ca50..6882844602286 100644 --- a/src/test/ui/privacy/private-variant-reexport.rs +++ b/src/test/ui/privacy/private-variant-reexport.rs @@ -1,13 +1,13 @@ mod m1 { - pub use ::E::V; //~ ERROR `V` is private, and cannot be re-exported + pub use ::E::V; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside } mod m2 { - pub use ::E::{V}; //~ ERROR `V` is private, and cannot be re-exported + pub use ::E::{V}; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside } mod m3 { - pub use ::E::V::{self}; //~ ERROR `V` is private, and cannot be re-exported + pub use ::E::V::{self}; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside } #[deny(unused_imports)] diff --git a/src/test/ui/privacy/private-variant-reexport.stderr b/src/test/ui/privacy/private-variant-reexport.stderr index 7a4c3234dbe6f..78771ee30d314 100644 --- a/src/test/ui/privacy/private-variant-reexport.stderr +++ b/src/test/ui/privacy/private-variant-reexport.stderr @@ -1,4 +1,4 @@ -error[E0364]: `V` is private, and cannot be re-exported +error[E0364]: `V` is only public within the crate, and cannot be re-exported outside --> $DIR/private-variant-reexport.rs:2:13 | LL | pub use ::E::V; @@ -10,7 +10,7 @@ note: consider marking `V` as `pub` in the imported module LL | pub use ::E::V; | ^^^^^^ -error[E0364]: `V` is private, and cannot be re-exported +error[E0364]: `V` is only public within the crate, and cannot be re-exported outside --> $DIR/private-variant-reexport.rs:6:19 | LL | pub use ::E::{V}; @@ -22,11 +22,11 @@ note: consider marking `V` as `pub` in the imported module LL | pub use ::E::{V}; | ^ -error[E0365]: `V` is private, and cannot be re-exported +error[E0365]: `V` is only public within the crate, and cannot be re-exported outside --> $DIR/private-variant-reexport.rs:10:22 | LL | pub use ::E::V::{self}; - | ^^^^ re-export of private `V` + | ^^^^ re-export of crate public `V` | = note: consider declaring type or module `V` with `pub` diff --git a/src/test/ui/rust-2018/uniform-paths/macro-rules.rs b/src/test/ui/rust-2018/uniform-paths/macro-rules.rs index 6c3f1892cb369..2d9a6a9a92499 100644 --- a/src/test/ui/rust-2018/uniform-paths/macro-rules.rs +++ b/src/test/ui/rust-2018/uniform-paths/macro-rules.rs @@ -8,7 +8,7 @@ mod m1 { use legacy_macro as _; // OK pub(crate) use legacy_macro as _; // OK - pub use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported + pub use legacy_macro as _; //~ ERROR `legacy_macro` is only public within the crate, and cannot be re-exported outside } mod m2 { diff --git a/src/test/ui/rust-2018/uniform-paths/macro-rules.stderr b/src/test/ui/rust-2018/uniform-paths/macro-rules.stderr index 622595bfa0328..9e48e26b1dfd3 100644 --- a/src/test/ui/rust-2018/uniform-paths/macro-rules.stderr +++ b/src/test/ui/rust-2018/uniform-paths/macro-rules.stderr @@ -1,4 +1,4 @@ -error[E0364]: `legacy_macro` is private, and cannot be re-exported +error[E0364]: `legacy_macro` is only public within the crate, and cannot be re-exported outside --> $DIR/macro-rules.rs:11:13 | LL | pub use legacy_macro as _;