Skip to content

Commit 5d74990

Browse files
committed
expand macro invocations in extern {} blocks
1 parent 5ee891c commit 5d74990

31 files changed

+544
-65
lines changed

src/librustc/hir/lowering.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2724,6 +2724,7 @@ impl<'a> LoweringContext<'a> {
27242724
hir::ForeignItemStatic(this.lower_ty(t, ImplTraitContext::Disallowed), m)
27252725
}
27262726
ForeignItemKind::Ty => hir::ForeignItemType,
2727+
ForeignItemKind::Macro(_) => panic!("shouldn't exist here"),
27272728
},
27282729
vis: this.lower_visibility(&i.vis, None),
27292730
span: i.span,

src/librustc/hir/map/def_collector.rs

+4
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
181181
}
182182

183183
fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
184+
if let ForeignItemKind::Macro(_) = foreign_item.node {
185+
return self.visit_macro_invoc(foreign_item.id, false);
186+
}
187+
184188
let def = self.create_def(foreign_item.id,
185189
DefPathData::ValueNs(foreign_item.ident.name.as_str()),
186190
REGULAR_SPACE,

src/librustc_passes/ast_validation.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
381381
.span_label(span, "pattern not allowed in foreign function").emit();
382382
});
383383
}
384-
ForeignItemKind::Static(..) | ForeignItemKind::Ty => {}
384+
ForeignItemKind::Static(..) | ForeignItemKind::Ty | ForeignItemKind::Macro(..) => {}
385385
}
386386

387387
visit::walk_foreign_item(self, fi)
@@ -460,6 +460,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
460460
self.check_late_bound_lifetime_defs(&t.bound_generic_params);
461461
visit::walk_poly_trait_ref(self, t, m);
462462
}
463+
464+
fn visit_mac(&mut self, mac: &Spanned<Mac_>) {
465+
// when a new macro kind is added but the author forgets to set it up for expansion
466+
// because that's the only part that won't cause a compiler error
467+
self.session.diagnostic()
468+
.span_bug(mac.span, "macro invocation missed in expansion; did you forget to override \
469+
the relevant `fold_*()` method in `PlaceholderExpander`?");
470+
}
463471
}
464472

465473
// Bans nested `impl Trait`, e.g. `impl Into<impl Debug>`.
@@ -522,6 +530,10 @@ impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> {
522530
}
523531
}
524532
}
533+
534+
fn visit_mac(&mut self, _mac: &Spanned<Mac_>) {
535+
// covered in AstValidator
536+
}
525537
}
526538

527539
// Bans `impl Trait` in path projections like `<impl Iterator>::Item` or `Foo::Bar<impl Trait>`.
@@ -583,6 +595,10 @@ impl<'a> Visitor<'a> for ImplTraitProjectionVisitor<'a> {
583595
_ => visit::walk_ty(self, t),
584596
}
585597
}
598+
599+
fn visit_mac(&mut self, _mac: &Spanned<Mac_>) {
600+
// covered in AstValidator
601+
}
586602
}
587603

588604
pub fn check_crate(session: &Session, krate: &Crate) {

src/librustc_resolve/build_reduced_graph.rs

+6
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@ impl<'a> Resolver<'a> {
456456
ForeignItemKind::Ty => {
457457
(Def::TyForeign(self.definitions.local_def_id(item.id)), TypeNS)
458458
}
459+
ForeignItemKind::Macro(_) => unreachable!(),
459460
};
460461
let parent = self.current_module;
461462
let vis = self.resolve_visibility(&item.vis);
@@ -816,6 +817,11 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
816817
}
817818

818819
fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
820+
if let ForeignItemKind::Macro(_) = foreign_item.node {
821+
self.visit_invoc(foreign_item.id);
822+
return;
823+
}
824+
819825
self.resolver.build_reduced_graph_for_foreign_item(foreign_item, self.expansion);
820826
visit::walk_foreign_item(self, foreign_item);
821827
}

