Skip to content

Commit e7ed844

Browse files
authored
Rollup merge of #100168 - WaffleLapkin:improve_diagnostics_for_missing_type_in_a_const_item, r=compiler-errors
Improve diagnostics for `const a: = expr;` Adds a suggestion to write a type when there is a colon, but the type is not present. I've also shrunk spans a little, so the suggestions are a little nicer. Resolves #100146 r? `@compiler-errors`
2 parents 404782d + 743ad07 commit e7ed844

16 files changed

+109
-66
lines changed

compiler/rustc_parse/src/parser/item.rs

+19-11
Original file line numberDiff line numberDiff line change
@@ -1179,39 +1179,47 @@ impl<'a> Parser<'a> {
11791179

11801180
// Parse the type of a `const` or `static mut?` item.
11811181
// That is, the `":" $ty` fragment.
1182-
let ty = if self.eat(&token::Colon) {
1183-
self.parse_ty()?
1184-
} else {
1185-
self.recover_missing_const_type(id, m)
1182+
let ty = match (self.eat(&token::Colon), self.check(&token::Eq) | self.check(&token::Semi))
1183+
{
1184+
// If there wasn't a `:` or the colon was followed by a `=` or `;` recover a missing type.
1185+
(true, false) => self.parse_ty()?,
1186+
(colon, _) => self.recover_missing_const_type(colon, m),
11861187
};
11871188

11881189
let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None };
11891190
self.expect_semi()?;
11901191
Ok((id, ty, expr))
11911192
}
11921193

1193-
/// We were supposed to parse `:` but the `:` was missing.
1194+
/// We were supposed to parse `":" $ty` but the `:` or the type was missing.
11941195
/// This means that the type is missing.
1195-
fn recover_missing_const_type(&mut self, id: Ident, m: Option<Mutability>) -> P<Ty> {
1196+
fn recover_missing_const_type(&mut self, colon_present: bool, m: Option<Mutability>) -> P<Ty> {
11961197
// Construct the error and stash it away with the hope
11971198
// that typeck will later enrich the error with a type.
11981199
let kind = match m {
11991200
Some(Mutability::Mut) => "static mut",
12001201
Some(Mutability::Not) => "static",
12011202
None => "const",
12021203
};
1203-
let mut err = self.struct_span_err(id.span, &format!("missing type for `{kind}` item"));
1204+
1205+
let colon = match colon_present {
1206+
true => "",
1207+
false => ":",
1208+
};
1209+
1210+
let span = self.prev_token.span.shrink_to_hi();
1211+
let mut err = self.struct_span_err(span, &format!("missing type for `{kind}` item"));
12041212
err.span_suggestion(
1205-
id.span,
1213+
span,
12061214
"provide a type for the item",
1207-
format!("{id}: <type>"),
1215+
format!("{colon} <type>"),
12081216
Applicability::HasPlaceholders,
12091217
);
1210-
err.stash(id.span, StashKey::ItemNoType);
1218+
err.stash(span, StashKey::ItemNoType);
12111219

12121220
// The user intended that the type be inferred,
12131221
// so treat this as if the user wrote e.g. `const A: _ = expr;`.
1214-
P(Ty { kind: TyKind::Infer, span: id.span, id: ast::DUMMY_NODE_ID, tokens: None })
1222+
P(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID, tokens: None })
12151223
}
12161224

12171225
/// Parses an enum declaration.

