Skip to content

Commit 2099182

Browse files
committed
Rollup merge of #37084 - jseyfried:cleanup_expanded_macro_use_scopes, r=nrc
macros: clean up scopes of expanded `#[macro_use]` imports This PR changes the scope of macro-expanded `#[macro_use]` imports to match that of unexpanded `#[macro_use]` imports. For example, this would be allowed: ```rust example!(); macro_rules! m { () => { #[macro_use(example)] extern crate example_crate; } } m!(); ``` This PR also enforces the full shadowing restrictions from RFC 1560 on `#[macro_use]` imports (currently, we only enforce the weakened restrictions from #36767). This is a [breaking-change], but I believe it is highly unlikely to cause breakage in practice. r? @nrc
2 parents 2d71be5 + 829bd8c commit 2099182

File tree

14 files changed

+316
-227
lines changed

14 files changed

+316
-227
lines changed

src/librustc/hir/lowering.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,7 @@ pub fn lower_crate(sess: &Session,
9494
let _ignore = sess.dep_graph.in_ignore();
9595

9696
LoweringContext {
97-
crate_root: if std_inject::no_core(krate) {
98-
None
99-
} else if std_inject::no_std(krate) {
100-
Some("core")
101-
} else {
102-
Some("std")
103-
},
97+
crate_root: std_inject::injected_crate_name(krate),
10498
sess: sess,
10599
parent_def: None,
106100
resolver: resolver,

src/librustc_driver/driver.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
649649
let resolver_arenas = Resolver::arenas();
650650
let mut resolver =
651651
Resolver::new(sess, &krate, make_glob_map, &mut crate_loader, &resolver_arenas);
652-
syntax_ext::register_builtins(&mut resolver, sess.features.borrow().quote);
652+
syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features.borrow().quote);
653653

654654
krate = time(time_passes, "expansion", || {
655655
// Windows dlls do not have rpaths, so they don't know how to find their
@@ -686,11 +686,17 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
686686
..syntax::ext::expand::ExpansionConfig::default(crate_name.to_string())
687687
};
688688
let mut ecx = ExtCtxt::new(&sess.parse_sess, krate.config.clone(), cfg, &mut resolver);
689-
let ret = syntax::ext::expand::expand_crate(&mut ecx, syntax_exts, krate);
689+
let err_count = ecx.parse_sess.span_diagnostic.err_count();
690+
691+
let krate = ecx.monotonic_expander().expand_crate(krate);
692+
693+
if ecx.parse_sess.span_diagnostic.err_count() - ecx.resolve_err_count > err_count {
694+
ecx.parse_sess.span_diagnostic.abort_if_errors();
695+
}
690696
if cfg!(windows) {
691697
env::set_var("PATH", &old_path);
692698
}
693-
ret
699+
krate
694700
});
695701

696702
krate.exported_macros = mem::replace(&mut resolver.exported_macros, Vec::new());

src/librustc_resolve/build_reduced_graph.rs

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
//! Here we build the "reduced graph": the graph of the module tree without
1414
//! any imports resolved.
1515
16-
use macros;
16+
use macros::{InvocationData, LegacyScope};
1717
use resolve_imports::ImportDirectiveSubclass::{self, GlobImport};
1818
use {Module, ModuleS, ModuleKind};
1919
use Namespace::{self, TypeNS, ValueNS};
@@ -200,16 +200,16 @@ impl<'b> Resolver<'b> {
200200
LoadedMacroKind::Def(mut def) => {
201201
let name = def.ident.name;
202202
if def.use_locally {
203-
let ext = macro_rules::compile(&self.session.parse_sess, &def);
204-
let shadowing =
205-
self.resolve_macro_name(Mark::root(), name, false).is_some();
206-
self.expansion_data[&Mark::root()].module.macros.borrow_mut()
207-
.insert(name, macros::NameBinding {
208-
ext: Rc::new(ext),
209-
expansion: expansion,
210-
shadowing: shadowing,
211-
span: loaded_macro.import_site,
212-
});
203+
let ext =
204+
Rc::new(macro_rules::compile(&self.session.parse_sess, &def));
205+
if self.builtin_macros.insert(name, ext).is_some() &&
206+
expansion != Mark::root() {
207+
let msg = format!("`{}` is already in scope", name);
208+
self.session.struct_span_err(loaded_macro.import_site, &msg)
209+
.note("macro-expanded `#[macro_use]`s may not shadow \
210+
existing macros (see RFC 1560)")
211+
.emit();
212+
}
213213
self.macro_names.insert(name);
214214
}
215215
if def.export {
@@ -250,7 +250,6 @@ impl<'b> Resolver<'b> {
250250
attr::contains_name(&item.attrs, "no_implicit_prelude")
251251
},
252252
normal_ancestor_id: Some(item.id),
253-
macros_escape: self.contains_macro_use(&item.attrs),
254253
..ModuleS::new(Some(parent), ModuleKind::Def(def, name))
255254
});
256255
self.define(parent, name, TypeNS, (module, sp, vis));
@@ -520,45 +519,62 @@ impl<'b> Resolver<'b> {
520519

521520
pub struct BuildReducedGraphVisitor<'a, 'b: 'a> {
522521
pub resolver: &'a mut Resolver<'b>,
522+
pub legacy_scope: LegacyScope<'b>,
523523
pub expansion: Mark,
524524
}
525525

526526
impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
527-
fn visit_invoc(&mut self, id: ast::NodeId) {
528-
self.resolver.expansion_data.get_mut(&Mark::from_placeholder_id(id)).unwrap().module =
529-
self.resolver.current_module;
527+
fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> {
528+
let invocation = self.resolver.invocations[&Mark::from_placeholder_id(id)];
529+
invocation.module.set(self.resolver.current_module);
530+
invocation.legacy_scope.set(self.legacy_scope);
531+
invocation
530532
}
531533
}
532534

533535
macro_rules! method {
534536
($visit:ident: $ty:ty, $invoc:path, $walk:ident) => {
535537
fn $visit(&mut self, node: &$ty) {
536-
match node.node {
537-
$invoc(..) => self.visit_invoc(node.id),
538-
_ => visit::$walk(self, node),
538+
if let $invoc(..) = node.node {
539+
self.visit_invoc(node.id);
540+
} else {
541+
visit::$walk(self, node);
539542
}
540543
}
541544
}
542545
}
543546

544547
impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> {
545548
method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item);
546-
method!(visit_stmt: ast::Stmt, ast::StmtKind::Mac, walk_stmt);
547549
method!(visit_expr: ast::Expr, ast::ExprKind::Mac, walk_expr);
548550
method!(visit_pat: ast::Pat, ast::PatKind::Mac, walk_pat);
549551
method!(visit_ty: ast::Ty, ast::TyKind::Mac, walk_ty);
550552

551553
fn visit_item(&mut self, item: &Item) {
552-
match item.node {
554+
let macro_use = match item.node {
553555
ItemKind::Mac(..) if item.id == ast::DUMMY_NODE_ID => return, // Scope placeholder
554-
ItemKind::Mac(..) => return self.visit_invoc(item.id),
555-
_ => {}
556-
}
556+
ItemKind::Mac(..) => {
557+
return self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id));
558+
}
559+
ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs),
560+
_ => false,
561+
};
557562

558-
let parent = self.resolver.current_module;
563+
let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope);
559564
self.resolver.build_reduced_graph_for_item(item, self.expansion);
560565
visit::walk_item(self, item);
561566
self.resolver.current_module = parent;
567+
if !macro_use {
568+
self.legacy_scope = legacy_scope;
569+
}
570+
}
571+
572+
fn visit_stmt(&mut self, stmt: &ast::Stmt) {
573+
if let ast::StmtKind::Mac(..) = stmt.node {
574+
self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(stmt.id));
575+
} else {
576+
visit::walk_stmt(self, stmt);
577+
}
562578
}
563579

