Skip to content

Commit 3e20e2f

Browse files
committed
WIP: expand attribute macros in extern {} blocks
1 parent d0b50ee commit 3e20e2f

File tree

11 files changed

+94
-8
lines changed

11 files changed

+94
-8
lines changed

src/libsyntax/ast.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,6 +2172,8 @@ pub enum ForeignItemKind {
21722172
Static(P<Ty>, bool),
21732173
/// A foreign type
21742174
Ty,
2175+
/// A macro invocation (not really supported)
2176+
Macro(Mac),
21752177
}
21762178

21772179
impl ForeignItemKind {
@@ -2180,6 +2182,7 @@ impl ForeignItemKind {
21802182
ForeignItemKind::Fn(..) => "foreign function",
21812183
ForeignItemKind::Static(..) => "foreign static item",
21822184
ForeignItemKind::Ty => "foreign type",
2185+
ForeignItemKind::Macro(..) => "macro in foreign module",
21832186
}
21842187
}
21852188
}

src/libsyntax/ext/base.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub enum Annotatable {
3838
Item(P<ast::Item>),
3939
TraitItem(P<ast::TraitItem>),
4040
ImplItem(P<ast::ImplItem>),
41+
ForeignItem(P<ast::ForeignItem>),
4142
}
4243

4344
impl HasAttrs for Annotatable {
@@ -46,6 +47,7 @@ impl HasAttrs for Annotatable {
4647
Annotatable::Item(ref item) => &item.attrs,
4748
Annotatable::TraitItem(ref trait_item) => &trait_item.attrs,
4849
Annotatable::ImplItem(ref impl_item) => &impl_item.attrs,
50+
Annotatable::ForeignItem(ref foreign_item) => &foreign_item.attrs,
4951
}
5052
}
5153

@@ -54,6 +56,8 @@ impl HasAttrs for Annotatable {
5456
Annotatable::Item(item) => Annotatable::Item(item.map_attrs(f)),
5557
Annotatable::TraitItem(trait_item) => Annotatable::TraitItem(trait_item.map_attrs(f)),
5658
Annotatable::ImplItem(impl_item) => Annotatable::ImplItem(impl_item.map_attrs(f)),
59+
Annotatable::ForeignItem(ref foreign_item) =>
60+
Annotatable::ForeignItem(foreign_item.map_attrs(f)),
5761
}
5862
}
5963
}
@@ -64,6 +68,7 @@ impl Annotatable {
6468
Annotatable::Item(ref item) => item.span,
6569
Annotatable::TraitItem(ref trait_item) => trait_item.span,
6670
Annotatable::ImplItem(ref impl_item) => impl_item.span,
71+
Annotatable::ForeignItem(ref foreign_item) => foreign_item.span,
6772
}
6873
}
6974

@@ -98,6 +103,13 @@ impl Annotatable {
98103
}
99104
}
100105

