Skip to content

Commit

Permalink
Rollup merge of #102927 - compiler-errors:let, r=davidtwco
Browse files Browse the repository at this point in the history
Fix `let` keyword removal suggestion in structs

(1.) Fixes a bug where, given this code:
```rust
struct Foo {
  let x: i32,
}
```

We were parsing the field name as `let` instead of `x`, which causes issues later on in the type-checking phase.

(2.) Also, suggestions for `let: i32` as a field regressed, displaying this extra `help:` which is removed by this PR

```
help: remove the let, the `let` keyword is not allowed in struct field definitions
  |
2 -     let: i32,
2 +     : i32,
```

(3.) Makes the suggestion text a bit more succinct, since we don't need to re-explain that `let` is not allowed in this position (since it's in a note that follows). This causes the suggestion to render inline as well.

cc `@gimbles,` this addresses a few nits I mentioned in your PR.
  • Loading branch information
Dylan-DPC authored Oct 12, 2022
2 parents 117a98c + f9d3c83 commit a9a5529
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 12 deletions.
17 changes: 11 additions & 6 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1789,20 +1789,25 @@ impl<'a> Parser<'a> {
}
} else {
let mut err = self.expected_ident_found();
if let Some((ident, _)) = self.token.ident() && ident.as_str() == "let" {
self.bump(); // `let`
let span = self.prev_token.span.until(self.token.span);
if self.eat_keyword_noexpect(kw::Let)
&& let removal_span = self.prev_token.span.until(self.token.span)
&& let Ok(ident) = self.parse_ident_common(false)
// Cancel this error, we don't need it.
.map_err(|err| err.cancel())
&& self.token.kind == TokenKind::Colon
{
err.span_suggestion(
span,
"remove the let, the `let` keyword is not allowed in struct field definitions",
removal_span,
"remove this `let` keyword",
String::new(),
Applicability::MachineApplicable,
);
err.note("the `let` keyword is not allowed in `struct` fields");
err.note("see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information");
err.emit();
self.bump();
return Ok(ident);
} else {
self.restore_snapshot(snapshot);
}
err
};
Expand Down
6 changes: 6 additions & 0 deletions src/test/ui/parser/bad-let-as-field.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
struct Foo {
let: i32,
//~^ ERROR expected identifier, found keyword
}

fn main() {}
15 changes: 15 additions & 0 deletions src/test/ui/parser/bad-let-as-field.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: expected identifier, found keyword `let`
--> $DIR/bad-let-as-field.rs:2:5
|
LL | struct Foo {
| --- while parsing this struct
LL | let: i32,
| ^^^ expected identifier, found keyword
|
help: escape `let` to use it as an identifier
|
LL | r#let: i32,
| ++

error: aborting due to previous error

12 changes: 12 additions & 0 deletions src/test/ui/parser/removed-syntax-field-let-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
struct Foo {
let x: i32,
//~^ ERROR expected identifier, found keyword
let y: i32,
//~^ ERROR expected identifier, found keyword
}

fn main() {
let _ = Foo {
//~^ ERROR missing fields `x` and `y` in initializer of `Foo`
};
}
33 changes: 33 additions & 0 deletions src/test/ui/parser/removed-syntax-field-let-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
error: expected identifier, found keyword `let`
--> $DIR/removed-syntax-field-let-2.rs:2:5
|
LL | let x: i32,
| ^^^-
| |
| expected identifier, found keyword
| help: remove this `let` keyword
|
= note: the `let` keyword is not allowed in `struct` fields
= note: see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information

error: expected identifier, found keyword `let`
--> $DIR/removed-syntax-field-let-2.rs:4:5
|
LL | let y: i32,
| ^^^-
| |
| expected identifier, found keyword
| help: remove this `let` keyword
|
= note: the `let` keyword is not allowed in `struct` fields
= note: see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information

error[E0063]: missing fields `x` and `y` in initializer of `Foo`
--> $DIR/removed-syntax-field-let-2.rs:9:13
|
LL | let _ = Foo {
| ^^^ missing `x` and `y`

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0063`.
10 changes: 4 additions & 6 deletions src/test/ui/parser/removed-syntax-field-let.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ error: expected identifier, found keyword `let`
--> $DIR/removed-syntax-field-let.rs:2:5
|
LL | let foo: (),
| ^^^ expected identifier, found keyword
| ^^^-
| |
| expected identifier, found keyword
| help: remove this `let` keyword
|
= note: the `let` keyword is not allowed in `struct` fields
= note: see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information
help: remove the let, the `let` keyword is not allowed in struct field definitions
|
LL - let foo: (),
LL + foo: (),
|

error: aborting due to previous error

0 comments on commit a9a5529

Please sign in to comment.