compiler/rustc_typeck/src/collect/type_of.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,9 @@ fn infer_placeholder_type<'a>(
801801
match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) {
802802
Some(mut err) => {
803803
if !ty.references_error() {
804+
// Only suggest adding `:` if it was missing (and suggested by parsing diagnostic)
805+
let colon = if span == item_ident.span.shrink_to_hi() { ":" } else { "" };
806+
804807
// The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
805808
// We are typeck and have the real type, so remove that and suggest the actual type.
806809
// FIXME(eddyb) this looks like it should be functionality on `Diagnostic`.
@@ -816,7 +819,7 @@ fn infer_placeholder_type<'a>(
816819
err.span_suggestion(
817820
span,
818821
&format!("provide a type for the {item}", item = kind),
819-
format!("{}: {}", item_ident, sugg_ty),
822+
format!("{colon} {sugg_ty}"),
820823
Applicability::MachineApplicable,
821824
);
822825
} else {

src/test/ui/attributes/issue-90873.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ LL | #![a={impl std::ops::Neg for i8 {}}]
3434
| ^ consider adding a `main` function to `$DIR/issue-90873.rs`
3535

3636
error: missing type for `static` item
37-
--> $DIR/issue-90873.rs:1:16
37+
--> $DIR/issue-90873.rs:1:17
3838
|
3939
LL | #![u=||{static d=||1;}]
40-
| ^ help: provide a type for the item: `d: <type>`
40+
| ^ help: provide a type for the item: `: <type>`
4141

4242
error: aborting due to 6 previous errors
4343

src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr

+7-7
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ LL | | }
1717
= note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info)
1818

1919
error: missing type for `const` item
20-
--> $DIR/issue-69396-const-no-type-in-macro.rs:4:19
20+
--> $DIR/issue-69396-const-no-type-in-macro.rs:4:20
2121
|
2222
LL | const A = "A".$fn();
23-
| ^ help: provide a type for the constant: `A: usize`
23+
| ^ help: provide a type for the constant: `: usize`
2424
...
2525
LL | / suite! {
2626
LL | | len;
@@ -31,13 +31,13 @@ LL | | }
3131
= note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info)
3232

3333
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
34-
--> $DIR/issue-69396-const-no-type-in-macro.rs:4:19
34+
--> $DIR/issue-69396-const-no-type-in-macro.rs:4:20
3535
|
3636
LL | const A = "A".$fn();
37-
| ^
38-
| |
39-
| not allowed in type signatures
40-
| help: replace with the correct type: `bool`
37+
| ^
38+
| |
39+
| not allowed in type signatures
40+
| help: replace with the correct type: `bool`
4141
...
4242
LL | / suite! {
4343
LL | | len;
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: missing type for `const` item
2-
--> $DIR/issue-89574.rs:2:11
2+
--> $DIR/issue-89574.rs:2:22
33
|
44
LL | const EMPTY_ARRAY = [];
5-
| ^^^^^^^^^^^ help: provide a type for the item: `EMPTY_ARRAY: <type>`
5+
| ^ help: provide a type for the item: `: <type>`
66

77
error: aborting due to previous error
88

src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ LL | const B;
1515
| help: provide a definition for the constant: `= <expr>;`
1616

1717
error: missing type for `const` item
18-
--> $DIR/item-free-const-no-body-semantic-fail.rs:6:7
18+
--> $DIR/item-free-const-no-body-semantic-fail.rs:6:8
1919
|
2020
LL | const B;
21-
| ^ help: provide a type for the item: `B: <type>`
21+
| ^ help: provide a type for the item: `: <type>`
2222

2323
error: aborting due to 3 previous errors
2424

src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,16 @@ LL | static mut D;
3131
| help: provide a definition for the static: `= <expr>;`
3232

3333
error: missing type for `static` item
34-
--> $DIR/item-free-static-no-body-semantic-fail.rs:6:8
34+
--> $DIR/item-free-static-no-body-semantic-fail.rs:6:9
3535
|
3636
LL | static B;
37-
| ^ help: provide a type for the item: `B: <type>`
37+
| ^ help: provide a type for the item: `: <type>`
3838

3939
error: missing type for `static mut` item
40-
--> $DIR/item-free-static-no-body-semantic-fail.rs:10:12
40+
--> $DIR/item-free-static-no-body-semantic-fail.rs:10:13
4141
|
4242
LL | static mut D;
43-
| ^ help: provide a type for the item: `D: <type>`
43+
| ^ help: provide a type for the item: `: <type>`
4444

4545
error: aborting due to 6 previous errors
4646

src/test/ui/parser/removed-syntax-static-fn.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ LL | }
1616
| - the item list ends here
1717

1818
error: missing type for `static` item
19-
--> $DIR/removed-syntax-static-fn.rs:4:12
19+
--> $DIR/removed-syntax-static-fn.rs:4:14
2020
|
2121
LL | static fn f() {}
22-
| ^^ help: provide a type for the item: `r#fn: <type>`
22+
| ^ help: provide a type for the item: `: <type>`
2323

2424
error: aborting due to 3 previous errors
2525