106+
pub fn expect_foreign_item(self) -> ast::ForeignItem {
107+
match self {
108+
Annotatable::ForeignItem(i) => i.into_inner(),
109+
_ => panic!("expected foreign item")
110+
}
111+
}
112+
101113
pub fn derive_allowed(&self) -> bool {
102114
match *self {
103115
Annotatable::Item(ref item) => match item.node {
@@ -308,6 +320,9 @@ pub trait MacResult {
308320
None
309321
}
310322

323+
/// Create zero or more items in an `extern {}` block
324+
fn make_foreign_items(self: Box<Self>) -> Option<SmallVector<ast::ForeignItem>> { None }
325+
311326
/// Create a pattern.
312327
fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
313328
None
@@ -356,6 +371,7 @@ make_MacEager! {
356371
items: SmallVector<P<ast::Item>>,
357372
impl_items: SmallVector<ast::ImplItem>,
358373
trait_items: SmallVector<ast::TraitItem>,
374+
foreign_items: SmallVector<ast::ForeignItem>,
359375
stmts: SmallVector<ast::Stmt>,
360376
ty: P<ast::Ty>,
361377
}
@@ -377,6 +393,10 @@ impl MacResult for MacEager {
377393
self.trait_items
378394
}
379395

396+
fn make_foreign_items(self: Box<Self>) -> Option<SmallVector<ast::ForeignItem>> {
397+
self.foreign_items
398+
}
399+
380400
fn make_stmts(self: Box<Self>) -> Option<SmallVector<ast::Stmt>> {
381401
match self.stmts.as_ref().map_or(0, |s| s.len()) {
382402
0 => make_stmts_default!(self),
@@ -493,6 +513,14 @@ impl MacResult for DummyResult {
493513
}
494514
}
495515

516+
fn make_foreign_items(self: Box<Self>) -> Option<SmallVector<ast::ForeignItem>> {
517+
if self.expr_only {
518+
None
519+
} else {
520+
Some(SmallVector::new())
521+
}
522+
}
523+
496524
fn make_stmts(self: Box<DummyResult>) -> Option<SmallVector<ast::Stmt>> {
497525
Some(SmallVector::one(ast::Stmt {
498526
id: ast::DUMMY_NODE_ID,

src/libsyntax/ext/expand.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ expansions! {
133133
"trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item;
134134
ImplItems: SmallVector<ast::ImplItem> [SmallVector, ast::ImplItem],
135135
"impl item", .make_impl_items, lift .fold_impl_item, lift .visit_impl_item;
136+
ForeignItems: SmallVector<ast::ForeignItem> [SmallVector, ast::ForeignItem],
137+
"foreign item", .make_foreign_items, lift .fold_foreign_item, lift .visit_foreign_item;
136138
}
137139

138140
impl ExpansionKind {
@@ -434,6 +436,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
434436
Annotatable::ImplItem(item) => {
435437
Annotatable::ImplItem(item.map(|item| cfg.fold_impl_item(item).pop().unwrap()))
436438
}
439+
Annotatable::ForeignItem(item) => {
440+
Annotatable::ForeignItem(
441+
item.map(|item| cfg.fold_foreign_item(item).pop().unwrap())
442+
)
443+
}
437444
}
438445
}
439446

@@ -500,6 +507,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
500507
Annotatable::Item(item) => token::NtItem(item),
501508
Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
502509
Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()),
510+
Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()),
503511
})).into();
504512
let tok_result = mac.expand(self.cx, attr.span, attr.tokens, item_tok);
505513
self.parse_expansion(tok_result, kind, &attr.path, attr.span)
@@ -758,6 +766,15 @@ impl<'a> Parser<'a> {
758766
}
759767
Expansion::ImplItems(items)
760768
}
769+
ExpansionKind::ForeignItems => {
770+
let mut items = SmallVector::new();
771+
while self.token != token::Eof {
772+
if let Some(item) = self.parse_foreign_item()? {
773+
items.push(item);
774+
}
775+
}
776+
Expansion::ForeignItems(items)
777+
}
761778
ExpansionKind::Stmts => {
762779
let mut stmts = SmallVector::new();
763780
while self.token != token::Eof &&
@@ -1089,6 +1106,18 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
10891106
noop_fold_foreign_mod(self.cfg.configure_foreign_mod(foreign_mod), self)
10901107
}
10911108

1109+
fn fold_foreign_item(&mut self, foreign_item: ast::ForeignItem) -> SmallVector<ast::ForeignItem> {
1110+
let (attr, traits, foreign_item) = self.classify_item(foreign_item);
1111+
1112+
if attr.is_some() || !traits.is_empty() {
1113+
let item = Annotatable::ForeignItem(P(foreign_item));
1114+
return self.collect_attr(attr, traits, item, ExpansionKind::ForeignItems)
1115+
.make_foreign_items();
1116+
}
1117+
1118+
return noop_fold_foreign_item(foreign_item, self);
1119+
}
1120+
10921121
fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
10931122
match item {
10941123
ast::ItemKind::MacroDef(..) => item,

src/libsyntax/ext/placeholders.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
6060
defaultness: ast::Defaultness::Final,
6161
tokens: None,
6262
})),
63+
ExpansionKind::ForeignItems => Expansion::ForeignItems(SmallVector::one(ast::ForeignItem {
64+
id, span, ident, vis, attrs,
65+
node: ast::ForeignItemKind::Macro(mac_placeholder()),
66+
})),
6367
ExpansionKind::Pat => Expansion::Pat(P(ast::Pat {
6468
id, span, node: ast::PatKind::Mac(mac_placeholder()),
6569
})),

src/libsyntax/feature_gate.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,6 +1556,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
15561556
gate_feature_post!(&self, extern_types, i.span,
15571557
"extern types are experimental");
15581558
}
1559+
ast::ForeignItemKind::Macro(..) => {
1560+
// FIXME: do we allow macro invocs in `extern {}`?
1561+
}
15591562
}
15601563

15611564
visit::walk_foreign_item(self, i)

src/libsyntax/fold.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,14 @@ pub trait Folder : Sized {
6060
noop_fold_use_tree(use_tree, self)
6161
}
6262

