about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTakayuki Maeda <takoyaki0316@gmail.com>2022-08-15 16:10:31 +0900
committerTakayuki Maeda <takoyaki0316@gmail.com>2022-08-15 16:10:31 +0900
commit40dcf89a26bde41734f6c3eb71d9eb6420e45ef8 (patch)
treef86f103a9e63e36a013d6f8c5c2b7b90b7b417fa
parent0068b8bf4b150b506ef0871be4e8652fd4308f84 (diff)
downloadrust-40dcf89a26bde41734f6c3eb71d9eb6420e45ef8.tar.gz
rust-40dcf89a26bde41734f6c3eb71d9eb6420e45ef8.zip
suggest adding a missing semicolon before an item
-rw-r--r--compiler/rustc_ast/src/token.rs24
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs6
-rw-r--r--src/test/ui/parser/recover-missing-semi-before-item.fixed61
-rw-r--r--src/test/ui/parser/recover-missing-semi-before-item.rs61
-rw-r--r--src/test/ui/parser/recover-missing-semi-before-item.stderr83
5 files changed, 233 insertions, 2 deletions
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 85d9687c600..dd98946b4cc 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -436,6 +436,30 @@ impl Token {
             || self == &OpenDelim(Delimiter::Parenthesis)
     }
 
+    /// Returns `true` if the token can appear at the start of an item.
+    pub fn can_begin_item(&self) -> bool {
+        match self.kind {
+            Ident(name, _) => [
+                kw::Fn,
+                kw::Use,
+                kw::Struct,
+                kw::Enum,
+                kw::Pub,
+                kw::Trait,
+                kw::Extern,
+                kw::Impl,
+                kw::Unsafe,
+                kw::Static,
+                kw::Union,
+                kw::Macro,
+                kw::Mod,
+                kw::Type,
+            ]
+            .contains(&name),
+            _ => false,
+        }
+    }
+
     /// Returns `true` if the token is any literal.
     pub fn is_lit(&self) -> bool {
         matches!(self.kind, Literal(..))
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index f4c6b33a529..d0fb768caa6 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -555,10 +555,12 @@ impl<'a> Parser<'a> {
                 return Ok(true);
             } else if self.look_ahead(0, |t| {
                 t == &token::CloseDelim(Delimiter::Brace)
-                    || (t.can_begin_expr() && t != &token::Semi && t != &token::Pound)
+                    || ((t.can_begin_expr() || t.can_begin_item())
+                        && t != &token::Semi
+                        && t != &token::Pound)
                     // Avoid triggering with too many trailing `#` in raw string.
                     || (sm.is_multiline(
-                        self.prev_token.span.shrink_to_hi().until(self.token.span.shrink_to_lo())
+                        self.prev_token.span.shrink_to_hi().until(self.token.span.shrink_to_lo()),
                     ) && t == &token::Pound)
             }) && !expected.contains(&TokenType::Token(token::Comma))
             {
diff --git a/src/test/ui/parser/recover-missing-semi-before-item.fixed b/src/test/ui/parser/recover-missing-semi-before-item.fixed
new file mode 100644
index 00000000000..0be17e69e8f
--- /dev/null
+++ b/src/test/ui/parser/recover-missing-semi-before-item.fixed
@@ -0,0 +1,61 @@
+// run-rustfix
+
+#![allow(unused_variables, dead_code)]
+
+fn for_struct() {
+    let foo = 3; //~ ERROR expected `;`, found keyword `struct`
+    struct Foo;
+}
+
+fn for_union() {
+    let foo = 3; //~ ERROR expected `;`, found `union`
+    union Foo {
+        foo: usize,
+    }
+}
+
+fn for_enum() {
+    let foo = 3; //~ ERROR expected `;`, found keyword `enum`
+    enum Foo {
+        Bar,
+    }
+}
+
+fn for_fn() {
+    let foo = 3; //~ ERROR expected `;`, found keyword `fn`
+    fn foo() {}
+}
+
+fn for_extern() {
+    let foo = 3; //~ ERROR expected `;`, found keyword `extern`
+    extern fn foo() {}
+}
+
+fn for_impl() {
+    struct Foo;
+    let foo = 3; //~ ERROR expected `;`, found keyword `impl`
+    impl Foo {}
+}
+
+fn for_use() {
+    let foo = 3; //~ ERROR expected `;`, found keyword `pub`
+    pub use bar::Bar;
+}
+
+fn for_mod() {
+    let foo = 3; //~ ERROR expected `;`, found keyword `mod`
+    mod foo {}
+}
+
+fn for_type() {
+    let foo = 3; //~ ERROR expected `;`, found keyword `type`
+    type Foo = usize;
+}
+
+mod bar {
+    pub struct Bar;
+}
+
+const X: i32 = 123; //~ ERROR expected `;`, found keyword `fn`
+
+fn main() {}
diff --git a/src/test/ui/parser/recover-missing-semi-before-item.rs b/src/test/ui/parser/recover-missing-semi-before-item.rs
new file mode 100644
index 00000000000..867b7b749bb
--- /dev/null
+++ b/src/test/ui/parser/recover-missing-semi-before-item.rs
@@ -0,0 +1,61 @@
+// run-rustfix
+
+#![allow(unused_variables, dead_code)]
+
+fn for_struct() {
+    let foo = 3 //~ ERROR expected `;`, found keyword `struct`
+    struct Foo;
+}
+
+fn for_union() {
+    let foo = 3 //~ ERROR expected `;`, found `union`
+    union Foo {
+        foo: usize,
+    }
+}
+
+fn for_enum() {
+    let foo = 3 //~ ERROR expected `;`, found keyword `enum`
+    enum Foo {
+        Bar,
+    }
+}
+
+fn for_fn() {
+    let foo = 3 //~ ERROR expected `;`, found keyword `fn`
+    fn foo() {}
+}
+
+fn for_extern() {
+    let foo = 3 //~ ERROR expected `;`, found keyword `extern`
+    extern fn foo() {}
+}
+
+fn for_impl() {
+    struct Foo;
+    let foo = 3 //~ ERROR expected `;`, found keyword `impl`
+    impl Foo {}
+}
+
+fn for_use() {
+    let foo = 3 //~ ERROR expected `;`, found keyword `pub`
+    pub use bar::Bar;
+}
+
+fn for_mod() {
+    let foo = 3 //~ ERROR expected `;`, found keyword `mod`
+    mod foo {}
+}
+
+fn for_type() {
+    let foo = 3 //~ ERROR expected `;`, found keyword `type`
+    type Foo = usize;
+}
+
+mod bar {
+    pub struct Bar;
+}
+
+const X: i32 = 123 //~ ERROR expected `;`, found keyword `fn`
+
+fn main() {}
diff --git a/src/test/ui/parser/recover-missing-semi-before-item.stderr b/src/test/ui/parser/recover-missing-semi-before-item.stderr
new file mode 100644
index 00000000000..61c43f2f189
--- /dev/null
+++ b/src/test/ui/parser/recover-missing-semi-before-item.stderr
@@ -0,0 +1,83 @@
+error: expected `;`, found keyword `struct`
+  --> $DIR/recover-missing-semi-before-item.rs:6:16
+   |
+LL |     let foo = 3
+   |                ^ help: add `;` here
+LL |     struct Foo;
+   |     ------ unexpected token
+
+error: expected `;`, found `union`
+  --> $DIR/recover-missing-semi-before-item.rs:11:16
+   |
+LL |     let foo = 3
+   |                ^ help: add `;` here
+LL |     union Foo {
+   |     ----- unexpected token
+
+error: expected `;`, found keyword `enum`
+  --> $DIR/recover-missing-semi-before-item.rs:18:16
+   |
+LL |     let foo = 3
+   |                ^ help: add `;` here
+LL |     enum Foo {
+   |     ---- unexpected token
+
+error: expected `;`, found keyword `fn`
+  --> $DIR/recover-missing-semi-before-item.rs:25:16
+   |
+LL |     let foo = 3
+   |                ^ help: add `;` here
+LL |     fn foo() {}
+   |     -- unexpected token
+
+error: expected `;`, found keyword `extern`
+  --> $DIR/recover-missing-semi-before-item.rs:30:16
+   |
+LL |     let foo = 3
+   |                ^ help: add `;` here
+LL |     extern fn foo() {}
+   |     ------ unexpected token
+
+error: expected `;`, found keyword `impl`
+  --> $DIR/recover-missing-semi-before-item.rs:36:16
+   |
+LL |     let foo = 3
+   |                ^ help: add `;` here
+LL |     impl Foo {}
+   |     ---- unexpected token
+
+error: expected `;`, found keyword `pub`
+  --> $DIR/recover-missing-semi-before-item.rs:41:16
+   |
+LL |     let foo = 3
+   |                ^ help: add `;` here
+LL |     pub use bar::Bar;
+   |     --- unexpected token
+
+error: expected `;`, found keyword `mod`
+  --> $DIR/recover-missing-semi-before-item.rs:46:16
+   |
+LL |     let foo = 3
+   |                ^ help: add `;` here
+LL |     mod foo {}
+   |     --- unexpected token
+
+error: expected `;`, found keyword `type`
+  --> $DIR/recover-missing-semi-before-item.rs:51:16
+   |
+LL |     let foo = 3
+   |                ^ help: add `;` here
+LL |     type Foo = usize;
+   |     ---- unexpected token
+
+error: expected `;`, found keyword `fn`
+  --> $DIR/recover-missing-semi-before-item.rs:59:19
+   |
+LL | const X: i32 = 123
+   |                   ^ help: add `;` here
+LL |
+LL | fn main() {}
+   | -- unexpected token
+
+error: aborting due to 10 previous errors
+