about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorPietro Albini <pietro@pietroalbini.org>2018-10-05 22:33:17 +0200
committerGitHub <noreply@github.com>2018-10-05 22:33:17 +0200
commita95a6e287a9ea2665e6e1a230cf6acaeb1bbe9d1 (patch)
tree6fc17abed4c52dd300c415ea77154bb16d079755 /src/libsyntax/parse
parent08af25fb27a521ee924787c10c96e8d9e2b04db9 (diff)
parent9da428dad8eefa8a821214bc0fe0d4159ba4efed (diff)
downloadrust-a95a6e287a9ea2665e6e1a230cf6acaeb1bbe9d1.tar.gz
rust-a95a6e287a9ea2665e6e1a230cf6acaeb1bbe9d1.zip
Rollup merge of #54833 - abonander:issue-54441, r=petrochenkov
make `Parser::parse_foreign_item()` return a foreign item or error

Fixes `Parser::parse_foreign_item()` to follow the convention of `parse_trait_item()` and `parse_impl_item()` in that it *must* parse an item or return an error, and then the caller is responsible for detecting the closing delimiter.

This prevents it from looping endlessly on an unexpected token in `ext/expand.rs` where it was also leaking memory by continually pushing to `Parser::expected_tokens` via `Parser::check_keyword()`.

closes #54441

r? @petrochenkov
cc @dtolnay
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/parser.rs23
1 files changed, 11 insertions, 12 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 1825ee6eab8..d653ed819fd 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -6737,10 +6737,9 @@ impl<'a> Parser<'a> {
         attrs.extend(self.parse_inner_attributes()?);
 
         let mut foreign_items = vec![];
-        while let Some(item) = self.parse_foreign_item()? {
-            foreign_items.push(item);
+        while !self.eat(&token::CloseDelim(token::Brace)) {
+            foreign_items.push(self.parse_foreign_item()?);
         }
-        self.expect(&token::CloseDelim(token::Brace))?;
 
         let prev_span = self.prev_span;
         let m = ast::ForeignMod {
@@ -7324,8 +7323,8 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse a foreign item.
-    crate fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> {
-        maybe_whole!(self, NtForeignItem, |ni| Some(ni));
+    crate fn parse_foreign_item(&mut self) -> PResult<'a, ForeignItem> {
+        maybe_whole!(self, NtForeignItem, |ni| ni);
 
         let attrs = self.parse_outer_attributes()?;
         let lo = self.span;
@@ -7345,20 +7344,20 @@ impl<'a> Parser<'a> {
                     ).emit();
             }
             self.bump(); // `static` or `const`
-            return Ok(Some(self.parse_item_foreign_static(visibility, lo, attrs)?));
+            return Ok(self.parse_item_foreign_static(visibility, lo, attrs)?);
         }
         // FOREIGN FUNCTION ITEM
         if self.check_keyword(keywords::Fn) {
-            return Ok(Some(self.parse_item_foreign_fn(visibility, lo, attrs)?));
+            return Ok(self.parse_item_foreign_fn(visibility, lo, attrs)?);
         }
         // FOREIGN TYPE ITEM
         if self.check_keyword(keywords::Type) {
-            return Ok(Some(self.parse_item_foreign_type(visibility, lo, attrs)?));
+            return Ok(self.parse_item_foreign_type(visibility, lo, attrs)?);
         }
 
         match self.parse_assoc_macro_invoc("extern", Some(&visibility), &mut false)? {
             Some(mac) => {
-                Ok(Some(
+                Ok(
                     ForeignItem {
                         ident: keywords::Invalid.ident(),
                         span: lo.to(self.prev_span),
@@ -7367,14 +7366,14 @@ impl<'a> Parser<'a> {
                         vis: visibility,
                         node: ForeignItemKind::Macro(mac),
                     }
-                ))
+                )
             }
             None => {
-                if !attrs.is_empty() {
+                if !attrs.is_empty()  {
                     self.expected_item_err(&attrs);
                 }
 
-                Ok(None)
+                self.unexpected()
             }
         }
     }