src/test/ui/suggestions/const-no-type.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -14,38 +14,38 @@ fn main() {}
1414
const C2 = 42;
1515
//~^ ERROR missing type for `const` item
1616
//~| HELP provide a type for the item
17-
//~| SUGGESTION C2: <type>
17+
//~| SUGGESTION : <type>
1818

1919
#[cfg(FALSE)]
2020
static S2 = "abc";
2121
//~^ ERROR missing type for `static` item
2222
//~| HELP provide a type for the item
23-
//~| SUGGESTION S2: <type>
23+
//~| SUGGESTION : <type>
2424

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

3131
// These will, so the diagnostics should be stolen by typeck:
3232

3333
const C = 42;
3434
//~^ ERROR missing type for `const` item
3535
//~| HELP provide a type for the constant
36-
//~| SUGGESTION C: i32
36+
//~| SUGGESTION : i32
3737

3838
const D = &&42;
3939
//~^ ERROR missing type for `const` item
4040
//~| HELP provide a type for the constant
41-
//~| SUGGESTION D: &&i32
41+
//~| SUGGESTION : &&i32
4242

4343
static S = Vec::<String>::new();
4444
//~^ ERROR missing type for `static` item
4545
//~| HELP provide a type for the static variable
46-
//~| SUGGESTION S: Vec<String>
46+
//~| SUGGESTION : Vec<String>
4747

4848
static mut SM = "abc";
4949
//~^ ERROR missing type for `static mut` item
5050
//~| HELP provide a type for the static variable
51-
//~| SUGGESTION &str
51+
//~| SUGGESTION : &str
+14-14
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,44 @@
11
error: missing type for `const` item
2-
--> $DIR/const-no-type.rs:33:7
2+
--> $DIR/const-no-type.rs:33:8
33
|
44
LL | const C = 42;
5-
| ^ help: provide a type for the constant: `C: i32`
5+
| ^ help: provide a type for the constant: `: i32`
66

77
error: missing type for `const` item
8-
--> $DIR/const-no-type.rs:38:7
8+
--> $DIR/const-no-type.rs:38:8
99
|
1010
LL | const D = &&42;
11-
| ^ help: provide a type for the constant: `D: &&i32`
11+
| ^ help: provide a type for the constant: `: &&i32`
1212

1313
error: missing type for `static` item
14-
--> $DIR/const-no-type.rs:43:8
14+
--> $DIR/const-no-type.rs:43:9
1515
|
1616
LL | static S = Vec::<String>::new();
17-
| ^ help: provide a type for the static variable: `S: Vec<String>`
17+
| ^ help: provide a type for the static variable: `: Vec<String>`
1818

1919
error: missing type for `static mut` item
20-
--> $DIR/const-no-type.rs:48:12
20+
--> $DIR/const-no-type.rs:48:14
2121
|
2222
LL | static mut SM = "abc";
23-
| ^^ help: provide a type for the static variable: `SM: &str`
23+
| ^ help: provide a type for the static variable: `: &str`
2424

2525
error: missing type for `const` item
26-
--> $DIR/const-no-type.rs:14:7
26+
--> $DIR/const-no-type.rs:14:9
2727
|
2828
LL | const C2 = 42;
29-
| ^^ help: provide a type for the item: `C2: <type>`
29+
| ^ help: provide a type for the item: `: <type>`
3030

3131
error: missing type for `static` item
32-
--> $DIR/const-no-type.rs:20:8
32+
--> $DIR/const-no-type.rs:20:10
3333
|
3434
LL | static S2 = "abc";
35-
| ^^ help: provide a type for the item: `S2: <type>`
35+
| ^ help: provide a type for the item: `: <type>`
3636

3737
error: missing type for `static mut` item
38-
--> $DIR/const-no-type.rs:26:12
38+
--> $DIR/const-no-type.rs:26:15
3939
|
4040
LL | static mut SM2 = "abc";
41-
| ^^^ help: provide a type for the item: `SM2: <type>`
41+
| ^ help: provide a type for the item: `: <type>`
4242

4343
error: aborting due to 7 previous errors
4444

src/test/ui/suggestions/unnamable-types.stderr

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: missing type for `const` item
2-
--> $DIR/unnamable-types.rs:6:7
2+
--> $DIR/unnamable-types.rs:6:8
33
|
44
LL | const A = 5;
5-
| ^ help: provide a type for the constant: `A: i32`
5+
| ^ help: provide a type for the constant: `: i32`
66