src/librustc_resolve/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
863863
}
864864
ForeignItemKind::Static(..) => NoTypeParameters,
865865
ForeignItemKind::Ty => NoTypeParameters,
866+
ForeignItemKind::Macro(..) => NoTypeParameters,
866867
};
867868
self.with_type_parameter_rib(type_parameters, |this| {
868869
visit::walk_foreign_item(this, foreign_item);

src/librustc_save_analysis/dump_visitor.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1812,6 +1812,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
18121812
self.dumper.dump_def(&access, var_data);
18131813
}
18141814
}
1815+
ast::ForeignItemKind::Macro(..) => {}
18151816
}
18161817
}
18171818
}

src/librustc_save_analysis/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
182182
}
183183
// FIXME(plietar): needs a new DefKind in rls-data
184184
ast::ForeignItemKind::Ty => None,
185+
ast::ForeignItemKind::Macro(..) => None,
185186
}
186187
}
187188

src/librustc_save_analysis/sig.rs

+1
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,7 @@ impl Sig for ast::ForeignItem {
822822
refs: vec![],
823823
})
824824
}
825+
ast::ForeignItemKind::Macro(..) => Err("macro"),
825826
}
826827
}
827828
}

src/libsyntax/ast.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2195,6 +2195,8 @@ pub enum ForeignItemKind {
21952195
Static(P<Ty>, bool),
21962196
/// A foreign type
21972197
Ty,
2198+
/// A macro invocation
2199+
Macro(Mac),
21982200
}
21992201

22002202
impl ForeignItemKind {
@@ -2203,6 +2205,7 @@ impl ForeignItemKind {
22032205
ForeignItemKind::Fn(..) => "foreign function",
22042206
ForeignItemKind::Static(..) => "foreign static item",
22052207
ForeignItemKind::Ty => "foreign type",
2208+
ForeignItemKind::Macro(..) => "macro in foreign module",
22062209
}
22072210
}
22082211
}

src/libsyntax/ext/base.rs

+28
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
Stmt(P<ast::Stmt>),
4243
Expr(P<ast::Expr>),
4344
}
@@ -48,6 +49,7 @@ impl HasAttrs for Annotatable {
4849
Annotatable::Item(ref item) => &item.attrs,
4950
Annotatable::TraitItem(ref trait_item) => &trait_item.attrs,
5051
Annotatable::ImplItem(ref impl_item) => &impl_item.attrs,
52+
Annotatable::ForeignItem(ref foreign_item) => &foreign_item.attrs,
5153
Annotatable::Stmt(ref stmt) => stmt.attrs(),
5254
Annotatable::Expr(ref expr) => &expr.attrs,
5355
}
@@ -58,6 +60,8 @@ impl HasAttrs for Annotatable {
5860
Annotatable::Item(item) => Annotatable::Item(item.map_attrs(f)),
5961
Annotatable::TraitItem(trait_item) => Annotatable::TraitItem(trait_item.map_attrs(f)),
6062
Annotatable::ImplItem(impl_item) => Annotatable::ImplItem(impl_item.map_attrs(f)),
63+
Annotatable::ForeignItem(foreign_item) =>
64+
Annotatable::ForeignItem(foreign_item.map_attrs(f)),
6165
Annotatable::Stmt(stmt) => Annotatable::Stmt(stmt.map_attrs(f)),
6266
Annotatable::Expr(expr) => Annotatable::Expr(expr.map_attrs(f)),
6367
}
@@ -70,6 +74,7 @@ impl Annotatable {
7074
Annotatable::Item(ref item) => item.span,
7175
Annotatable::TraitItem(ref trait_item) => trait_item.span,
7276
Annotatable::ImplItem(ref impl_item) => impl_item.span,
77+
Annotatable::ForeignItem(ref foreign_item) => foreign_item.span,
7378
Annotatable::Stmt(ref stmt) => stmt.span,
7479
Annotatable::Expr(ref expr) => expr.span,
7580
}
@@ -106,6 +111,13 @@ impl Annotatable {
106111
}
107112
}
108113

