diff --git a/src/shadow.rs b/src/shadow.rs index bbd146f77a5a..1c09bffd9e62 100644 --- a/src/shadow.rs +++ b/src/shadow.rs @@ -39,12 +39,6 @@ fn check_fn(cx: &Context, decl: &FnDecl, block: &Block) { check_block(cx, block, &mut bindings); } -fn named(pat: &Pat) -> Option { - if let PatIdent(_, ident, _) = pat.node { - Some(ident.node.name) - } else { None } -} - fn check_block(cx: &Context, block: &Block, bindings: &mut Vec) { let len = bindings.len(); for stmt in &block.stmts { @@ -64,25 +58,46 @@ fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec) { if let DeclLocal(ref local) = decl.node { let Local{ ref pat, ref ty, ref init, id: _, span } = **local; if let &Some(ref t) = ty { check_ty(cx, t, bindings) } - check_pat(cx, pat, init, span, bindings); if let &Some(ref o) = init { check_expr(cx, o, bindings) } + check_pat(cx, pat, init, span, bindings); } } fn check_pat(cx: &Context, pat: &Pat, init: &Option, span: Span, bindings: &mut Vec) where T: Deref { //TODO: match more stuff / destructuring - named(pat).map(|name| { - if let &Some(ref o) = init { - if !in_external_macro(cx, o.span) { - check_expr(cx, o, bindings); + match pat.node { + PatIdent(_, ref ident, ref inner) => { + let name = ident.node.name; + if pat_is_binding(&cx.tcx.def_map, pat) { + if bindings.contains(&name) { + lint_shadow(cx, name, span, pat.span, init); + } + bindings.push(name); } - } - if bindings.contains(&name) { - lint_shadow(cx, name, span, pat.span, init); - } - bindings.push(name); - }); + if let Some(ref p) = *inner { check_pat(cx, p, init, span, bindings); } + }, + //PatEnum(Path, Option>>), + //PatQPath(QSelf, Path), + //PatStruct(Path, Vec>, bool), + //PatTup(Vec>), + PatBox(ref inner) => { + if let Some(ref initp) = *init { + match initp.node { + ExprBox(_, ref inner_init) => + check_pat(cx, inner, &Some(&**inner_init), span, bindings), + //TODO: ExprCall on Box::new + _ => check_pat(cx, inner, init, span, bindings), + } + } else { + check_pat(cx, inner, init, span, bindings); + } + }, + //PatRegion(P, Mutability), + //PatRange(P, P), + //PatVec(Vec>, Option>, Vec>), + _ => (), + } } fn lint_shadow(cx: &Context, name: Name, span: Span, lspan: Span, init: @@ -122,6 +137,8 @@ fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec) { check_expr(cx, place, bindings); check_expr(cx, e, bindings) } ExprBlock(ref block) | ExprLoop(ref block, _) => { check_block(cx, block, bindings) }, + //ExprCall + //ExprMethodCall ExprVec(ref v) | ExprTup(ref v) => for ref e in v { check_expr(cx, e, bindings) }, ExprIf(ref cond, ref then, ref otherwise) => { @@ -133,17 +150,19 @@ fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec) { check_expr(cx, cond, bindings); check_block(cx, block, bindings); }, - ExprMatch(ref init, ref arms, _) => + ExprMatch(ref init, ref arms, _) => { + check_expr(cx, init, bindings); for ref arm in arms { for ref pat in &arm.pats { + check_pat(cx, &pat, &Some(&**init), pat.span, bindings); //TODO: This is ugly, but needed to get the right type - check_pat(cx, pat, &Some(&**init), pat.span, bindings); } if let Some(ref guard) = arm.guard { check_expr(cx, guard, bindings); } - check_expr(cx, &*arm.body, bindings); - }, + check_expr(cx, &arm.body, bindings); + } + }, _ => () } } @@ -179,7 +198,8 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool { } fn path_eq_name(name: Name, path: &Path) -> bool { - path.segments.len() == 1 && path.segments[0].identifier.name == name + !path.global && path.segments.len() == 1 && + path.segments[0].identifier.name == name } fn contains_self(name: Name, expr: &Expr) -> bool { @@ -205,8 +225,7 @@ fn contains_self(name: Name, expr: &Expr) -> bool { ExprMatch(ref e, ref arms, _) => arms.iter().any(|ref arm| arm.pats.iter().any(|ref pat| contains_pat_self(name, pat))) || contains_self(name, e), - ExprPath(_, ref path) => path.segments.len() == 1 && - path.segments[0].identifier.name == name, + ExprPath(_, ref path) => path_eq_name(name, path), _ => false } }