Skip to content

Commit a95a6e2

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#54441 r? @petrochenkov cc @dtolnay
2 parents 08af25f + 9da428d commit a95a6e2

File tree

5 files changed

+40
-16
lines changed

5 files changed

+40
-16
lines changed

src/libsyntax/ext/expand.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,9 +1001,7 @@ impl<'a> Parser<'a> {
10011001
AstFragmentKind::ForeignItems => {
10021002
let mut items = SmallVec::new();
10031003
while self.token != token::Eof {
1004-
if let Some(item) = self.parse_foreign_item()? {
1005-
items.push(item);
1006-
}
1004+
items.push(self.parse_foreign_item()?);
10071005
}
10081006
AstFragment::ForeignItems(items)
10091007
}

src/libsyntax/parse/parser.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6737,10 +6737,9 @@ impl<'a> Parser<'a> {
67376737
attrs.extend(self.parse_inner_attributes()?);
67386738

67396739
let mut foreign_items = vec![];
6740-
while let Some(item) = self.parse_foreign_item()? {
6741-
foreign_items.push(item);
6740+
while !self.eat(&token::CloseDelim(token::Brace)) {
6741+
foreign_items.push(self.parse_foreign_item()?);
67426742
}
6743-
self.expect(&token::CloseDelim(token::Brace))?;
67446743

67456744
let prev_span = self.prev_span;
67466745
let m = ast::ForeignMod {
@@ -7324,8 +7323,8 @@ impl<'a> Parser<'a> {
73247323
}
73257324

73267325
/// Parse a foreign item.
7327-
crate fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> {
7328-
maybe_whole!(self, NtForeignItem, |ni| Some(ni));
7326+
crate fn parse_foreign_item(&mut self) -> PResult<'a, ForeignItem> {
7327+
maybe_whole!(self, NtForeignItem, |ni| ni);
73297328

73307329
let attrs = self.parse_outer_attributes()?;
73317330
let lo = self.span;
@@ -7345,20 +7344,20 @@ impl<'a> Parser<'a> {
73457344
).emit();
73467345
}
73477346
self.bump(); // `static` or `const`
7348-
return Ok(Some(self.parse_item_foreign_static(visibility, lo, attrs)?));
7347+
return Ok(self.parse_item_foreign_static(visibility, lo, attrs)?);
73497348
}
73507349
// FOREIGN FUNCTION ITEM
73517350
if self.check_keyword(keywords::Fn) {
7352-
return Ok(Some(self.parse_item_foreign_fn(visibility, lo, attrs)?));
7351+
return Ok(self.parse_item_foreign_fn(visibility, lo, attrs)?);
73537352
}
73547353
// FOREIGN TYPE ITEM
73557354
if self.check_keyword(keywords::Type) {
7356-
return Ok(Some(self.parse_item_foreign_type(visibility, lo, attrs)?));
7355+
return Ok(self.parse_item_foreign_type(visibility, lo, attrs)?);
73577356
}
73587357

73597358
match self.parse_assoc_macro_invoc("extern", Some(&visibility), &mut false)? {
73607359
Some(mac) => {
7361-
Ok(Some(
7360+
Ok(
73627361
ForeignItem {
73637362
ident: keywords::Invalid.ident(),
73647363
span: lo.to(self.prev_span),
@@ -7367,14 +7366,14 @@ impl<'a> Parser<'a> {
73677366
vis: visibility,
73687367
node: ForeignItemKind::Macro(mac),
73697368
}
7370-
))
7369+
)
73717370
}
73727371
None => {
7373-
if !attrs.is_empty() {
7372+
if !attrs.is_empty() {
73747373
self.expected_item_err(&attrs);
73757374
}
73767375

7377-
Ok(None)
7376+
self.unexpected()
73787377
}
73797378
}
73807379
}

src/test/parse-fail/duplicate-visibility.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
// compile-flags: -Z parse-only
1212

13-
// error-pattern:expected one of `(`, `fn`, `static`, `type`, or `}` here
13+
// error-pattern:expected one of `(`, `fn`, `static`, or `type`
1414
extern {
1515
pub pub fn foo();
1616
}

src/test/ui/macros/issue-54441.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(macros_in_extern)]
2+
3+
macro_rules! m {
4+
() => {
5+
let //~ ERROR expected
6+
};
7+
}
8+
9+
extern "C" {
10+
m!();
11+
}
12+
13+
fn main() {}

src/test/ui/macros/issue-54441.stderr

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: expected one of `crate`, `fn`, `pub`, `static`, or `type`, found `let`
2+
--> $DIR/issue-54441.rs:5:9
3+
|
4+
LL | #![feature(macros_in_extern)]
5+
| - expected one of `crate`, `fn`, `pub`, `static`, or `type` here
6+
...
7+
LL | let //~ ERROR expected
8+
| ^^^ unexpected token
9+
...
10+
LL | m!();
11+
| ----- in this macro invocation
12+
13+
error: aborting due to previous error
14+

0 commit comments

Comments
 (0)