Skip to content

Commit f3a66c0

Browse files
committed
Merge pull request #449 from Manishearth/shadow_visitor
use visitor for contains_self
2 parents 12d1d6f + aea2eb7 commit f3a66c0

File tree

1 file changed

+12
-88
lines changed

1 file changed

+12
-88
lines changed

src/shadow.rs

+12-88
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::ops::Deref;
22
use rustc_front::hir::*;
33
use reexport::*;
44
use syntax::codemap::Span;
5-
use rustc_front::visit::FnKind;
5+
use rustc_front::visit::{Visitor, FnKind};
66

77
use rustc::lint::*;
88
use rustc::middle::def::Def::{DefVariant, DefStruct};
@@ -269,97 +269,21 @@ fn path_eq_name(name: Name, path: &Path) -> bool {
269269
path.segments[0].identifier.name == name
270270
}
271271

272-
fn contains_self(name: Name, expr: &Expr) -> bool {
273-
match expr.node {
274-
// the "self" name itself (maybe)
275-
ExprPath(_, ref path) => path_eq_name(name, path),
276-
// no subexprs
277-
ExprLit(_) => false,
278-
// one subexpr
279-
ExprUnary(_, ref e) | ExprField(ref e, _) |
280-
ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(ref e) |
281-
ExprCast(ref e, _) =>
282-
contains_self(name, e),
283-
// two subexprs
284-
ExprBinary(_, ref l, ref r) | ExprIndex(ref l, ref r) |
285-
ExprAssign(ref l, ref r) | ExprAssignOp(_, ref l, ref r) |
286-
ExprRepeat(ref l, ref r) =>
287-
contains_self(name, l) || contains_self(name, r),
288-
// one optional subexpr
289-
ExprRet(ref oe) =>
290-
oe.as_ref().map_or(false, |ref e| contains_self(name, e)),
291-
// two optional subexprs
292-
ExprRange(ref ol, ref or) =>
293-
ol.as_ref().map_or(false, |ref e| contains_self(name, e)) ||
294-
or.as_ref().map_or(false, |ref e| contains_self(name, e)),
295-
// one subblock
296-
ExprBlock(ref block) | ExprLoop(ref block, _) |
297-
ExprClosure(_, _, ref block) =>
298-
contains_block_self(name, block),
299-
// one vec
300-
ExprMethodCall(_, _, ref v) | ExprVec(ref v) | ExprTup(ref v) =>
301-
v.iter().any(|ref a| contains_self(name, a)),
302-
// one expr, one vec
303-
ExprCall(ref fun, ref args) =>
304-
contains_self(name, fun) ||
305-
args.iter().any(|ref a| contains_self(name, a)),
306-
// special ones
307-
ExprIf(ref cond, ref then, ref otherwise) =>
308-
contains_self(name, cond) || contains_block_self(name, then) ||
309-
otherwise.as_ref().map_or(false, |ref e| contains_self(name, e)),
310-
ExprWhile(ref e, ref block, _) =>
311-
contains_self(name, e) || contains_block_self(name, block),
312-
ExprMatch(ref e, ref arms, _) =>
313-
contains_self(name, e) ||
314-
arms.iter().any(
315-
|ref arm|
316-
arm.pats.iter().any(|ref pat| contains_pat_self(name, pat)) ||
317-
arm.guard.as_ref().map_or(false, |ref g| contains_self(name, g)) ||
318-
contains_self(name, &arm.body)),
319-
ExprStruct(_, ref fields, ref other) =>
320-
fields.iter().any(|ref f| contains_self(name, &f.expr)) ||
321-
other.as_ref().map_or(false, |ref e| contains_self(name, e)),
322-
_ => false,
323-
}
272+
struct ContainsSelf {
273+
name: Name,
274+
result: bool
324275
}
325276

326-
fn contains_block_self(name: Name, block: &Block) -> bool {
327-
for stmt in &block.stmts {
328-
match stmt.node {
329-
StmtDecl(ref decl, _) =>
330-
if let DeclLocal(ref local) = decl.node {
331-
//TODO: We don't currently handle the case where the name
332-
//is shadowed wiithin the block; this means code including this
333-
//degenerate pattern will get the wrong warning.
334-
if let Some(ref init) = local.init {
335-
if contains_self(name, init) { return true; }
336-
}
337-
},
338-
StmtExpr(ref e, _) | StmtSemi(ref e, _) =>
339-
if contains_self(name, e) { return true }
277+
impl<'v> Visitor<'v> for ContainsSelf {
278+
fn visit_name(&mut self, _: Span, name: Name) {
279+
if self.name == name {
280+
self.result = true;
340281
}
341282
}
342-
if let Some(ref e) = block.expr { contains_self(name, e) } else { false }
343283
}
344284

345-
fn contains_pat_self(name: Name, pat: &Pat) -> bool {
346-
match pat.node {
347-
PatIdent(_, ref ident, ref inner) => name == ident.node.name ||
348-
inner.as_ref().map_or(false, |ref p| contains_pat_self(name, p)),
349-
PatEnum(_, ref opats) => opats.as_ref().map_or(false,
350-
|pats| pats.iter().any(|p| contains_pat_self(name, p))),
351-
PatQPath(_, ref path) => path_eq_name(name, path),
352-
PatStruct(_, ref fieldpats, _) => fieldpats.iter().any(
353-
|ref fp| contains_pat_self(name, &fp.node.pat)),
354-
PatTup(ref ps) => ps.iter().any(|ref p| contains_pat_self(name, p)),
355-
PatBox(ref p) |
356-
PatRegion(ref p, _) => contains_pat_self(name, p),
357-
PatRange(ref from, ref until) =>
358-
contains_self(name, from) || contains_self(name, until),
359-
PatVec(ref pre, ref opt, ref post) =>
360-
pre.iter().any(|ref p| contains_pat_self(name, p)) ||
361-
opt.as_ref().map_or(false, |ref p| contains_pat_self(name, p)) ||
362-
post.iter().any(|ref p| contains_pat_self(name, p)),
363-
_ => false,
364-
}
285+
fn contains_self(name: Name, expr: &Expr) -> bool {
286+
let mut cs = ContainsSelf { name: name, result: false };
287+
cs.visit_expr(expr);
288+
cs.result
365289
}

0 commit comments

Comments
 (0)