77
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
88
--> $DIR/unnamable-types.rs:10:11
@@ -26,10 +26,10 @@ LL | const C: _ = || 42;
2626
| ^^^^^
2727

2828
error: missing type for `const` item
29-
--> $DIR/unnamable-types.rs:23:7
29+
--> $DIR/unnamable-types.rs:23:8
3030
|
3131
LL | const D = S { t: { let i = 0; move || -> i32 { i } } };
32-
| ^
32+
| ^
3333
|
3434
note: however, the inferred type `S<[closure@$DIR/unnamable-types.rs:23:31: 23:45]>` cannot be named
3535
--> $DIR/unnamable-types.rs:23:11
@@ -38,22 +38,22 @@ LL | const D = S { t: { let i = 0; move || -> i32 { i } } };
3838
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3939

4040
error: missing type for `const` item
41-
--> $DIR/unnamable-types.rs:29:7
41+
--> $DIR/unnamable-types.rs:29:8
4242
|
4343
LL | const E = foo;
44-
| ^ help: provide a type for the constant: `E: fn() -> i32`
44+
| ^ help: provide a type for the constant: `: fn() -> i32`
4545

4646
error: missing type for `const` item
47-
--> $DIR/unnamable-types.rs:32:7
47+
--> $DIR/unnamable-types.rs:32:8
4848
|
4949
LL | const F = S { t: foo };
50-
| ^ help: provide a type for the constant: `F: S<fn() -> i32>`
50+
| ^ help: provide a type for the constant: `: S<fn() -> i32>`
5151

5252
error: missing type for `const` item
53-
--> $DIR/unnamable-types.rs:37:7
53+
--> $DIR/unnamable-types.rs:37:8
5454
|
5555
LL | const G = || -> i32 { yield 0; return 1; };
56-
| ^
56+
| ^
5757
|
5858
note: however, the inferred type `[generator@$DIR/unnamable-types.rs:37:11: 37:20]` cannot be named
5959
--> $DIR/unnamable-types.rs:37:11

src/test/ui/typeck/issue-100164.fixed

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// run-rustfix
2+
3+
const _A: i32 = 123;
4+
//~^ ERROR: missing type for `const` item
5+
6+
fn main() {
7+
const _B: i32 = 123;
8+
//~^ ERROR: missing type for `const` item
9+
}

src/test/ui/typeck/issue-100164.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// run-rustfix
2+
3+
const _A: = 123;
4+
//~^ ERROR: missing type for `const` item
5+
6+
fn main() {
7+
const _B: = 123;
8+
//~^ ERROR: missing type for `const` item
9+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: missing type for `const` item
2+
--> $DIR/issue-100164.rs:3:10
3+
|
4+
LL | const _A: = 123;
5+
| ^ help: provide a type for the constant: `i32`
6+
7+
error: missing type for `const` item
8+
--> $DIR/issue-100164.rs:7:14
9+
|
10+
LL | const _B: = 123;
11+
| ^ help: provide a type for the constant: `i32`
12+
13+
error: aborting due to 2 previous errors
14+

src/test/ui/typeck/issue-79040.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ LL | const FOO = "hello" + 1;
77
| &str
88

99
error: missing type for `const` item
10-
--> $DIR/issue-79040.rs:2:11
10+
--> $DIR/issue-79040.rs:2:14
1111
|
1212
LL | const FOO = "hello" + 1;
13-
| ^^^ help: provide a type for the item: `FOO: <type>`
13+
| ^ help: provide a type for the item: `: <type>`
1414

1515
error: aborting due to 2 previous errors
1616

src/test/ui/typeck/typeck_type_placeholder_item.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,10 @@ LL ~ b: (T, T),
189189
|
190190

191191
error: missing type for `static` item
192-
--> $DIR/typeck_type_placeholder_item.rs:73:12
192+
--> $DIR/typeck_type_placeholder_item.rs:73:13
193193
|
194194
LL | static A = 42;
195-
| ^ help: provide a type for the static variable: `A: i32`
195+
| ^ help: provide a type for the static variable: `: i32`
196196

197197
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
198198
--> $DIR/typeck_type_placeholder_item.rs:75:15

0 commit comments

Comments
 (0)