Skip to content

Commit 8667465

Browse files
committed
Refactor macro-shadowing into a LintPass
This moves the shadowing check from an early check that happens during macro expansion to a late lint-pass check (which inspects the crate rather than the syntax expansion context).
1 parent 2916678 commit 8667465

File tree

3 files changed

+49
-15
lines changed

3 files changed

+49
-15
lines changed

src/libcore/macros.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
#![macro_escape]
12+
#![allow(shadowing_macros)]
1213

1314
// NOTE(stage0): Remove cfg after a snapshot
1415
#[cfg(not(stage0))]

src/librustc/lint/builtin.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1627,6 +1627,52 @@ impl LintPass for MissingCopyImplementations {
16271627
}
16281628
}
16291629

1630+
declare_lint! {
1631+
pub SHADOWING_MACROS,
1632+
Warn,
1633+
"detects shadowing macro definitions"
1634+
}
1635+
1636+
#[deriving(Copy)]
1637+
pub struct ShadowingMacrosPass;
1638+
1639+
impl LintPass for ShadowingMacrosPass {
1640+
fn get_lints(&self) -> LintArray {
1641+
lint_array!(SHADOWING_MACROS)
1642+
}
1643+
1644+
fn check_crate(&mut self, cx: &Context, krate: &ast::Crate) {
1645+
// Will map name uints to macro ast::Items. The loop below will then
1646+
// make a lint warning if a macro use with the name already exists
1647+
// in the map, or add that macro to the map so that subsequent ones
1648+
// with the same name will warn.
1649+
let mut uses = FnvHashMap::new();
1650+
1651+
for it in krate.macros.iter() {
1652+
let name = it.ident.name;
1653+
match uses.get(&name.uint()) {
1654+
Some(_) => {
1655+
let span = it.span;
1656+
// FIXME: Include span-printing of the first use to
1657+
// help users.
1658+
cx.span_lint(
1659+
SHADOWING_MACROS,
1660+
span,
1661+
format!(
1662+
"shadowing macro definition: {}",
1663+
name.as_str()
1664+
)[]
1665+
);
1666+
continue;
1667+
},
1668+
None => { }
1669+
}
1670+
// Have to put None-case here to dodge the borrow-checker.
1671+
uses.insert(name.uint(), it);
1672+
}
1673+
}
1674+
}
1675+
16301676
declare_lint! {
16311677
DEPRECATED,
16321678
Warn,
@@ -1903,7 +1949,8 @@ impl LintPass for HardwiredLints {
19031949
UNKNOWN_FEATURES,
19041950
UNKNOWN_CRATE_TYPES,
19051951
VARIANT_SIZE_DIFFERENCES,
1906-
FAT_PTR_TRANSMUTES
1952+
FAT_PTR_TRANSMUTES,
1953+
SHADOWING_MACROS
19071954
)
19081955
}
19091956
}

src/libsyntax/ext/tt/macro_rules.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -273,20 +273,6 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt,
273273
_ => cx.span_bug(sp, "wrong-structured rhs")
274274
};
275275

276-
// Warn if the name already exists in our local macro syntax environment
277-
match cx.syntax_env.find(&name.name) {
278-
Some(_) => {
279-
cx.span_warn(
280-
sp,
281-
format!(
282-
"shadowing macro definition: {}",
283-
name.as_str()
284-
)[]
285-
);
286-
},
287-
None => {}
288-
};
289-
290276
let exp = box MacroRulesMacroExpander {
291277
name: name,
292278
lhses: lhses,

0 commit comments

Comments
 (0)