From 743ad07c4b267bc5806a455b51ff07b3012591cc Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 5 Aug 2022 15:41:42 +0400 Subject: [PATCH] Improve diagnostics for `const a: = expr;` --- compiler/rustc_parse/src/parser/item.rs | 30 ++++++++++++------- compiler/rustc_typeck/src/collect/type_of.rs | 5 +++- src/test/ui/attributes/issue-90873.stderr | 4 +-- .../issue-69396-const-no-type-in-macro.stderr | 14 ++++----- src/test/ui/parser/issues/issue-89574.stderr | 4 +-- ...em-free-const-no-body-semantic-fail.stderr | 4 +-- ...m-free-static-no-body-semantic-fail.stderr | 8 ++--- .../ui/parser/removed-syntax-static-fn.stderr | 4 +-- src/test/ui/suggestions/const-no-type.rs | 14 ++++----- src/test/ui/suggestions/const-no-type.stderr | 28 ++++++++--------- .../ui/suggestions/unnamable-types.stderr | 20 ++++++------- src/test/ui/typeck/issue-100164.fixed | 9 ++++++ src/test/ui/typeck/issue-100164.rs | 9 ++++++ src/test/ui/typeck/issue-100164.stderr | 14 +++++++++ src/test/ui/typeck/issue-79040.stderr | 4 +-- .../typeck_type_placeholder_item.stderr | 4 +-- 16 files changed, 109 insertions(+), 66 deletions(-) create mode 100644 src/test/ui/typeck/issue-100164.fixed create mode 100644 src/test/ui/typeck/issue-100164.rs create mode 100644 src/test/ui/typeck/issue-100164.stderr diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 2c1e5807aa7f9..0d175c5c89323 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1179,10 +1179,11 @@ impl<'a> Parser<'a> { // Parse the type of a `const` or `static mut?` item. // That is, the `":" $ty` fragment. - let ty = if self.eat(&token::Colon) { - self.parse_ty()? - } else { - self.recover_missing_const_type(id, m) + let ty = match (self.eat(&token::Colon), self.check(&token::Eq) | self.check(&token::Semi)) + { + // If there wasn't a `:` or the colon was followed by a `=` or `;` recover a missing type. + (true, false) => self.parse_ty()?, + (colon, _) => self.recover_missing_const_type(colon, m), }; let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None }; @@ -1190,9 +1191,9 @@ impl<'a> Parser<'a> { Ok((id, ty, expr)) } - /// We were supposed to parse `:` but the `:` was missing. + /// We were supposed to parse `":" $ty` but the `:` or the type was missing. /// This means that the type is missing. - fn recover_missing_const_type(&mut self, id: Ident, m: Option) -> P { + fn recover_missing_const_type(&mut self, colon_present: bool, m: Option) -> P { // Construct the error and stash it away with the hope // that typeck will later enrich the error with a type. let kind = match m { @@ -1200,18 +1201,25 @@ impl<'a> Parser<'a> { Some(Mutability::Not) => "static", None => "const", }; - let mut err = self.struct_span_err(id.span, &format!("missing type for `{kind}` item")); + + let colon = match colon_present { + true => "", + false => ":", + }; + + let span = self.prev_token.span.shrink_to_hi(); + let mut err = self.struct_span_err(span, &format!("missing type for `{kind}` item")); err.span_suggestion( - id.span, + span, "provide a type for the item", - format!("{id}: "), + format!("{colon} "), Applicability::HasPlaceholders, ); - err.stash(id.span, StashKey::ItemNoType); + err.stash(span, StashKey::ItemNoType); // The user intended that the type be inferred, // so treat this as if the user wrote e.g. `const A: _ = expr;`. - P(Ty { kind: TyKind::Infer, span: id.span, id: ast::DUMMY_NODE_ID, tokens: None }) + P(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID, tokens: None }) } /// Parses an enum declaration. diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 534ddfa9531c1..f1dbe64f13abb 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -801,6 +801,9 @@ fn infer_placeholder_type<'a>( match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) { Some(mut err) => { if !ty.references_error() { + // Only suggest adding `:` if it was missing (and suggested by parsing diagnostic) + let colon = if span == item_ident.span.shrink_to_hi() { ":" } else { "" }; + // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type. // We are typeck and have the real type, so remove that and suggest the actual type. // FIXME(eddyb) this looks like it should be functionality on `Diagnostic`. @@ -816,7 +819,7 @@ fn infer_placeholder_type<'a>( err.span_suggestion( span, &format!("provide a type for the {item}", item = kind), - format!("{}: {}", item_ident, sugg_ty), + format!("{colon} {sugg_ty}"), Applicability::MachineApplicable, ); } else { diff --git a/src/test/ui/attributes/issue-90873.stderr b/src/test/ui/attributes/issue-90873.stderr index 0852bb7ca8b92..894ec8341f8e0 100644 --- a/src/test/ui/attributes/issue-90873.stderr +++ b/src/test/ui/attributes/issue-90873.stderr @@ -34,10 +34,10 @@ LL | #![a={impl std::ops::Neg for i8 {}}] | ^ consider adding a `main` function to `$DIR/issue-90873.rs` error: missing type for `static` item - --> $DIR/issue-90873.rs:1:16 + --> $DIR/issue-90873.rs:1:17 | LL | #![u=||{static d=||1;}] - | ^ help: provide a type for the item: `d: ` + | ^ help: provide a type for the item: `: ` error: aborting due to 6 previous errors diff --git a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr index e5ab65169ce3b..f581429a28154 100644 --- a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr +++ b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr @@ -17,10 +17,10 @@ LL | | } = note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) error: missing type for `const` item - --> $DIR/issue-69396-const-no-type-in-macro.rs:4:19 + --> $DIR/issue-69396-const-no-type-in-macro.rs:4:20 | LL | const A = "A".$fn(); - | ^ help: provide a type for the constant: `A: usize` + | ^ help: provide a type for the constant: `: usize` ... LL | / suite! { LL | | len; @@ -31,13 +31,13 @@ LL | | } = note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/issue-69396-const-no-type-in-macro.rs:4:19 + --> $DIR/issue-69396-const-no-type-in-macro.rs:4:20 | LL | const A = "A".$fn(); - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `bool` + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `bool` ... LL | / suite! { LL | | len; diff --git a/src/test/ui/parser/issues/issue-89574.stderr b/src/test/ui/parser/issues/issue-89574.stderr index cbee3d35155c7..fb1312c782aab 100644 --- a/src/test/ui/parser/issues/issue-89574.stderr +++ b/src/test/ui/parser/issues/issue-89574.stderr @@ -1,8 +1,8 @@ error: missing type for `const` item - --> $DIR/issue-89574.rs:2:11 + --> $DIR/issue-89574.rs:2:22 | LL | const EMPTY_ARRAY = []; - | ^^^^^^^^^^^ help: provide a type for the item: `EMPTY_ARRAY: ` + | ^ help: provide a type for the item: `: ` error: aborting due to previous error diff --git a/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr b/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr index c340e958ee585..5365b0a1f8242 100644 --- a/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr +++ b/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr @@ -15,10 +15,10 @@ LL | const B; | help: provide a definition for the constant: `= ;` error: missing type for `const` item - --> $DIR/item-free-const-no-body-semantic-fail.rs:6:7 + --> $DIR/item-free-const-no-body-semantic-fail.rs:6:8 | LL | const B; - | ^ help: provide a type for the item: `B: ` + | ^ help: provide a type for the item: `: ` error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr b/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr index 4d542b79861fd..1b61e430546e0 100644 --- a/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr +++ b/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr @@ -31,16 +31,16 @@ LL | static mut D; | help: provide a definition for the static: `= ;` error: missing type for `static` item - --> $DIR/item-free-static-no-body-semantic-fail.rs:6:8 + --> $DIR/item-free-static-no-body-semantic-fail.rs:6:9 | LL | static B; - | ^ help: provide a type for the item: `B: ` + | ^ help: provide a type for the item: `: ` error: missing type for `static mut` item - --> $DIR/item-free-static-no-body-semantic-fail.rs:10:12 + --> $DIR/item-free-static-no-body-semantic-fail.rs:10:13 | LL | static mut D; - | ^ help: provide a type for the item: `D: ` + | ^ help: provide a type for the item: `: ` error: aborting due to 6 previous errors diff --git a/src/test/ui/parser/removed-syntax-static-fn.stderr b/src/test/ui/parser/removed-syntax-static-fn.stderr index 04e34dc16a842..52e0658949d3d 100644 --- a/src/test/ui/parser/removed-syntax-static-fn.stderr +++ b/src/test/ui/parser/removed-syntax-static-fn.stderr @@ -16,10 +16,10 @@ LL | } | - the item list ends here error: missing type for `static` item - --> $DIR/removed-syntax-static-fn.rs:4:12 + --> $DIR/removed-syntax-static-fn.rs:4:14 | LL | static fn f() {} - | ^^ help: provide a type for the item: `r#fn: ` + | ^ help: provide a type for the item: `: ` error: aborting due to 3 previous errors diff --git a/src/test/ui/suggestions/const-no-type.rs b/src/test/ui/suggestions/const-no-type.rs index 6f46cfdf02467..c6fdcdadbeafc 100644 --- a/src/test/ui/suggestions/const-no-type.rs +++ b/src/test/ui/suggestions/const-no-type.rs @@ -14,38 +14,38 @@ fn main() {} const C2 = 42; //~^ ERROR missing type for `const` item //~| HELP provide a type for the item -//~| SUGGESTION C2: +//~| SUGGESTION : #[cfg(FALSE)] static S2 = "abc"; //~^ ERROR missing type for `static` item //~| HELP provide a type for the item -//~| SUGGESTION S2: +//~| SUGGESTION : #[cfg(FALSE)] static mut SM2 = "abc"; //~^ ERROR missing type for `static mut` item //~| HELP provide a type for the item -//~| SUGGESTION SM2: +//~| SUGGESTION : // These will, so the diagnostics should be stolen by typeck: const C = 42; //~^ ERROR missing type for `const` item //~| HELP provide a type for the constant -//~| SUGGESTION C: i32 +//~| SUGGESTION : i32 const D = &&42; //~^ ERROR missing type for `const` item //~| HELP provide a type for the constant -//~| SUGGESTION D: &&i32 +//~| SUGGESTION : &&i32 static S = Vec::::new(); //~^ ERROR missing type for `static` item //~| HELP provide a type for the static variable -//~| SUGGESTION S: Vec +//~| SUGGESTION : Vec static mut SM = "abc"; //~^ ERROR missing type for `static mut` item //~| HELP provide a type for the static variable -//~| SUGGESTION &str +//~| SUGGESTION : &str diff --git a/src/test/ui/suggestions/const-no-type.stderr b/src/test/ui/suggestions/const-no-type.stderr index 3b0fd6337f1f1..bd703992fd4a6 100644 --- a/src/test/ui/suggestions/const-no-type.stderr +++ b/src/test/ui/suggestions/const-no-type.stderr @@ -1,44 +1,44 @@ error: missing type for `const` item - --> $DIR/const-no-type.rs:33:7 + --> $DIR/const-no-type.rs:33:8 | LL | const C = 42; - | ^ help: provide a type for the constant: `C: i32` + | ^ help: provide a type for the constant: `: i32` error: missing type for `const` item - --> $DIR/const-no-type.rs:38:7 + --> $DIR/const-no-type.rs:38:8 | LL | const D = &&42; - | ^ help: provide a type for the constant: `D: &&i32` + | ^ help: provide a type for the constant: `: &&i32` error: missing type for `static` item - --> $DIR/const-no-type.rs:43:8 + --> $DIR/const-no-type.rs:43:9 | LL | static S = Vec::::new(); - | ^ help: provide a type for the static variable: `S: Vec` + | ^ help: provide a type for the static variable: `: Vec` error: missing type for `static mut` item - --> $DIR/const-no-type.rs:48:12 + --> $DIR/const-no-type.rs:48:14 | LL | static mut SM = "abc"; - | ^^ help: provide a type for the static variable: `SM: &str` + | ^ help: provide a type for the static variable: `: &str` error: missing type for `const` item - --> $DIR/const-no-type.rs:14:7 + --> $DIR/const-no-type.rs:14:9 | LL | const C2 = 42; - | ^^ help: provide a type for the item: `C2: ` + | ^ help: provide a type for the item: `: ` error: missing type for `static` item - --> $DIR/const-no-type.rs:20:8 + --> $DIR/const-no-type.rs:20:10 | LL | static S2 = "abc"; - | ^^ help: provide a type for the item: `S2: ` + | ^ help: provide a type for the item: `: ` error: missing type for `static mut` item - --> $DIR/const-no-type.rs:26:12 + --> $DIR/const-no-type.rs:26:15 | LL | static mut SM2 = "abc"; - | ^^^ help: provide a type for the item: `SM2: ` + | ^ help: provide a type for the item: `: ` error: aborting due to 7 previous errors diff --git a/src/test/ui/suggestions/unnamable-types.stderr b/src/test/ui/suggestions/unnamable-types.stderr index de64269d1f191..ede3ebfa739c4 100644 --- a/src/test/ui/suggestions/unnamable-types.stderr +++ b/src/test/ui/suggestions/unnamable-types.stderr @@ -1,8 +1,8 @@ error: missing type for `const` item - --> $DIR/unnamable-types.rs:6:7 + --> $DIR/unnamable-types.rs:6:8 | LL | const A = 5; - | ^ help: provide a type for the constant: `A: i32` + | ^ help: provide a type for the constant: `: i32` error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/unnamable-types.rs:10:11 @@ -26,10 +26,10 @@ LL | const C: _ = || 42; | ^^^^^ error: missing type for `const` item - --> $DIR/unnamable-types.rs:23:7 + --> $DIR/unnamable-types.rs:23:8 | LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; - | ^ + | ^ | note: however, the inferred type `S<[closure@$DIR/unnamable-types.rs:23:31: 23:45]>` cannot be named --> $DIR/unnamable-types.rs:23:11 @@ -38,22 +38,22 @@ LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing type for `const` item - --> $DIR/unnamable-types.rs:29:7 + --> $DIR/unnamable-types.rs:29:8 | LL | const E = foo; - | ^ help: provide a type for the constant: `E: fn() -> i32` + | ^ help: provide a type for the constant: `: fn() -> i32` error: missing type for `const` item - --> $DIR/unnamable-types.rs:32:7 + --> $DIR/unnamable-types.rs:32:8 | LL | const F = S { t: foo }; - | ^ help: provide a type for the constant: `F: S i32>` + | ^ help: provide a type for the constant: `: S i32>` error: missing type for `const` item - --> $DIR/unnamable-types.rs:37:7 + --> $DIR/unnamable-types.rs:37:8 | LL | const G = || -> i32 { yield 0; return 1; }; - | ^ + | ^ | note: however, the inferred type `[generator@$DIR/unnamable-types.rs:37:11: 37:20]` cannot be named --> $DIR/unnamable-types.rs:37:11 diff --git a/src/test/ui/typeck/issue-100164.fixed b/src/test/ui/typeck/issue-100164.fixed new file mode 100644 index 0000000000000..a5f68beb1d522 --- /dev/null +++ b/src/test/ui/typeck/issue-100164.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +const _A: i32 = 123; +//~^ ERROR: missing type for `const` item + +fn main() { + const _B: i32 = 123; + //~^ ERROR: missing type for `const` item +} diff --git a/src/test/ui/typeck/issue-100164.rs b/src/test/ui/typeck/issue-100164.rs new file mode 100644 index 0000000000000..7efb9ac624042 --- /dev/null +++ b/src/test/ui/typeck/issue-100164.rs @@ -0,0 +1,9 @@ +// run-rustfix + +const _A: = 123; +//~^ ERROR: missing type for `const` item + +fn main() { + const _B: = 123; + //~^ ERROR: missing type for `const` item +} diff --git a/src/test/ui/typeck/issue-100164.stderr b/src/test/ui/typeck/issue-100164.stderr new file mode 100644 index 0000000000000..06a132d651429 --- /dev/null +++ b/src/test/ui/typeck/issue-100164.stderr @@ -0,0 +1,14 @@ +error: missing type for `const` item + --> $DIR/issue-100164.rs:3:10 + | +LL | const _A: = 123; + | ^ help: provide a type for the constant: `i32` + +error: missing type for `const` item + --> $DIR/issue-100164.rs:7:14 + | +LL | const _B: = 123; + | ^ help: provide a type for the constant: `i32` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/typeck/issue-79040.stderr b/src/test/ui/typeck/issue-79040.stderr index aec2e1ec9e4ef..c820d1e08c4ad 100644 --- a/src/test/ui/typeck/issue-79040.stderr +++ b/src/test/ui/typeck/issue-79040.stderr @@ -7,10 +7,10 @@ LL | const FOO = "hello" + 1; | &str error: missing type for `const` item - --> $DIR/issue-79040.rs:2:11 + --> $DIR/issue-79040.rs:2:14 | LL | const FOO = "hello" + 1; - | ^^^ help: provide a type for the item: `FOO: ` + | ^ help: provide a type for the item: `: ` error: aborting due to 2 previous errors diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index 3ea317dfb1a5d..c57f71b8057a9 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -189,10 +189,10 @@ LL ~ b: (T, T), | error: missing type for `static` item - --> $DIR/typeck_type_placeholder_item.rs:73:12 + --> $DIR/typeck_type_placeholder_item.rs:73:13 | LL | static A = 42; - | ^ help: provide a type for the static variable: `A: i32` + | ^ help: provide a type for the static variable: `: i32` error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:75:15