Skip to content

Commit

Permalink
Rollup merge of rust-lang#54833 - abonander:issue-54441, r=petrochenkov
Browse files Browse the repository at this point in the history
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 rust-lang#54441

r? @petrochenkov
cc @dtolnay
  • Loading branch information
pietroalbini authored Oct 5, 2018
2 parents 08af25f + 9da428d commit a95a6e2
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 16 deletions.
4 changes: 1 addition & 3 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1001,9 +1001,7 @@ impl<'a> Parser<'a> {
AstFragmentKind::ForeignItems => {
let mut items = SmallVec::new();
while self.token != token::Eof {
if let Some(item) = self.parse_foreign_item()? {
items.push(item);
}
items.push(self.parse_foreign_item()?);
}
AstFragment::ForeignItems(items)
}
Expand Down
23 changes: 11 additions & 12 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand All @@ -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),
Expand All @@ -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()
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/parse-fail/duplicate-visibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

// compile-flags: -Z parse-only

// error-pattern:expected one of `(`, `fn`, `static`, `type`, or `}` here
// error-pattern:expected one of `(`, `fn`, `static`, or `type`
extern {
pub pub fn foo();
}
13 changes: 13 additions & 0 deletions src/test/ui/macros/issue-54441.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#![feature(macros_in_extern)]

macro_rules! m {
() => {
let //~ ERROR expected
};
}

extern "C" {
m!();
}

fn main() {}
14 changes: 14 additions & 0 deletions src/test/ui/macros/issue-54441.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: expected one of `crate`, `fn`, `pub`, `static`, or `type`, found `let`
--> $DIR/issue-54441.rs:5:9
|
LL | #![feature(macros_in_extern)]
| - expected one of `crate`, `fn`, `pub`, `static`, or `type` here
...
LL | let //~ ERROR expected
| ^^^ unexpected token
...
LL | m!();
| ----- in this macro invocation

error: aborting due to previous error

0 comments on commit a95a6e2

Please sign in to comment.