564580
fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
@@ -567,18 +583,20 @@ impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> {
567583
}
568584

569585
fn visit_block(&mut self, block: &Block) {
570-
let parent = self.resolver.current_module;
586+
let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope);
571587
self.resolver.build_reduced_graph_for_block(block);
572588
visit::walk_block(self, block);
573589
self.resolver.current_module = parent;
590+
self.legacy_scope = legacy_scope;
574591
}
575592

576593
fn visit_trait_item(&mut self, item: &TraitItem) {
577594
let parent = self.resolver.current_module;
578595
let def_id = parent.def_id().unwrap();
579596

580597
if let TraitItemKind::Macro(_) = item.node {
581-
return self.visit_invoc(item.id);
598+
self.visit_invoc(item.id);
599+
return
582600
}
583601

584602
// Add the item to the trait info.

src/librustc_resolve/lib.rs

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ use syntax::ext::base::MultiItemModifier;
5757
use syntax::ext::hygiene::Mark;
5858
use syntax::ast::{self, FloatTy};
5959
use syntax::ast::{CRATE_NODE_ID, Name, NodeId, IntTy, UintTy};
60+
use syntax::ext::base::SyntaxExtension;
6061
use syntax::parse::token::{self, keywords};
6162
use syntax::util::lev_distance::find_best_match_for_name;
6263

@@ -77,6 +78,7 @@ use std::mem::replace;
7778
use std::rc::Rc;
7879

7980
use resolve_imports::{ImportDirective, NameResolution};
81+
use macros::{InvocationData, LegacyBinding, LegacyScope};
8082

8183
// NB: This module needs to be declared first so diagnostics are
8284
// registered before they are used.
@@ -791,9 +793,6 @@ pub struct ModuleS<'a> {
791793
// access the children must be preceded with a
792794
// `populate_module_if_necessary` call.
793795
populated: Cell<bool>,
794-
795-
macros: RefCell<FnvHashMap<Name, macros::NameBinding>>,
796-
macros_escape: bool,
797796
}
798797

