Skip to content

Commit a63f35d

Browse files
committed
parse: use parse_item_common in parse_foreign_item.
1 parent a920a05 commit a63f35d

14 files changed

+392
-70
lines changed

src/librustc_expand/expand.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -879,8 +879,8 @@ pub fn parse_ast_fragment<'a>(
879879
}
880880
AstFragmentKind::ForeignItems => {
881881
let mut items = SmallVec::new();
882-
while this.token != token::Eof {
883-
items.push(this.parse_foreign_item(&mut false)?);
882+
while let Some(item) = this.parse_foreign_item()? {
883+
items.extend(item);
884884
}
885885
AstFragment::ForeignItems(items)
886886
}

src/librustc_parse/parser/item.rs

Lines changed: 53 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,8 @@ impl<'a> Parser<'a> {
457457

458458
generics.where_clause = self.parse_where_clause()?;
459459

460-
let impl_items = self.parse_item_list(attrs, |p, at_end| p.parse_impl_item(at_end))?;
460+
let impl_items =
461+
self.parse_item_list(attrs, |p, at_end| p.parse_impl_item(at_end).map(Some).map(Some))?;
461462

462463
let item_kind = match ty_second {
463464
Some(ty_second) => {
@@ -516,8 +517,9 @@ impl<'a> Parser<'a> {
516517
fn parse_item_list<T>(
517518
&mut self,
518519
attrs: &mut Vec<Attribute>,
519-
mut parse_item: impl FnMut(&mut Parser<'a>, &mut bool) -> PResult<'a, T>,
520+
mut parse_item: impl FnMut(&mut Parser<'a>, &mut bool) -> PResult<'a, Option<Option<T>>>,
520521
) -> PResult<'a, Vec<T>> {
522+
let open_brace_span = self.token.span;
521523
self.expect(&token::OpenDelim(token::Brace))?;
522524
attrs.append(&mut self.parse_inner_attributes()?);
523525

@@ -528,7 +530,18 @@ impl<'a> Parser<'a> {
528530
}
529531
let mut at_end = false;
530532
match parse_item(self, &mut at_end) {
531-
Ok(item) => items.push(item),
533+
Ok(None) => {
534+
// We have to bail or we'll potentially never make progress.
535+
let non_item_span = self.token.span;
536+
self.consume_block(token::Brace, ConsumeClosingDelim::Yes);
537+
self.struct_span_err(non_item_span, "non-item in item list")
538+
.span_label(open_brace_span, "item list starts here")
539+
.span_label(non_item_span, "non-item starts here")
540+
.span_label(self.prev_span, "item list ends here")
541+
.emit();
542+
break;
543+
}
544+
Ok(Some(item)) => items.extend(item),
532545
Err(mut err) => {
533546
err.emit();
534547
if !at_end {
@@ -631,7 +644,9 @@ impl<'a> Parser<'a> {
631644
} else {
632645
// It's a normal trait.
633646
tps.where_clause = self.parse_where_clause()?;
634-
let items = self.parse_item_list(attrs, |p, at_end| p.parse_trait_item(at_end))?;
647+
let items = self.parse_item_list(attrs, |p, at_end| {
648+
p.parse_trait_item(at_end).map(Some).map(Some)
649+
})?;
635650
Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, items)))
636651
}
637652
}
@@ -892,38 +907,48 @@ impl<'a> Parser<'a> {
892907
/// ```
893908
fn parse_item_foreign_mod(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, ItemInfo> {
894909
let abi = self.parse_abi(); // ABI?
895-
let items = self.parse_item_list(attrs, |p, at_end| p.parse_foreign_item(at_end))?;
910+
let items = self.parse_item_list(attrs, |p, _| p.parse_foreign_item())?;
896911
let module = ast::ForeignMod { abi, items };
897912
Ok((Ident::invalid(), ItemKind::ForeignMod(module)))
898913
}
899914

900915
/// Parses a foreign item (one in an `extern { ... }` block).
901-
pub fn parse_foreign_item(&mut self, at_end: &mut bool) -> PResult<'a, P<ForeignItem>> {
902-
maybe_whole!(self, NtForeignItem, |ni| ni);
916+
pub fn parse_foreign_item(&mut self) -> PResult<'a, Option<Option<P<ForeignItem>>>> {
917+
maybe_whole!(self, NtForeignItem, |item| Some(Some(item)));
903918

904-
let mut attrs = self.parse_outer_attributes()?;
905-
let lo = self.token.span;
906-
let vis = self.parse_visibility(FollowedByType::No)?;
907-
let (ident, kind) = self.parse_assoc_item_kind(at_end, &mut attrs, |_| true, &vis)?;
908-
let item = self.mk_item(lo, ident, kind, vis, Defaultness::Final, attrs);
909-
self.error_on_foreign_const(&item);
910-
Ok(P(item))
919+
let attrs = self.parse_outer_attributes()?;
920+
let it = self.parse_item_common(attrs, true, false)?;
921+
Ok(it.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| {
922+
self.error_on_illegal_default(defaultness);
923+
let kind = match kind {
924+
ItemKind::Mac(a) => AssocItemKind::Macro(a),
925+
ItemKind::Fn(a, b, c) => AssocItemKind::Fn(a, b, c),
926+
ItemKind::TyAlias(a, b, c) => AssocItemKind::TyAlias(a, b, c),
927+
ItemKind::Static(a, b, c) => AssocItemKind::Static(a, b, c),
928+
ItemKind::Const(a, b) => {
929+
self.error_on_foreign_const(span, ident);
930+
AssocItemKind::Static(a, Mutability::Not, b)
931+
}
932+
_ => {
933+
let span = self.sess.source_map().def_span(span);
934+
self.struct_span_err(span, "item kind not supported in `extern` block").emit();
935+
return None;
936+
}
937+
};
938+
Some(P(Item { attrs, id, span, vis, ident, defaultness, kind, tokens }))
939+
}))
911940
}
912941

913-
fn error_on_foreign_const(&self, item: &ForeignItem) {
914-
if let AssocItemKind::Const(..) = item.kind {
915-
self.struct_span_err(item.ident.span, "extern items cannot be `const`")
916-
.span_suggestion(
917-
item.span.with_hi(item.ident.span.lo()),
918-
"try using a static value",
919-
"static ".to_string(),
920-
Applicability::MachineApplicable,
921-
)
922-
.note(
923-
"for more information, visit https://doc.rust-lang.org/std/keyword.extern.html",
924-
)
925-
.emit();
926-
}
942+
fn error_on_foreign_const(&self, span: Span, ident: Ident) {
943+
self.struct_span_err(ident.span, "extern items cannot be `const`")
944+
.span_suggestion(
945+
span.with_hi(ident.span.lo()),
946+
"try using a static value",
947+
"static ".to_string(),
948+
Applicability::MachineApplicable,
949+
)
950+
.note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html")
951+
.emit();
927952
}
928953

929954
fn is_static_global(&mut self) -> bool {

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
macro_rules! m {
2-
//~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration
32
() => {
4-
let
3+
let //~ ERROR macro expansion ignores token `let` and any following
54
};
65
}
76

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
error: missing `fn`, `type`, `const`, or `static` for item declaration
2-
--> $DIR/issue-54441.rs:1:1
1+
error: macro expansion ignores token `let` and any following
2+
--> $DIR/issue-54441.rs:3:9
33
|
4-
LL | / macro_rules! m {
5-
LL | |
6-
LL | | () => {
7-
LL | | let
8-
| |________^ missing `fn`, `type`, `const`, or `static`
4+
LL | let
5+
| ^^^
6+
...
7+
LL | m!();
8+
| ----- caused by the macro expansion here
9+
|
10+
= note: the usage of `m!` is likely invalid in foreign item context
911

1012
error: aborting due to previous error
1113

src/test/ui/parser/default-on-wrong-item-kind.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Test parsing for `default` where it doesn't belong.
22
// Specifically, we are interested in kinds of items or items in certain contexts.
3+
// Also test item kinds in `extern` blocks and associated contexts which are not allowed there.
34

45
fn main() {}
56

@@ -24,3 +25,38 @@ mod free_items {
2425
default macro foo {} //~ ERROR item cannot be `default`
2526
default macro_rules! foo {} //~ ERROR item cannot be `default`
2627
}
28+
29+
#[cfg(FALSE)]
30+
extern "C" {
31+
default extern crate foo; //~ ERROR item cannot be `default`
32+
//~^ ERROR item kind not supported in `extern` block
33+
default use foo; //~ ERROR item cannot be `default`
34+
//~^ ERROR item kind not supported in `extern` block
35+
default static foo: u8; //~ ERROR item cannot be `default`
36+
default const foo: u8; //~ ERROR item cannot be `default`
37+
//~^ ERROR extern items cannot be `const`
38+
default fn foo(); //~ ERROR item cannot be `default`
39+
default mod foo {} //~ ERROR item cannot be `default`
40+
//~^ ERROR item kind not supported in `extern` block
41+
default extern "C" {} //~ ERROR item cannot be `default`
42+
//~^ ERROR item kind not supported in `extern` block
43+
default type foo = u8; //~ ERROR item cannot be `default`
44+
default enum foo {} //~ ERROR item cannot be `default`
45+
//~^ ERROR item kind not supported in `extern` block
46+
default struct foo {} //~ ERROR item cannot be `default`
47+
//~^ ERROR item kind not supported in `extern` block
48+
default union foo {} //~ ERROR item cannot be `default`
49+
//~^ ERROR item kind not supported in `extern` block
50+
default trait foo {} //~ ERROR item cannot be `default`
51+
//~^ ERROR item kind not supported in `extern` block
52+
default trait foo = Ord; //~ ERROR item cannot be `default`
53+
//~^ ERROR item kind not supported in `extern` block
54+
default impl foo {}
55+
//~^ ERROR item kind not supported in `extern` block
56+
default!();
57+
default::foo::bar!();
58+
default macro foo {} //~ ERROR item cannot be `default`
59+
//~^ ERROR item kind not supported in `extern` block
60+
default macro_rules! foo {} //~ ERROR item cannot be `default`
61+
//~^ ERROR item kind not supported in `extern` block
62+
}

0 commit comments

Comments
 (0)