about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Wood <david@davidtw.co>2019-04-20 11:31:38 +0100
committerDavid Wood <david@davidtw.co>2019-04-20 11:36:04 +0100
commit60c6ed9664e8d6fa30388290d5fe86eb80bc6fc7 (patch)
tree54080badf103398e605f4f6dc8a7e767c2890dbe
parentd6f513ec7d1e83c8689f94fb48686dd11f1d1c80 (diff)
Fix fn front matter parsing ICE from invalid code.
This commit fixes an "unreachable code" ICE that results from parsing
invalid code where the compiler is expecting the next trait item
declaration in the middle of the previous trait item due to extra
closing braces.
-rw-r--r--src/libsyntax/parse/parser.rs7
-rw-r--r--src/test/ui/issue-60075.rs12
-rw-r--r--src/test/ui/issue-60075.stderr37
3 files changed, 55 insertions, 1 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a5adb37f745..8e6db8a541a 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -6575,7 +6575,12 @@ impl<'a> Parser<'a> {
             };
             (respan(self.prev_span, Constness::NotConst), unsafety, abi)
         };
-        self.expect_keyword(keywords::Fn)?;
+        if !self.eat_keyword(keywords::Fn) {
+            // It is possible for `expect_one_of` to recover given the contents of
+            // `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't
+            // account for this.
+            if !self.expect_one_of(&[], &[])? { unreachable!() }
+        }
         Ok((constness, unsafety, asyncness, abi))
     }
 
diff --git a/src/test/ui/issue-60075.rs b/src/test/ui/issue-60075.rs
new file mode 100644
index 00000000000..5788716a526
--- /dev/null
+++ b/src/test/ui/issue-60075.rs
@@ -0,0 +1,12 @@
+fn main() {}
+
+trait T {
+    fn qux() -> Option<usize> {
+        let _ = if true {
+        });
+//~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `;`
+//~^^ ERROR expected one of `.`, `;`, `?`, `else`, or an operator, found `}`
+//~^^^ ERROR 6:11: 6:12: expected identifier, found `;`
+//~^^^^ ERROR missing `fn`, `type`, or `const` for trait-item declaration
+        Some(4)
+    }
diff --git a/src/test/ui/issue-60075.stderr b/src/test/ui/issue-60075.stderr
new file mode 100644
index 00000000000..244aef2d1f0
--- /dev/null
+++ b/src/test/ui/issue-60075.stderr
@@ -0,0 +1,37 @@
+error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}`
+  --> $DIR/issue-60075.rs:6:10
+   |
+LL |         });
+   |          ^ expected one of `.`, `;`, `?`, `else`, or an operator here
+
+error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `;`
+  --> $DIR/issue-60075.rs:6:11
+   |
+LL |     fn qux() -> Option<usize> {
+   |                               - unclosed delimiter
+LL |         let _ = if true {
+LL |         });
+   |           ^
+   |           |
+   |           help: `}` may belong here
+
+error: expected identifier, found `;`
+  --> $DIR/issue-60075.rs:6:11
+   |
+LL |         });
+   |           ^ expected identifier
+
+error: missing `fn`, `type`, or `const` for trait-item declaration
+  --> $DIR/issue-60075.rs:6:12
+   |
+LL |           });
+   |  ____________^
+LL | |
+LL | |
+LL | |
+LL | |
+LL | |         Some(4)
+   | |________^ missing `fn`, `type`, or `const`
+
+error: aborting due to 4 previous errors
+