63-
fn fold_foreign_item(&mut self, ni: ForeignItem) -> ForeignItem {
63+
fn fold_foreign_item(&mut self, ni: ForeignItem) -> SmallVector<ForeignItem> {
6464
noop_fold_foreign_item(ni, self)
6565
}
6666

67+
fn fold_foreign_item_simple(&mut self, ni: ForeignItem) -> ForeignItem {
68+
noop_fold_foreign_item_simple(ni, self)
69+
}
70+
6771
fn fold_item(&mut self, i: P<Item>) -> SmallVector<P<Item>> {
6872
noop_fold_item(i, self)
6973
}
@@ -413,7 +417,7 @@ pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod,
413417
fld: &mut T) -> ForeignMod {
414418
ForeignMod {
415419
abi,
416-
items: items.move_map(|x| fld.fold_foreign_item(x)),
420+
items: items.move_flat_map(|x| fld.fold_foreign_item(x)),
417421
}
418422
}
419423

@@ -1070,7 +1074,12 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span,
10701074
}
10711075
}
10721076

1073-
pub fn noop_fold_foreign_item<T: Folder>(ni: ForeignItem, folder: &mut T) -> ForeignItem {
1077+
pub fn noop_fold_foreign_item<T: Folder>(ni: ForeignItem, folder: &mut T)
1078+
-> SmallVector<ForeignItem> {
1079+
SmallVector::one(folder.fold_foreign_item_simple(ni))
1080+
}
1081+
1082+
pub fn noop_fold_foreign_item_simple<T: Folder>(ni: ForeignItem, folder: &mut T) -> ForeignItem {
10741083
ForeignItem {
10751084
id: folder.new_id(ni.id),
10761085
vis: folder.fold_vis(ni.vis),
@@ -1084,6 +1093,7 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: ForeignItem, folder: &mut T) -> For
10841093
ForeignItemKind::Static(folder.fold_ty(t), m)
10851094
}
10861095
ForeignItemKind::Ty => ForeignItemKind::Ty,
1096+
ForeignItemKind::Macro(mac) => ForeignItemKind::Macro(folder.fold_mac(mac)),
10871097
},
10881098
span: folder.new_span(ni.span)
10891099
}

src/libsyntax/parse/parser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6776,7 +6776,7 @@ impl<'a> Parser<'a> {
67766776
}
67776777

67786778
/// Parse a foreign item.
6779-
fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> {
6779+
pub fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> {
67806780
let attrs = self.parse_outer_attributes()?;
67816781
let lo = self.span;
67826782
let visibility = self.parse_visibility(false)?;

src/libsyntax/parse/token.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,7 @@ pub enum Nonterminal {
539539
NtArm(ast::Arm),
540540
NtImplItem(ast::ImplItem),
541541
NtTraitItem(ast::TraitItem),
542+
NtForeignItem(ast::ForeignItem),
542543
NtGenerics(ast::Generics),
543544
NtWhereClause(ast::WhereClause),
544545
NtArg(ast::Arg),
@@ -561,6 +562,7 @@ impl fmt::Debug for Nonterminal {
561562
NtArm(..) => f.pad("NtArm(..)"),
562563
NtImplItem(..) => f.pad("NtImplItem(..)"),
563564
NtTraitItem(..) => f.pad("NtTraitItem(..)"),
565+
NtForeignItem(..) => f.pad("NtForeignItem(..)"),
564566
NtGenerics(..) => f.pad("NtGenerics(..)"),
565567
NtWhereClause(..) => f.pad("NtWhereClause(..)"),
566568
NtArg(..) => f.pad("NtArg(..)"),

src/libsyntax/print/pprust.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,6 +1126,9 @@ impl<'a> State<'a> {
11261126
self.end()?; // end the head-ibox
11271127
self.end() // end the outer cbox
11281128
}
1129+
ast::ForeignItemKind::Macro(..) => {
1130+
// FIXME: stub for now
1131+
}
11291132
}
11301133
}
11311134

src/libsyntax/visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, foreign_item: &'a
459459
}
460460
ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ),
461461
ForeignItemKind::Ty => (),
462+
ForeignItemKind::Macro(ref mac) => visitor.visit_mac(mac),
462463
}
463464

464465
walk_list!(visitor, visit_attribute, &foreign_item.attrs);

src/test/run-pass-fulldeps/proc-macro/attr-more-places.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,25 @@
1010

1111
// aux-build:nop-attr.rs
1212
// ignore-stage1
13+
#![feature(proc_macro)]
1314

1415
extern crate nop_attr;
1516

1617
use nop_attr::{nop_attr, no_output};
1718

1819
fn main() {
1920
#[nop_attr]
20-
println!("Hello, world!");
21+
let string = "Hello, world!";
2122

22-
#[nop_attr]
23+
println!("{}", string);
24+
25+
#[no_output]
2326
{
24-
println!("Hello, world!");
27+
unsafe { some_definitely_unknown_symbol_which_should_be_removed() };
2528
}
2629
}
2730

2831
extern {
2932
#[no_output]
30-
fn read();
33+
fn some_definitely_unknown_symbol_which_should_be_removed();
3134
}

0 commit comments

Comments
 (0)