Skip to content

Commit 7aba683

Browse files
authored
Auto merge of #34239 - jseyfried:fix_macro_use_scope_regression, r=nrc
Revert a change in the scope of macros imported from crates to fix a regression Fixes #34212. The regression was caused by #34032, which changed the scope of macros imported from extern crates to match the scope of macros imported from modules. r? @nrc
2 parents 6edea2c + 236b67a commit 7aba683

File tree

4 files changed

+91
-26
lines changed

4 files changed

+91
-26
lines changed

src/libsyntax/ext/base.rs

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

src/libsyntax/ext/expand.rs

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ trait MacroGenerable: Sized {
4141

4242
// Fold this node or list of nodes using the given folder.
4343
fn fold_with<F: Folder>(self, folder: &mut F) -> Self;
44+
fn visit_with<'v, V: Visitor<'v>>(&'v self, visitor: &mut V);
4445

4546
// Return a placeholder expansion to allow compilation to continue after an erroring expansion.
4647
fn dummy(span: Span) -> Self;
@@ -50,7 +51,9 @@ trait MacroGenerable: Sized {
5051
}
5152

5253
macro_rules! impl_macro_generable {
53-
($($ty:ty: $kind_name:expr, .$make:ident, $(.$fold:ident)* $(lift .$fold_elt:ident)*,
54+
($($ty:ty: $kind_name:expr, .$make:ident,
55+
$(.$fold:ident)* $(lift .$fold_elt:ident)*,
56+
$(.$visit:ident)* $(lift .$visit_elt:ident)*,
5457
|$span:ident| $dummy:expr;)*) => { $(
5558
impl MacroGenerable for $ty {
5659
fn kind_name() -> &'static str { $kind_name }
@@ -59,21 +62,27 @@ macro_rules! impl_macro_generable {
5962
$( folder.$fold(self) )*
6063
$( self.into_iter().flat_map(|item| folder. $fold_elt (item)).collect() )*
6164
}
65+
fn visit_with<'v, V: Visitor<'v>>(&'v self, visitor: &mut V) {
66+
$( visitor.$visit(self) )*
67+
$( for item in self.as_slice() { visitor. $visit_elt (item) } )*
68+
}
6269
fn dummy($span: Span) -> Self { $dummy }
6370
}
6471
)* }
6572
}
6673

6774
impl_macro_generable! {
68-
P<ast::Expr>: "expression", .make_expr, .fold_expr, |span| DummyResult::raw_expr(span);
69-
P<ast::Pat>: "pattern", .make_pat, .fold_pat, |span| P(DummyResult::raw_pat(span));
70-
P<ast::Ty>: "type", .make_ty, .fold_ty, |span| DummyResult::raw_ty(span);
71-
SmallVector<ast::ImplItem>:
72-
"impl item", .make_impl_items, lift .fold_impl_item, |_span| SmallVector::zero();
73-
SmallVector<P<ast::Item>>:
74-
"item", .make_items, lift .fold_item, |_span| SmallVector::zero();
75+
P<ast::Pat>: "pattern", .make_pat, .fold_pat, .visit_pat, |span| P(DummyResult::raw_pat(span));
76+
P<ast::Ty>: "type", .make_ty, .fold_ty, .visit_ty, |span| DummyResult::raw_ty(span);
77+
P<ast::Expr>:
78+
"expression", .make_expr, .fold_expr, .visit_expr, |span| DummyResult::raw_expr(span);
7579
SmallVector<ast::Stmt>:
76-
"statement", .make_stmts, lift .fold_stmt, |_span| SmallVector::zero();
80+
"statement", .make_stmts, lift .fold_stmt, lift .visit_stmt, |_span| SmallVector::zero();
81+
SmallVector<P<ast::Item>>:
82+
"item", .make_items, lift .fold_item, lift .visit_item, |_span| SmallVector::zero();
83+
SmallVector<ast::ImplItem>:
84+
"impl item", .make_impl_items, lift .fold_impl_item, lift .visit_impl_item,
85+
|_span| SmallVector::zero();
7786
}
7887

7988
impl MacroGenerable for Option<P<ast::Expr>> {
@@ -85,6 +94,9 @@ impl MacroGenerable for Option<P<ast::Expr>> {
8594
fn fold_with<F: Folder>(self, folder: &mut F) -> Self {
8695
self.and_then(|expr| folder.fold_opt_expr(expr))
8796
}
97+
fn visit_with<'v, V: Visitor<'v>>(&'v self, visitor: &mut V) {
98+
self.as_ref().map(|expr| visitor.visit_expr(expr));
99+
}
88100
}
89101

90102
pub fn expand_expr(expr: ast::Expr, fld: &mut MacroExpander) -> P<ast::Expr> {
@@ -320,6 +332,7 @@ fn expand_mac_invoc<T>(mac: ast::Mac, ident: Option<Ident>, attrs: Vec<ast::Attr
320332

321333
let marked = expanded.fold_with(&mut Marker { mark: mark, expn_id: Some(fld.cx.backtrace()) });
322334
let configured = marked.fold_with(&mut fld.strip_unconfigured());
335+
fld.load_macros(&configured);
323336
let fully_expanded = configured.fold_with(fld);
324337
fld.cx.bt_pop();
325338
fully_expanded
@@ -742,15 +755,6 @@ fn expand_annotatable(a: Annotatable,
742755
}
743756
result
744757
},
745-
ast::ItemKind::ExternCrate(_) => {
746-
// We need to error on `#[macro_use] extern crate` when it isn't at the
747-
// crate root, because `$crate` won't work properly.
748-
let allows_macros = fld.cx.syntax_env.is_crate_root();
749-
for def in fld.cx.loader.load_crate(&it, allows_macros) {
750-
fld.cx.insert_macro(def);
751-
}
752-
SmallVector::one(it)
753-
},
754758
_ => noop_fold_item(it, fld),
755759
}.into_iter().map(|i| Annotatable::Item(i)).collect(),
756760

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

10041042
impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
@@ -1142,7 +1180,7 @@ impl<'feat> ExpansionConfig<'feat> {
11421180

11431181
pub fn expand_crate(mut cx: ExtCtxt,
11441182
user_exts: Vec<NamedSyntaxExtension>,
1145-
c: Crate) -> (Crate, HashSet<Name>) {
1183+
mut c: Crate) -> (Crate, HashSet<Name>) {
11461184
if std_inject::no_core(&c) {
11471185
cx.crate_root = None;
11481186
} else if std_inject::no_std(&c) {
@@ -1157,6 +1195,10 @@ pub fn expand_crate(mut cx: ExtCtxt,
11571195
expander.cx.syntax_env.insert(name, extension);
11581196
}
11591197

1198+
let items = SmallVector::many(c.module.items);
1199+
expander.load_macros(&items);
1200+
c.module.items = items.into();
1201+
11601202
let err_count = cx.parse_sess.span_diagnostic.err_count();
11611203
let mut ret = expander.fold_crate(c);
11621204
ret.exported_macros = expander.cx.exported_macros.clone();

src/libsyntax/util/small_vector.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ enum SmallVectorRepr<T> {
2929
Many(Vec<T>),
3030
}
3131

32+
impl<T> Into<Vec<T>> for SmallVector<T> {
33+
fn into(self) -> Vec<T> {
34+
match self.repr {
35+
Zero => Vec::new(),
36+
One(t) => vec![t],
37+
Many(vec) => vec,
38+
}
39+
}
40+
}
41+
3242
impl<T> FromIterator<T> for SmallVector<T> {
3343
fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> SmallVector<T> {
3444
let mut v = SmallVector::zero();

src/test/compile-fail-fulldeps/expanded-macro-use.rs renamed to src/test/compile-fail/macro-use-scope.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,25 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
#![feature(rustc_private)]
12-
macro_rules! m {
13-
() => { #[macro_use] extern crate syntax; }
11+
// aux-build:two_macros.rs
12+
13+
#![feature(rustc_attrs)]
14+
#![allow(unused)]
15+
16+
fn f() {
17+
let _ = macro_one!();
1418
}
19+
#[macro_use(macro_one)] // Check that this macro is usable in the above function
20+
extern crate two_macros;
21+
22+
macro_rules! m { () => {
23+
fn g() {
24+
macro_two!();
25+
}
26+
#[macro_use(macro_two)] // Check that this macro is usable in the above function
27+
extern crate two_macros as _two_macros;
28+
} }
1529
m!();
1630

17-
fn main() {
18-
help!(); //~ ERROR unexpected end of macro invocation
19-
}
31+
#[rustc_error]
32+
fn main() {} //~ ERROR compilation successful

0 commit comments

Comments
 (0)