Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve diagnostics for const a: = expr; #100168

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 19 additions & 11 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1179,39 +1179,47 @@ 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 };
self.expect_semi()?;
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<Mutability>) -> P<Ty> {
fn recover_missing_const_type(&mut self, colon_present: bool, m: Option<Mutability>) -> P<Ty> {
// Construct the error and stash it away with the hope
// that typeck will later enrich the error with a type.
let kind = match m {
Some(Mutability::Mut) => "static mut",
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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

match bool 💀

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}: <type>"),
format!("{colon} <type>"),
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.
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_typeck/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand All @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/attributes/issue-90873.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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: <type>`
| ^ help: provide a type for the item: `: <type>`

error: aborting due to 6 previous errors

Expand Down
14 changes: 7 additions & 7 deletions src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Copy link
Contributor

@klensy klensy Aug 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks kinda off, IMHO: suggestion talks about type but suggest not var+type, not type, but something in between: colon+type.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think old style is better, and also seems more consistant with other suggestions in rustc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If anything this could be fixed by bumping to a verbose diagnostic, but I don't think this is necessarily a regression.

...
LL | / suite! {
LL | | len;
Expand All @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/parser/issues/issue-89574.stderr
Original file line number Diff line number Diff line change
@@ -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: <type>`
| ^ help: provide a type for the item: `: <type>`

error: aborting due to previous error

Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ LL | const B;
| help: provide a definition for the constant: `= <expr>;`

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: <type>`
| ^ help: provide a type for the item: `: <type>`

error: aborting due to 3 previous errors

Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ LL | static mut D;
| help: provide a definition for the static: `= <expr>;`

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: <type>`
| ^ help: provide a type for the item: `: <type>`

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: <type>`
| ^ help: provide a type for the item: `: <type>`

error: aborting due to 6 previous errors

4 changes: 2 additions & 2 deletions src/test/ui/parser/removed-syntax-static-fn.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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: <type>`
| ^ help: provide a type for the item: `: <type>`

error: aborting due to 3 previous errors

14 changes: 7 additions & 7 deletions src/test/ui/suggestions/const-no-type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,38 @@ fn main() {}
const C2 = 42;
//~^ ERROR missing type for `const` item
//~| HELP provide a type for the item
//~| SUGGESTION C2: <type>
//~| SUGGESTION : <type>

#[cfg(FALSE)]
static S2 = "abc";
//~^ ERROR missing type for `static` item
//~| HELP provide a type for the item
//~| SUGGESTION S2: <type>
//~| SUGGESTION : <type>

#[cfg(FALSE)]
static mut SM2 = "abc";
//~^ ERROR missing type for `static mut` item
//~| HELP provide a type for the item
//~| SUGGESTION SM2: <type>
//~| SUGGESTION : <type>

// 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::<String>::new();
//~^ ERROR missing type for `static` item
//~| HELP provide a type for the static variable
//~| SUGGESTION S: Vec<String>
//~| SUGGESTION : Vec<String>

static mut SM = "abc";
//~^ ERROR missing type for `static mut` item
//~| HELP provide a type for the static variable
//~| SUGGESTION &str
//~| SUGGESTION : &str
28 changes: 14 additions & 14 deletions src/test/ui/suggestions/const-no-type.stderr
Original file line number Diff line number Diff line change
@@ -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::<String>::new();
| ^ help: provide a type for the static variable: `S: Vec<String>`
| ^ help: provide a type for the static variable: `: Vec<String>`

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: <type>`
| ^ help: provide a type for the item: `: <type>`

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: <type>`
| ^ help: provide a type for the item: `: <type>`

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: <type>`
| ^ help: provide a type for the item: `: <type>`

error: aborting due to 7 previous errors

20 changes: 10 additions & 10 deletions src/test/ui/suggestions/unnamable-types.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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<fn() -> i32>`
| ^ help: provide a type for the constant: `: S<fn() -> 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
Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/typeck/issue-100164.fixed
Original file line number Diff line number Diff line change
@@ -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
}
9 changes: 9 additions & 0 deletions src/test/ui/typeck/issue-100164.rs
Original file line number Diff line number Diff line change
@@ -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
}
14 changes: 14 additions & 0 deletions src/test/ui/typeck/issue-100164.stderr
Original file line number Diff line number Diff line change
@@ -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

4 changes: 2 additions & 2 deletions src/test/ui/typeck/issue-79040.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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: <type>`
| ^ help: provide a type for the item: `: <type>`

error: aborting due to 2 previous errors

Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/typeck/typeck_type_placeholder_item.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down