Skip to content

Commit 2d1f300

Browse files
committed
Load macros from #[macro_use] crates earlier in expansion
1 parent 3b8e1f3 commit 2d1f300

File tree

2 files changed

+41
-11
lines changed

2 files changed

+41
-11
lines changed

src/libsyntax/ext/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,6 @@ impl SyntaxEnv {
944944
pub fn is_crate_root(&mut self) -> bool {
945945
// The first frame is pushed in `SyntaxEnv::new()` and the second frame is
946946
// pushed when folding the crate root pseudo-module (c.f. noop_fold_crate).
947-
self.chain.len() == 2
947+
self.chain.len() <= 2
948948
}
949949
}

src/libsyntax/ext/expand.rs

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ fn expand_mac_invoc<T>(mac: ast::Mac, ident: Option<Ident>, attrs: Vec<ast::Attr
338338

339339
let marked = expanded.fold_with(&mut Marker { mark: mark, expn_id: Some(fld.cx.backtrace()) });
340340
let configured = marked.fold_with(&mut fld.strip_unconfigured());
341+
fld.load_macros(&configured);
341342
let fully_expanded = configured.fold_with(fld);
342343
fld.cx.bt_pop();
343344
fully_expanded
@@ -760,15 +761,6 @@ fn expand_annotatable(a: Annotatable,
760761
}
761762
result
762763
},
763-
ast::ItemKind::ExternCrate(_) => {
764-
// We need to error on `#[macro_use] extern crate` when it isn't at the
765-
// crate root, because `$crate` won't work properly.
766-
let allows_macros = fld.cx.syntax_env.is_crate_root();
767-
for def in fld.cx.loader.load_crate(&it, allows_macros) {
768-
fld.cx.insert_macro(def);
769-
}
770-
SmallVector::one(it)
771-
},
772764
_ => noop_fold_item(it, fld),
773765
}.into_iter().map(|i| Annotatable::Item(i)).collect(),
774766

@@ -1017,6 +1009,40 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
10171009
&self.cx.parse_sess.span_diagnostic,
10181010
self.cx.feature_gated_cfgs)
10191011
}
1012+
1013+
fn load_macros<T: MacroGenerable>(&mut self, node: &T) {
1014+
struct MacroLoadingVisitor<'a, 'b: 'a>{
1015+
cx: &'a mut ExtCtxt<'b>,
1016+
at_crate_root: bool,
1017+
}
1018+
1019+
impl<'a, 'b, 'v> Visitor<'v> for MacroLoadingVisitor<'a, 'b> {
1020+
fn visit_mac(&mut self, _: &'v ast::Mac) {}
1021+
fn visit_item(&mut self, item: &'v ast::Item) {
1022+
if let ast::ItemKind::ExternCrate(..) = item.node {
1023+
// We need to error on `#[macro_use] extern crate` when it isn't at the
1024+
// crate root, because `$crate` won't work properly.
1025+
for def in self.cx.loader.load_crate(item, self.at_crate_root) {
1026+
self.cx.insert_macro(def);
1027+
}
1028+
} else {
1029+
let at_crate_root = ::std::mem::replace(&mut self.at_crate_root, false);
1030+
visit::walk_item(self, item);
1031+
self.at_crate_root = at_crate_root;
1032+
}
1033+
}
1034+
fn visit_block(&mut self, block: &'v ast::Block) {
1035+
let at_crate_root = ::std::mem::replace(&mut self.at_crate_root, false);
1036+
visit::walk_block(self, block);
1037+
self.at_crate_root = at_crate_root;
1038+
}
1039+
}
1040+
1041+
node.visit_with(&mut MacroLoadingVisitor {
1042+
at_crate_root: self.cx.syntax_env.is_crate_root(),
1043+
cx: self.cx,
1044+
});
1045+
}
10201046
}
10211047

10221048
impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
@@ -1160,7 +1186,7 @@ impl<'feat> ExpansionConfig<'feat> {
11601186

11611187
pub fn expand_crate(mut cx: ExtCtxt,
11621188
user_exts: Vec<NamedSyntaxExtension>,
1163-
c: Crate) -> (Crate, HashSet<Name>) {
1189+
mut c: Crate) -> (Crate, HashSet<Name>) {
11641190
if std_inject::no_core(&c) {
11651191
cx.crate_root = None;
11661192
} else if std_inject::no_std(&c) {
@@ -1175,6 +1201,10 @@ pub fn expand_crate(mut cx: ExtCtxt,
11751201
expander.cx.syntax_env.insert(name, extension);
11761202
}
11771203

1204+
let items = SmallVector::many(c.module.items);
1205+
expander.load_macros(&items);
1206+
c.module.items = items.into();
1207+
11781208
let err_count = cx.parse_sess.span_diagnostic.err_count();
11791209
let mut ret = expander.fold_crate(c);
11801210
ret.exported_macros = expander.cx.exported_macros.clone();

0 commit comments

Comments
 (0)