799798
pub type Module<'a> = &'a ModuleS<'a>;
@@ -811,8 +810,6 @@ impl<'a> ModuleS<'a> {
811810
globs: RefCell::new((Vec::new())),
812811
traits: RefCell::new(None),
813812
populated: Cell::new(true),
814-
macros: RefCell::new(FnvHashMap()),
815-
macros_escape: false,
816813
}
817814
}
818815

@@ -1076,7 +1073,7 @@ pub struct Resolver<'a> {
10761073

10771074
privacy_errors: Vec<PrivacyError<'a>>,
10781075
ambiguity_errors: Vec<AmbiguityError<'a>>,
1079-
macro_shadowing_errors: FnvHashSet<Span>,
1076+
disallowed_shadowing: Vec<(Name, Span, LegacyScope<'a>)>,
10801077

10811078
arenas: &'a ResolverArenas<'a>,
10821079
dummy_binding: &'a NameBinding<'a>,
@@ -1086,9 +1083,10 @@ pub struct Resolver<'a> {
10861083
pub derive_modes: FnvHashMap<Name, Rc<MultiItemModifier>>,
10871084
crate_loader: &'a mut CrateLoader,
10881085
macro_names: FnvHashSet<Name>,
1086+
builtin_macros: FnvHashMap<Name, Rc<SyntaxExtension>>,
10891087

10901088
// Maps the `Mark` of an expansion to its containing module or block.
1091-
expansion_data: FnvHashMap<Mark, macros::ExpansionData<'a>>,
1089+
invocations: FnvHashMap<Mark, &'a InvocationData<'a>>,
10921090
}
10931091

10941092
pub struct ResolverArenas<'a> {
@@ -1097,6 +1095,8 @@ pub struct ResolverArenas<'a> {
10971095
name_bindings: arena::TypedArena<NameBinding<'a>>,
10981096
import_directives: arena::TypedArena<ImportDirective<'a>>,
10991097
name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>,
1098+
invocation_data: arena::TypedArena<InvocationData<'a>>,
1099+
legacy_bindings: arena::TypedArena<LegacyBinding<'a>>,
11001100
}
11011101

