about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-10-12 22:13:26 +0530
committerGitHub <noreply@github.com>2022-10-12 22:13:26 +0530
commita9a5529eac770084cea00d786ad572e130112ddd (patch)
tree2d01aa77fd2bb4059fc276497f62b5d8086dd767
parent117a98c5ceec27ef909bf95e62d079529ce24a82 (diff)
parentf9d3c8352660451cb14df831002eb1ec514e59e6 (diff)
downloadrust-a9a5529eac770084cea00d786ad572e130112ddd.tar.gz
rust-a9a5529eac770084cea00d786ad572e130112ddd.zip
Rollup merge of #102927 - compiler-errors:let, r=davidtwco
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.
-rw-r--r--compiler/rustc_parse/src/parser/item.rs17
-rw-r--r--src/test/ui/parser/bad-let-as-field.rs6
-rw-r--r--src/test/ui/parser/bad-let-as-field.stderr15
-rw-r--r--src/test/ui/parser/removed-syntax-field-let-2.rs12
-rw-r--r--src/test/ui/parser/removed-syntax-field-let-2.stderr33
-rw-r--r--src/test/ui/parser/removed-syntax-field-let.stderr10
6 files changed, 81 insertions, 12 deletions
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index e82044a89c4..ebcbc75ba32 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -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
             };
diff --git a/src/test/ui/parser/bad-let-as-field.rs b/src/test/ui/parser/bad-let-as-field.rs
new file mode 100644
index 00000000000..fec2bc25617
--- /dev/null
+++ b/src/test/ui/parser/bad-let-as-field.rs
@@ -0,0 +1,6 @@
+struct Foo {
+    let: i32,
+    //~^ ERROR expected identifier, found keyword
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/bad-let-as-field.stderr b/src/test/ui/parser/bad-let-as-field.stderr
new file mode 100644
index 00000000000..57def42b1ee
--- /dev/null
+++ b/src/test/ui/parser/bad-let-as-field.stderr
@@ -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
+
diff --git a/src/test/ui/parser/removed-syntax-field-let-2.rs b/src/test/ui/parser/removed-syntax-field-let-2.rs
new file mode 100644
index 00000000000..7ff91b476ae
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-field-let-2.rs
@@ -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`
+    };
+}
diff --git a/src/test/ui/parser/removed-syntax-field-let-2.stderr b/src/test/ui/parser/removed-syntax-field-let-2.stderr
new file mode 100644
index 00000000000..fda0919b9b6
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-field-let-2.stderr
@@ -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`.
diff --git a/src/test/ui/parser/removed-syntax-field-let.stderr b/src/test/ui/parser/removed-syntax-field-let.stderr
index bd1b23f7e3b..9bc18dabd6e 100644
--- a/src/test/ui/parser/removed-syntax-field-let.stderr
+++ b/src/test/ui/parser/removed-syntax-field-let.stderr
@@ -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