114+
pub fn expect_foreign_item(self) -> ast::ForeignItem {
115+
match self {
116+
Annotatable::ForeignItem(i) => i.into_inner(),
117+
_ => panic!("expected foreign item")
118+
}
119+
}
120+
109121
pub fn derive_allowed(&self) -> bool {
110122
match *self {
111123
Annotatable::Item(ref item) => match item.node {
@@ -317,6 +329,9 @@ pub trait MacResult {
317329
None
318330
}
319331

332+
/// Create zero or more items in an `extern {}` block
333+
fn make_foreign_items(self: Box<Self>) -> Option<SmallVector<ast::ForeignItem>> { None }
334+
320335
/// Create a pattern.
321336
fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
322337
None
@@ -365,6 +380,7 @@ make_MacEager! {
365380
items: SmallVector<P<ast::Item>>,
366381
impl_items: SmallVector<ast::ImplItem>,
367382
trait_items: SmallVector<ast::TraitItem>,
383+
foreign_items: SmallVector<ast::ForeignItem>,
368384
stmts: SmallVector<ast::Stmt>,
369385
ty: P<ast::Ty>,
370386
}
@@ -386,6 +402,10 @@ impl MacResult for MacEager {
386402
self.trait_items
387403
}
388404

405+
fn make_foreign_items(self: Box<Self>) -> Option<SmallVector<ast::ForeignItem>> {
406+
self.foreign_items
407+
}
408+
389409
fn make_stmts(self: Box<Self>) -> Option<SmallVector<ast::Stmt>> {
390410
match self.stmts.as_ref().map_or(0, |s| s.len()) {
391411
0 => make_stmts_default!(self),
@@ -502,6 +522,14 @@ impl MacResult for DummyResult {
502522
}
503523
}
504524

525+
fn make_foreign_items(self: Box<Self>) -> Option<SmallVector<ast::ForeignItem>> {
526+
if self.expr_only {
527+
None
528+
} else {
529+
Some(SmallVector::new())
530+
}
531+
}
532+
505533
fn make_stmts(self: Box<DummyResult>) -> Option<SmallVector<ast::Stmt>> {
506534
Some(SmallVector::one(ast::Stmt {
507535
id: ast::DUMMY_NODE_ID,

src/libsyntax/ext/expand.rs

+58
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 {
@@ -149,6 +151,8 @@ impl ExpansionKind {
149151
Expansion::ImplItems(items.map(Annotatable::expect_impl_item).collect()),
150152
ExpansionKind::TraitItems =>
151153
Expansion::TraitItems(items.map(Annotatable::expect_trait_item).collect()),
154+
ExpansionKind::ForeignItems =>
155+
Expansion::ForeignItems(items.map(Annotatable::expect_foreign_item).collect()),
152156
_ => unreachable!(),
153157
}
154158
}
@@ -435,6 +439,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
435439
Annotatable::ImplItem(item) => {
436440
Annotatable::ImplItem(item.map(|item| cfg.fold_impl_item(item).pop().unwrap()))
437441
}
442+
Annotatable::ForeignItem(item) => {
443+
Annotatable::ForeignItem(
444+
item.map(|item| cfg.fold_foreign_item(item).pop().unwrap())
445+
)
446+
}
438447
Annotatable::Stmt(stmt) => {
439448
Annotatable::Stmt(stmt.map(|stmt| cfg.fold_stmt(stmt).pop().unwrap()))
440449
}
@@ -509,6 +518,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
509518
Annotatable::Item(item) => token::NtItem(item),
510519
Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
511520
Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()),
521+
Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()),
512522
Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
513523
Annotatable::Expr(expr) => token::NtExpr(expr),
514524
})).into();
@@ -793,6 +803,15 @@ impl<'a> Parser<'a> {
793803
}
794804
Expansion::ImplItems(items)
795805
}
806+
ExpansionKind::ForeignItems => {
807+
let mut items = SmallVector::new();
808+
while self.token != token::Eof {
809+
if let Some(item) = self.parse_foreign_item()? {
810+
items.push(item);
811+
}
812+
}
813+
Expansion::ForeignItems(items)
814+
}
796815
ExpansionKind::Stmts => {
797816
let mut stmts = SmallVector::new();
798817
while self.token != token::Eof &&
@@ -1166,6 +1185,44 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
11661185
noop_fold_foreign_mod(self.cfg.configure_foreign_mod(foreign_mod), self)
11671186
}
11681187

1188+
fn fold_foreign_item(&mut self,
1189+
foreign_item: ast::ForeignItem) -> SmallVector<ast::ForeignItem> {
1190+
let (attr, traits, foreign_item) = self.classify_item(foreign_item);
1191+
1192+
let explain = if self.cx.ecfg.proc_macro_enabled() {
1193+
feature_gate::EXPLAIN_PROC_MACROS_IN_EXTERN
1194+
} else {
1195+
feature_gate::EXPLAIN_MACROS_IN_EXTERN
1196+
};
1197+
1198+
if attr.is_some() || !traits.is_empty() {
1199+
if !self.cx.ecfg.macros_in_extern_enabled() {
1200+
if let Some(ref attr) = attr {
1201+
emit_feature_err(&self.cx.parse_sess, "macros_in_extern", attr.span,
1202+
GateIssue::Language, explain);
1203+
}
1204+
}
1205+
1206+
let item = Annotatable::ForeignItem(P(foreign_item));
1207+
return self.collect_attr(attr, traits, item, ExpansionKind::ForeignItems)
1208+
.make_foreign_items();
1209+
}
1210+
1211+
if let ast::ForeignItemKind::Macro(mac) = foreign_item.node {
1212+
self.check_attributes(&foreign_item.attrs);
1213+
1214+
if !self.cx.ecfg.macros_in_extern_enabled() {
1215+
emit_feature_err(&self.cx.parse_sess, "macros_in_extern", foreign_item.span,
1216+
GateIssue::Language, explain);
1217+
}
1218+
1219+
return self.collect_bang(mac, foreign_item.span, ExpansionKind::ForeignItems)
1220+
.make_foreign_items();
1221+
}
1222+
1223+
noop_fold_foreign_item(foreign_item, self)
1224+
}
1225+
11691226
fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
11701227
match item {
11711228
ast::ItemKind::MacroDef(..) => item,
@@ -1311,6 +1368,7 @@ impl<'feat> ExpansionConfig<'feat> {
13111368
fn enable_allow_internal_unstable = allow_internal_unstable,
13121369
fn enable_custom_derive = custom_derive,
13131370
fn proc_macro_enabled = proc_macro,
1371+
fn macros_in_extern_enabled = macros_in_extern,
13141372
}
13151373
}
13161374

src/libsyntax/ext/placeholders.rs

+11
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
})),
@@ -132,6 +136,13 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
132136
}
133137
}
134138

