Skip to content

Instantly share code, notes, and snippets.

@mrhota
Created November 9, 2014 01:33
Show Gist options
  • Save mrhota/d11ade4db40b911e7dcf to your computer and use it in GitHub Desktop.
Save mrhota/d11ade4db40b911e7dcf to your computer and use it in GitHub Desktop.
#![forbid(shadowed_name)]
#![allow(unused_variables)]
pub fn main() {
let foo = 0i;
{
let foo = Some(2.0f64); //~ ERROR foo is shadowed
}
}
// $> rustc src/test/compile-fail/lint-simple-shadow.rs
// src/test/compile-fail/lint-simple-shadow.rs:17:13: 17:16 error: foo is shadowed
// src/test/compile-fail/lint-simple-shadow.rs:17 let foo = Some(2.0f64); //~ ERROR foo is shadowed
// ^~~
// src/test/compile-fail/lint-simple-shadow.rs:11:11: 11:24 note: lint level defined here
// src/test/compile-fail/lint-simple-shadow.rs:11 #![forbid(shadowed_name)]
// ^~~~~~~~~~~~~
// src/test/compile-fail/lint-simple-shadow.rs:15:9: 15:12 note: foo shadowed here
// src/test/compile-fail/lint-simple-shadow.rs:15 let foo = 0i;
// --------
declare_lint!(pub SHADOWED_NAME, Allow,
"detects declarations which shadow names from enclosing scopes")
pub struct ShadowedName {
shadowed_names: HashMap<ast::Name, ast::NodeId>,
}
impl ShadowedName {
pub fn new() -> ShadowedName {
ShadowedName {
shadowed_names: HashMap::new(),
}
}
}
impl LintPass for ShadowedName {
fn get_lints(&self) -> LintArray {
lint_array!(SHADOWED_NAME)
}
fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
match p.node {
ast::PatIdent(_, spannedident, _) => {
let name = spannedident.node.name;
match self.shadowed_names.entry(name) {
Vacant(entry) => {
entry.set(p.id);
},
Occupied(entry) => {
// name is potentially shadowing something!
let ref rmap = cx.tcx.region_maps;
let &origid = entry.get();
let origscope = match rmap.opt_encl_scope(origid) {
Some(s) => s,
None => return
};
let thisscope = match rmap.opt_encl_scope(p.id) {
Some(s) => s,
None => return
};
if origscope != thisscope {
let lvl = cx.current_level(SHADOWED_NAME);
if rmap.is_subscope_of(thisscope, origscope) {
cx.span_lint(SHADOWED_NAME, cx.tcx.map.span(origid),
format!("{} is shadowed",
token::get_name(name)).as_slice());
if lvl > lint::Allow {
span_note!(cx.sess(), p.span, "{} shadowed here",
token::get_name(name));
}
} else {
cx.span_lint(SHADOWED_NAME, p.span,
format!("{} is shadowed",
token::get_name(name)).as_slice());
if lvl > lint::Allow {
span_note!(cx.sess(), cx.tcx.map.span(origid),
"{} shadowed here",
token::get_name(name));
}
}
} else {
println!("{} scope was weird", name);
println!("origscope: {}", origscope);
println!("thisscope: {}", thisscope);
}
},
}
},
_ => {},
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment