about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-04-21 07:20:14 +0000
committerbors <bors@rust-lang.org>2019-04-21 07:20:14 +0000
commit4d9c6cd7226e1839a195f1b6e7d40a3ccf9bb062 (patch)
tree57987160b517735c1654f387d18b1c24b35a4788 /src
parent9224be5fa39f6170f6e046342976efee5453a1ff (diff)
parent60c6ed9664e8d6fa30388290d5fe86eb80bc6fc7 (diff)
downloadrust-4d9c6cd7226e1839a195f1b6e7d40a3ccf9bb062.tar.gz
rust-4d9c6cd7226e1839a195f1b6e7d40a3ccf9bb062.zip
Auto merge of #60132 - davidtwco:issue-60075, r=estebank
Fix fn front matter parsing ICE from invalid code.

Fixes #60075.

This PR 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.

r? @estebank (thanks for the minimized test case)
Diffstat (limited to 'src')
-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 8feab373e71..29d2d2ad73d 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -6618,7 +6618,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
+