139+
fn fold_foreign_item(&mut self, item: ast::ForeignItem) -> SmallVector<ast::ForeignItem> {
140+
match item.node {
141+
ast::ForeignItemKind::Macro(_) => self.remove(item.id).make_foreign_items(),
142+
_ => noop_fold_foreign_item(item, self),
143+
}
144+
}
145+
135146
fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
136147
match expr.node {
137148
ast::ExprKind::Mac(_) => self.remove(expr.id).make_expr(),

src/libsyntax/feature_gate.rs

+11
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,9 @@ declare_features! (
447447

448448
// Allows keywords to be escaped for use as identifiers
449449
(active, raw_identifiers, "1.26.0", Some(48589), None),
450+
451+
// Allows macro invocations in `extern {}` blocks
452+
(active, macros_in_extern, "1.27.0", Some(49476), None),
450453
);
451454

452455
declare_features! (
@@ -1296,6 +1299,13 @@ pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
12961299
pub const EXPLAIN_MACRO_AT_MOST_ONCE_REP: &'static str =
12971300
"Using the `?` macro Kleene operator for \"at most one\" repetition is unstable";
12981301

1302+
pub const EXPLAIN_MACROS_IN_EXTERN: &'static str =
1303+
"Macro invocations in `extern {}` blocks are experimental.";
1304+
1305+
// mention proc-macros when enabled
1306+
pub const EXPLAIN_PROC_MACROS_IN_EXTERN: &'static str =
1307+
"Macro and proc-macro invocations in `extern {}` blocks are experimental.";
1308+
12991309
struct PostExpansionVisitor<'a> {
13001310
context: &'a Context<'a>,
13011311
}
@@ -1600,6 +1610,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
16001610
gate_feature_post!(&self, extern_types, i.span,
16011611
"extern types are experimental");
16021612
}
1613+
ast::ForeignItemKind::Macro(..) => {}
16031614
}
16041615

16051616
visit::walk_foreign_item(self, i)

0 commit comments

Comments
 (0)