Skip to content

Commit ed1e002

Browse files
committed
Enforce the weakened shadowing restriction.
1 parent 72544af commit ed1e002

File tree

3 files changed

+68
-17
lines changed

3 files changed

+68
-17
lines changed

src/librustc_resolve/build_reduced_graph.rs

+27-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//! Here we build the "reduced graph": the graph of the module tree without
1414
//! any imports resolved.
1515
16+
use macros;
1617
use resolve_imports::ImportDirectiveSubclass::{self, GlobImport};
1718
use {Module, ModuleS, ModuleKind};
1819
use Namespace::{self, TypeNS, ValueNS};
@@ -39,6 +40,7 @@ use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
3940
use syntax::ext::base::{MultiItemModifier, Resolver as SyntaxResolver};
4041
use syntax::ext::hygiene::Mark;
4142
use syntax::feature_gate::{self, emit_feature_err};
43+
use syntax::ext::tt::macro_rules;
4244
use syntax::parse::token::keywords;
4345
use syntax::visit::{self, Visitor};
4446

@@ -77,7 +79,7 @@ impl<'b> Resolver<'b> {
7779
}
7880

7981
/// Constructs the reduced graph for one item.
80-
fn build_reduced_graph_for_item(&mut self, item: &Item) {
82+
fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
8183
let parent = self.current_module;
8284
let name = item.ident.name;
8385
let sp = item.span;
@@ -188,9 +190,28 @@ impl<'b> Resolver<'b> {
188190
// We need to error on `#[macro_use] extern crate` when it isn't at the
189191
// crate root, because `$crate` won't work properly.
190192
let is_crate_root = self.current_module.parent.is_none();
191-
for def in self.crate_loader.load_macros(item, is_crate_root) {
192-
match def.kind {
193-
LoadedMacroKind::Def(def) => self.add_macro(Mark::root(), def),
193+
for loaded_macro in self.crate_loader.load_macros(item, is_crate_root) {
194+
match loaded_macro.kind {
195+
LoadedMacroKind::Def(mut def) => {
196+
let name = def.ident.name;
197+
if def.use_locally {
198+
let ext = macro_rules::compile(&self.session.parse_sess, &def);
199+
let shadowing =
200+
self.resolve_macro_name(Mark::root(), name, false).is_some();
201+
self.expansion_data[&Mark::root()].module.macros.borrow_mut()
202+
.insert(name, macros::NameBinding {
203+
ext: Rc::new(ext),
204+
expansion: expansion,
205+
shadowing: shadowing,
206+
span: loaded_macro.import_site,
207+
});
208+
self.macro_names.insert(name);
209+
}
210+
if def.export {
211+
def.id = self.next_node_id();
212+
self.exported_macros.push(def);
213+
}
214+
}
194215
LoadedMacroKind::CustomDerive(name, ext) => {
195216
self.insert_custom_derive(&name, ext, item.span);
196217
}
@@ -527,6 +548,7 @@ impl<'b> Resolver<'b> {
527548

528549
pub struct BuildReducedGraphVisitor<'a, 'b: 'a> {
529550
pub resolver: &'a mut Resolver<'b>,
551+
pub expansion: Mark,
530552
}
531553

532554
impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
@@ -562,7 +584,7 @@ impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> {
562584
}
563585

564586
let parent = self.resolver.current_module;
565-
self.resolver.build_reduced_graph_for_item(item);
587+
self.resolver.build_reduced_graph_for_item(item, self.expansion);
566588
visit::walk_item(self, item);
567589
self.resolver.current_module = parent;
568590
}

src/librustc_resolve/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,7 @@ pub struct Resolver<'a> {
10731073

10741074
privacy_errors: Vec<PrivacyError<'a>>,
10751075
ambiguity_errors: Vec<AmbiguityError<'a>>,
1076+
macro_shadowing_errors: FnvHashSet<Span>,
10761077

10771078
arenas: &'a ResolverArenas<'a>,
10781079
dummy_binding: &'a NameBinding<'a>,
@@ -1248,6 +1249,7 @@ impl<'a> Resolver<'a> {
12481249

12491250
privacy_errors: Vec::new(),
12501251
ambiguity_errors: Vec::new(),
1252+
macro_shadowing_errors: FnvHashSet(),
12511253

12521254
arenas: arenas,
12531255
dummy_binding: arenas.alloc_name_binding(NameBinding {

src/librustc_resolve/macros.rs

+39-12
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@ use syntax::ext::hygiene::{Mark, SyntaxContext};
2222
use syntax::ext::tt::macro_rules;
2323
use syntax::parse::token::intern;
2424
use syntax::util::lev_distance::find_best_match_for_name;
25+
use syntax_pos::{Span, DUMMY_SP};
2526

2627
// FIXME(jseyfried) Merge with `::NameBinding`.
2728
pub struct NameBinding {
28-
ext: Rc<SyntaxExtension>,
29+
pub ext: Rc<SyntaxExtension>,
30+
pub expansion: Mark,
31+
pub shadowing: bool,
32+
pub span: Span,
2933
}
3034

3135
#[derive(Clone)]
@@ -69,24 +73,26 @@ impl<'a> base::Resolver for Resolver<'a> {
6973
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion) {
7074
self.collect_def_ids(mark, expansion);
7175
self.current_module = self.expansion_data[&mark].module;
72-
expansion.visit_with(&mut BuildReducedGraphVisitor { resolver: self });
76+
expansion.visit_with(&mut BuildReducedGraphVisitor { resolver: self, expansion: mark });
7377
}
7478

7579
fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef) {
7680
if &def.ident.name.as_str() == "macro_rules" {
7781
self.session.span_err(def.span, "user-defined macros may not be named `macro_rules`");
7882
}
7983
if def.use_locally {
80-
self.macro_names.insert(def.ident.name);
81-
let ext = macro_rules::compile(&self.session.parse_sess, &def);
82-
83-
let mut module = self.expansion_data[&scope].module;
84+
let ExpansionData { mut module, backtrace, .. } = self.expansion_data[&scope];
8485
while module.macros_escape {
8586
module = module.parent.unwrap();
8687
}
87-
module.macros.borrow_mut().insert(def.ident.name, NameBinding {
88-
ext: Rc::new(ext),
89-
});
88+
let binding = NameBinding {
89+
ext: Rc::new(macro_rules::compile(&self.session.parse_sess, &def)),
90+
expansion: backtrace.data().prev_ctxt.data().outer_mark,
91+
shadowing: self.resolve_macro_name(scope, def.ident.name, false).is_some(),
92+
span: def.span,
93+
};
94+
module.macros.borrow_mut().insert(def.ident.name, binding);
95+
self.macro_names.insert(def.ident.name);
9096
}
9197
if def.export {
9298
def.id = self.next_node_id();
@@ -100,6 +106,9 @@ impl<'a> base::Resolver for Resolver<'a> {
100106
}
101107
self.graph_root.macros.borrow_mut().insert(ident.name, NameBinding {
102108
ext: ext,
109+
expansion: Mark::root(),
110+
shadowing: false,
111+
span: DUMMY_SP,
103112
});
104113
}
105114

@@ -138,7 +147,7 @@ impl<'a> base::Resolver for Resolver<'a> {
138147
InvocationKind::Attr { ref attr, .. } => (intern(&*attr.name()), attr.span),
139148
};
140149

141-
self.resolve_macro_name(scope, name).or_else(|| {
150+
self.resolve_macro_name(scope, name, true).or_else(|| {
142151
let mut err =
143152
self.session.struct_span_err(span, &format!("macro undefined: '{}!'", name));
144153
self.suggest_macro_name(&name.as_str(), &mut err);
@@ -153,10 +162,28 @@ impl<'a> base::Resolver for Resolver<'a> {
153162
}
154163

155164
impl<'a> Resolver<'a> {
156-
fn resolve_macro_name(&mut self, scope: Mark, name: ast::Name) -> Option<Rc<SyntaxExtension>> {
157-
let mut module = self.expansion_data[&scope].module;
165+
pub fn resolve_macro_name(&mut self, scope: Mark, name: ast::Name, record_used: bool)
166+
-> Option<Rc<SyntaxExtension>> {
167+
let ExpansionData { mut module, backtrace, .. } = self.expansion_data[&scope];
158168
loop {
159169
if let Some(binding) = module.macros.borrow().get(&name) {
170+
let mut backtrace = backtrace.data();
171+
while binding.expansion != backtrace.outer_mark {
172+
if backtrace.outer_mark != Mark::root() {
173+
backtrace = backtrace.prev_ctxt.data();
174+
continue
175+
}
176+
177+
if record_used && binding.shadowing &&
178+
self.macro_shadowing_errors.insert(binding.span) {
179+
let msg = format!("`{}` is already in scope", name);
180+
self.session.struct_span_err(binding.span, &msg)
181+
.note("macro-expanded `macro_rules!`s and `#[macro_use]`s \
182+
may not shadow existing macros (see RFC 1560)")
183+
.emit();
184+
}
185+
break
186+
}
160187
return Some(binding.ext.clone());
161188
}
162189
match module.parent {

0 commit comments

Comments
 (0)