11021102
impl<'a> ResolverArenas<'a> {
@@ -1120,6 +1120,13 @@ impl<'a> ResolverArenas<'a> {
11201120
fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
11211121
self.name_resolutions.alloc(Default::default())
11221122
}
1123+
fn alloc_invocation_data(&'a self, expansion_data: InvocationData<'a>)
1124+
-> &'a InvocationData<'a> {
1125+
self.invocation_data.alloc(expansion_data)
1126+
}
1127+
fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBinding<'a> {
1128+
self.legacy_bindings.alloc(binding)
1129+
}
11231130
}
11241131

11251132
impl<'a> ty::NodeIdTree for Resolver<'a> {
@@ -1205,8 +1212,9 @@ impl<'a> Resolver<'a> {
12051212
let mut definitions = Definitions::new();
12061213
DefCollector::new(&mut definitions).collect_root();
12071214

1208-
let mut expansion_data = FnvHashMap();
1209-
expansion_data.insert(Mark::root(), macros::ExpansionData::root(graph_root));
1215+
let mut invocations = FnvHashMap();
1216+
invocations.insert(Mark::root(),
1217+
arenas.alloc_invocation_data(InvocationData::root(graph_root)));
12101218

12111219
Resolver {
12121220
session: session,
@@ -1252,7 +1260,7 @@ impl<'a> Resolver<'a> {
12521260

12531261
privacy_errors: Vec::new(),
12541262
ambiguity_errors: Vec::new(),
1255-
macro_shadowing_errors: FnvHashSet(),
1263+
disallowed_shadowing: Vec::new(),
12561264

12571265
arenas: arenas,
12581266
dummy_binding: arenas.alloc_name_binding(NameBinding {
@@ -1266,7 +1274,8 @@ impl<'a> Resolver<'a> {
12661274
derive_modes: FnvHashMap(),
12671275
crate_loader: crate_loader,
12681276
macro_names: FnvHashSet(),
1269-
expansion_data: expansion_data,
1277+
builtin_macros: FnvHashMap(),
1278+
invocations: invocations,
12701279
}
12711280
}
12721281

@@ -1277,6 +1286,8 @@ impl<'a> Resolver<'a> {
12771286
name_bindings: arena::TypedArena::new(),
12781287
import_directives: arena::TypedArena::new(),
12791288
name_resolutions: arena::TypedArena::new(),
1289+
invocation_data: arena::TypedArena::new(),
1290+
legacy_bindings: arena::TypedArena::new(),
12801291
}
12811292
}
12821293

@@ -3338,7 +3349,8 @@ impl<'a> Resolver<'a> {
33383349
vis.is_accessible_from(module.normal_ancestor_id.unwrap(), self)
33393350
}
33403351

3341-
fn report_errors(&self) {
3352+
fn report_errors(&mut self) {
3353+
self.report_shadowing_errors();
33423354
let mut reported_spans = FnvHashSet();
33433355

33443356
for &AmbiguityError { span, name, b1, b2 } in &self.ambiguity_errors {
@@ -3366,6 +3378,20 @@ impl<'a> Resolver<'a> {
33663378
}
33673379
}
33683380

3381+
fn report_shadowing_errors(&mut self) {
3382+
let mut reported_errors = FnvHashSet();
3383+
for (name, span, scope) in replace(&mut self.disallowed_shadowing, Vec::new()) {
3384+
if self.resolve_macro_name(scope, name, false).is_some() &&
3385+
reported_errors.insert((name, span)) {
3386+
let msg = format!("`{}` is already in scope", name);
3387+
self.session.struct_span_err(span, &msg)
3388+
.note("macro-expanded `macro_rules!`s may not shadow \
3389+
existing macros (see RFC 1560)")
3390+
.emit();
3391+
}
3392+
}
3393+
}
3394+
33693395
fn report_conflict(&self,
33703396
parent: Module,
33713397
name: Name,

0 commit comments

Comments
 (0)