This commit is contained in:
Manish Goregaokar 2016-02-29 16:49:32 +05:30
parent e256055dc4
commit bd45cfd273
18 changed files with 137 additions and 203 deletions

View File

@ -92,8 +92,7 @@ fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
snippet_block(cx, then.span, "..")));
}
} else {
let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span,
|e| e.span);
let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span);
if in_macro(cx, span) || differing_macro_contexts(expr.span, span) {
return;
}

View File

@ -71,15 +71,13 @@ fn check_if(cx: &LateContext, e: &Expr) {
});
}}
} else if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), span: sp, ..}) =
single_stmt_of_block(then) {
single_stmt_of_block(then) {
if e.span.expn_id != sp.expn_id {
return;
}
span_lint_and_then(cx,
COLLAPSIBLE_IF,
e.span,
"this if statement can be collapsed", |db| {
db.span_suggestion(e.span, "try",
span_lint_and_then(cx, COLLAPSIBLE_IF, e.span, "this if statement can be collapsed", |db| {
db.span_suggestion(e.span,
"try",
format!("if {} && {} {}",
check_to_string(cx, check),
check_to_string(cx, check_inner),

View File

@ -91,9 +91,7 @@ fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) {
h.finish()
};
let eq: &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool {
SpanlessEq::new(cx).eq_block(lhs, rhs)
};
let eq: &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) };
if let Some((i, j)) = search_same(blocks, hash, eq) {
span_note_and_lint(cx,

View File

@ -87,13 +87,7 @@ fn check_item(&mut self, cx: &LateContext, item: &Item) {
}
/// Implementation of the `DERIVE_HASH_XOR_EQ` lint.
fn check_hash_peq(
cx: &LateContext,
span: Span,
trait_ref: &TraitRef,
ty: ty::Ty,
hash_is_automatically_derived: bool
) {
fn check_hash_peq(cx: &LateContext, span: Span, trait_ref: &TraitRef, ty: ty::Ty, hash_is_automatically_derived: bool) {
if_let_chain! {[
match_path(&trait_ref.path, &HASH_PATH),
let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait()
@ -143,9 +137,7 @@ fn check_hash_peq(
}
/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>,
item: &Item,
trait_ref: &TraitRef, ty: ty::Ty<'tcx>) {
fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref: &TraitRef, ty: ty::Ty<'tcx>) {
if match_path(&trait_ref.path, &CLONE_TRAIT_PATH) {
let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, item.id);
let subst_ty = ty.subst(cx.tcx, &parameter_environment.free_substs);

View File

@ -48,7 +48,7 @@ fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
// in case of `if !m.contains_key(&k) { m.insert(k, v); }`
// we can give a better error message
let sole_expr = else_block.is_none() &&
if then_block.expr.is_some() { 1 } else { 0 } + then_block.stmts.len() == 1;
((then_block.expr.is_some() as usize) + then_block.stmts.len() == 1);
let mut visitor = InsertVisitor {
cx: cx,

View File

@ -31,17 +31,16 @@ fn var2str(var: &Variant) -> InternedString {
var.node.name.name.as_str()
}
/*
FIXME: waiting for https://github.com/rust-lang/rust/pull/31700
fn partial_match(pre: &str, name: &str) -> usize {
// skip(1) to ensure that the prefix never takes the whole variant name
pre.chars().zip(name.chars().rev().skip(1).rev()).take_while(|&(l, r)| l == r).count()
}
fn partial_rmatch(post: &str, name: &str) -> usize {
// skip(1) to ensure that the postfix never takes the whole variant name
post.chars().rev().zip(name.chars().skip(1).rev()).take_while(|&(l, r)| l == r).count()
}*/
// FIXME: waiting for https://github.com/rust-lang/rust/pull/31700
// fn partial_match(pre: &str, name: &str) -> usize {
// // skip(1) to ensure that the prefix never takes the whole variant name
// pre.chars().zip(name.chars().rev().skip(1).rev()).take_while(|&(l, r)| l == r).count()
// }
//
// fn partial_rmatch(post: &str, name: &str) -> usize {
// // skip(1) to ensure that the postfix never takes the whole variant name
// post.chars().rev().zip(name.chars().skip(1).rev()).take_while(|&(l, r)| l == r).count()
// }
fn partial_match(pre: &str, name: &str) -> usize {
let mut name_iter = name.chars();
@ -99,7 +98,8 @@ fn check_item(&mut self, cx: &EarlyContext, item: &Item) {
item.span,
&format!("All variants have the same {}fix: `{}`", what, value),
&format!("remove the {}fixes and use full paths to \
the variants instead of glob imports", what));
the variants instead of glob imports",
what));
}
}
}

View File

@ -96,9 +96,11 @@ fn check_assign(cx: &EarlyContext, expr: &ast::Expr) {
span_note_and_lint(cx,
SUSPICIOUS_ASSIGNMENT_FORMATTING,
eqop_span,
&format!("this looks like you are trying to use `.. {op}= ..`, but you really are doing `.. = ({op} ..)`", op=op),
&format!("this looks like you are trying to use `.. {op}= ..`, but you \
really are doing `.. = ({op} ..)`",
op = op),
eqop_span,
&format!("to remove this lint, use either `{op}=` or `= {op}`", op=op));
&format!("to remove this lint, use either `{op}=` or `= {op}`", op = op));
}
}
}
@ -109,9 +111,7 @@ fn check_assign(cx: &EarlyContext, expr: &ast::Expr) {
/// Implementation of the SUSPICIOUS_ELSE_FORMATTING lint for weird `else if`.
fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) {
if let Some((then, &Some(ref else_))) = unsugar_if(expr) {
if unsugar_if(else_).is_some() &&
!differing_macro_contexts(then.span, else_.span) &&
!in_macro(cx, then.span) {
if unsugar_if(else_).is_some() && !differing_macro_contexts(then.span, else_.span) && !in_macro(cx, then.span) {
// this will be a span from the closing } of the “then” block (excluding) to the
// “if” of the “else if” block (excluding)
let else_span = mk_sp(then.span.hi, else_.span.lo);
@ -127,7 +127,8 @@ fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) {
else_span,
"this is an `else if` but the formatting might hide it",
else_span,
"to remove this lint, remove the `else` or remove the new line between `else` and `if`");
"to remove this lint, remove the `else` or remove the new line between `else` \
and `if`");
}
}
}
@ -136,10 +137,8 @@ fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) {
/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for consecutive ifs.
fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Expr) {
if !differing_macro_contexts(first.span, second.span) &&
!in_macro(cx, first.span) &&
unsugar_if(first).is_some() &&
unsugar_if(second).is_some() {
if !differing_macro_contexts(first.span, second.span) && !in_macro(cx, first.span) &&
unsugar_if(first).is_some() && unsugar_if(second).is_some() {
// where the else would be
let else_span = mk_sp(first.span.hi, second.span.lo);
@ -150,14 +149,15 @@ fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Exp
else_span,
"this looks like an `else if` but the `else` is missing",
else_span,
"to remove this lint, add the missing `else` or add a new line before the second `if`");
"to remove this lint, add the missing `else` or add a new line before the second \
`if`");
}
}
}
}
/// Match `if` or `else if` expressions and return the `then` and `else` block.
fn unsugar_if(expr: &ast::Expr) -> Option<(&P<ast::Block>, &Option<P<ast::Expr>>)>{
fn unsugar_if(expr: &ast::Expr) -> Option<(&P<ast::Block>, &Option<P<ast::Expr>>)> {
match expr.node {
ast::ExprKind::If(_, ref then, ref else_) |
ast::ExprKind::IfLet(_, _, ref then, ref else_) => Some((then, else_)),

View File

@ -155,17 +155,11 @@ fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str)
fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], lit: &Lit, op: &str) {
if let Spanned{node: LitKind::Int(0, _), ..} = *lit {
if name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) {
span_lint_and_then(cx,
LEN_ZERO,
span,
"length comparison to zero",
|db| {
db.span_suggestion(span,
"consider using `is_empty`",
format!("{}{}.is_empty()",
op,
snippet(cx, args[0].span, "_")));
});
span_lint_and_then(cx, LEN_ZERO, span, "length comparison to zero", |db| {
db.span_suggestion(span,
"consider using `is_empty`",
format!("{}{}.is_empty()", op, snippet(cx, args[0].span, "_")));
});
}
}
}

View File

@ -370,14 +370,14 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex
span_lint(cx,
NEEDLESS_RANGE_LOOP,
expr.span,
&format!("the loop variable `{}` is used to index `{}`. \
Consider using `for ({}, item) in {}.iter().enumerate(){}{}` or similar iterators",
ident.node.name,
indexed,
ident.node.name,
indexed,
take,
skip));
&format!("the loop variable `{}` is used to index `{}`. Consider using `for ({}, \
item) in {}.iter().enumerate(){}{}` or similar iterators",
ident.node.name,
indexed,
ident.node.name,
indexed,
take,
skip));
} else {
let repl = if starts_at_zero && take.is_empty() {
format!("&{}", indexed)
@ -390,9 +390,9 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex
expr.span,
&format!("the loop variable `{}` is only used to index `{}`. \
Consider using `for item in {}` or similar iterators",
ident.node.name,
indexed,
repl));
ident.node.name,
indexed,
repl));
}
}
}
@ -447,9 +447,7 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) {
"consider using the following if \
you are attempting to iterate \
over this range in reverse",
format!("({}..{}).rev()` ",
stop_snippet,
start_snippet));
format!("({}..{}).rev()` ", stop_snippet, start_snippet));
});
} else if eq {
// if they are equal, it's also problematic - this loop
@ -744,6 +742,7 @@ fn visit_expr(&mut self, expr: &'v Expr) {
/// Return true if the type of expr is one that provides IntoIterator impls
/// for &T and &mut T, such as Vec.
#[cfg_attr(rustfmt, rustfmt_skip)]
fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool {
// no walk_ptrs_ty: calling iter() on a reference can make sense because it
// will allow further borrows afterwards

View File

@ -1,10 +1,8 @@
use rustc::lint::*;
use rustc_front::hir::*;
use utils::{CLONE_PATH, OPTION_PATH};
use utils::{
is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint,
walk_ptrs_ty, walk_ptrs_ty_depth
};
use utils::{is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint, walk_ptrs_ty,
walk_ptrs_ty_depth};
/// **What it does:** This lint checks for mapping clone() over an iterator.
///

View File

@ -134,10 +134,11 @@ fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
}
}
#[cfg_attr(rustfmt, rustfmt_skip)]
fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
if arms.len() == 2 &&
arms[0].pats.len() == 1 && arms[0].guard.is_none() &&
arms[1].pats.len() == 1 && arms[1].guard.is_none() {
arms[0].pats.len() == 1 && arms[0].guard.is_none() &&
arms[1].pats.len() == 1 && arms[1].guard.is_none() {
let els = if is_unit_expr(&arms[1].body) {
None
} else if let ExprBlock(_) = arms[1].body.node {
@ -167,28 +168,28 @@ fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm],
lint,
expr.span,
"you seem to be trying to use match for destructuring a single pattern. \
Consider using `if let`", |db| {
db.span_suggestion(expr.span, "try this",
format!("if let {} = {} {}{}",
snippet(cx, arms[0].pats[0].span, ".."),
snippet(cx, ex.span, ".."),
expr_block(cx, &arms[0].body, None, ".."),
els_str));
});
Consider using `if let`",
|db| {
db.span_suggestion(expr.span,
"try this",
format!("if let {} = {} {}{}",
snippet(cx, arms[0].pats[0].span, ".."),
snippet(cx, ex.span, ".."),
expr_block(cx, &arms[0].body, None, ".."),
els_str));
});
}
}
fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, ty: ty::Ty, els: Option<&Expr>) {
// list of candidate Enums we know will never get any more members
let candidates = &[
(&COW_PATH, "Borrowed"),
(&COW_PATH, "Cow::Borrowed"),
(&COW_PATH, "Cow::Owned"),
(&COW_PATH, "Owned"),
(&OPTION_PATH, "None"),
(&RESULT_PATH, "Err"),
(&RESULT_PATH, "Ok"),
];
let candidates = &[(&COW_PATH, "Borrowed"),
(&COW_PATH, "Cow::Borrowed"),
(&COW_PATH, "Cow::Owned"),
(&COW_PATH, "Owned"),
(&OPTION_PATH, "None"),
(&RESULT_PATH, "Err"),
(&RESULT_PATH, "Ok")];
let path = match arms[1].pats[0].node {
PatKind::TupleStruct(ref path, Some(ref inner)) => {

View File

@ -565,7 +565,9 @@ fn lint_clone_double_ref(cx: &LateContext, expr: &Expr, arg: &Expr) {
let ty = cx.tcx.expr_ty(arg);
if let ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) = ty.sty {
if let ty::TyRef(..) = inner.sty {
let mut db = span_lint(cx, CLONE_DOUBLE_REF, expr.span,
let mut db = span_lint(cx,
CLONE_DOUBLE_REF,
expr.span,
"using `clone` on a double-reference; \
this will copy the reference instead of cloning \
the inner type");
@ -583,10 +585,7 @@ fn lint_extend(cx: &LateContext, expr: &Expr, args: &MethodArgs) {
}
let arg_ty = cx.tcx.expr_ty(&args[1]);
if let Some((span, r)) = derefs_to_slice(cx, &args[1], &arg_ty) {
span_lint(cx,
EXTEND_FROM_SLICE,
expr.span,
"use of `extend` to extend a Vec by a slice")
span_lint(cx, EXTEND_FROM_SLICE, expr.span, "use of `extend` to extend a Vec by a slice")
.span_suggestion(expr.span,
"try this",
format!("{}.extend_from_slice({}{})",

View File

@ -60,9 +60,8 @@ fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
// `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)`
else if args.len() == 2 && match_path(path, &FMT_ARGUMENTV1_NEW_PATH) {
if let ExprPath(None, ref path) = args[1].node {
if match_path(path, &DEBUG_FMT_METHOD_PATH) &&
!is_in_debug_impl(cx, expr) &&
is_expn_of(cx, expr.span, "panic").is_none() {
if match_path(path, &DEBUG_FMT_METHOD_PATH) && !is_in_debug_impl(cx, expr) &&
is_expn_of(cx, expr.span, "panic").is_none() {
span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting");
}
}
@ -75,8 +74,10 @@ fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool {
let map = &cx.tcx.map;
if let Some(NodeImplItem(item)) = map.find(map.get_parent(expr.id)) { // `fmt` method
if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) { // `Debug` impl
// `fmt` method
if let Some(NodeImplItem(item)) = map.find(map.get_parent(expr.id)) {
// `Debug` impl
if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) {
if let ItemImpl(_, _, _, Some(ref tr), _, _) = item.node {
return match_path(&tr.path, &["Debug"]);
}

View File

@ -147,7 +147,11 @@ fn str_span(base: Span, s: &str, c: usize) -> Span {
Some((b, _)) => base.lo + BytePos(b as u32),
_ => base.hi,
};
Span{ lo: lo, hi: lo, ..base }
Span {
lo: lo,
hi: lo,
..base
}
}
fn const_str(cx: &LateContext, e: &Expr) -> Option<InternedString> {

View File

@ -144,7 +144,7 @@ fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
let msg = format!("calling `as_bytes()` on a string literal. \
Consider using a byte string literal instead: \
`b{}`",
snippet(cx, args[0].span, r#""foo""#));
snippet(cx, args[0].span, r#""foo""#));
span_lint(cx, STRING_LIT_AS_BYTES, e.span, &msg);
}
}

View File

@ -390,7 +390,8 @@ fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
check_truncation_and_wrapping(cx, expr, cast_from, cast_to);
}
(false, false) => {
if let (&ty::TyFloat(FloatTy::F64), &ty::TyFloat(FloatTy::F32)) = (&cast_from.sty, &cast_to.sty) {
if let (&ty::TyFloat(FloatTy::F64), &ty::TyFloat(FloatTy::F32)) = (&cast_from.sty,
&cast_to.sty) {
span_lint(cx,
CAST_POSSIBLE_TRUNCATION,
expr.span,
@ -570,7 +571,7 @@ fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
truncates them";
let help = format!("Consider using a byte literal \
instead:\nb{}",
snippet(cx, e.span, "'x'"));
snippet(cx, e.span, "'x'"));
span_help_and_lint(cx, CHAR_LIT_AS_U8, expr.span, msg, &help);
}
}
@ -623,7 +624,10 @@ fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs
type Extr<'a> = ExtremeExpr<'a>;
// Put the expression in the form lhs < rhs or lhs <= rhs.
enum Rel { Lt, Le };
enum Rel {
Lt,
Le,
};
let (rel, lhs2, rhs2) = match op {
BiLt => (Rel::Lt, lhs, rhs),
BiLe => (Rel::Le, lhs, rhs),

View File

@ -38,10 +38,8 @@ pub fn eq_stmt(&self, left: &Stmt, right: &Stmt) -> bool {
(&StmtDecl(ref l, _), &StmtDecl(ref r, _)) => {
if let (&DeclLocal(ref l), &DeclLocal(ref r)) = (&l.node, &r.node) {
// TODO: tys
l.ty.is_none() && r.ty.is_none() &&
both(&l.init, &r.init, |l, r| self.eq_expr(l, r))
}
else {
l.ty.is_none() && r.ty.is_none() && both(&l.init, &r.init, |l, r| self.eq_expr(l, r))
} else {
false
}
}
@ -71,15 +69,9 @@ pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool {
}
match (&left.node, &right.node) {
(&ExprAddrOf(lmut, ref le), &ExprAddrOf(rmut, ref re)) => {
lmut == rmut && self.eq_expr(le, re)
}
(&ExprAgain(li), &ExprAgain(ri)) => {
both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str())
}
(&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => {
self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
}
(&ExprAddrOf(lmut, ref le), &ExprAddrOf(rmut, ref re)) => lmut == rmut && self.eq_expr(le, re),
(&ExprAgain(li), &ExprAgain(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()),
(&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr),
(&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => {
lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
}
@ -87,79 +79,50 @@ pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool {
(&ExprBinary(lop, ref ll, ref lr), &ExprBinary(rop, ref rl, ref rr)) => {
lop.node == rop.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
}
(&ExprBreak(li), &ExprBreak(ri)) => {
both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str())
}
(&ExprBox(ref l), &ExprBox(ref r)) => {
self.eq_expr(l, r)
}
(&ExprBreak(li), &ExprBreak(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()),
(&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r),
(&ExprCall(ref lfun, ref largs), &ExprCall(ref rfun, ref rargs)) => {
!self.ignore_fn &&
self.eq_expr(lfun, rfun) &&
self.eq_exprs(largs, rargs)
}
(&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => {
self.eq_expr(lx, rx) && self.eq_ty(lt, rt)
!self.ignore_fn && self.eq_expr(lfun, rfun) && self.eq_exprs(largs, rargs)
}
(&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => self.eq_expr(lx, rx) && self.eq_ty(lt, rt),
(&ExprField(ref lfexp, ref lfident), &ExprField(ref rfexp, ref rfident)) => {
lfident.node == rfident.node && self.eq_expr(lfexp, rfexp)
}
(&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => {
self.eq_expr(la, ra) && self.eq_expr(li, ri)
}
(&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri),
(&ExprIf(ref lc, ref lt, ref le), &ExprIf(ref rc, ref rt, ref re)) => {
self.eq_expr(lc, rc) &&
self.eq_block(lt, rt) &&
both(le, re, |l, r| self.eq_expr(l, r))
self.eq_expr(lc, rc) && self.eq_block(lt, rt) && both(le, re, |l, r| self.eq_expr(l, r))
}
(&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node,
(&ExprLoop(ref lb, ref ll), &ExprLoop(ref rb, ref rl)) => {
self.eq_block(lb, rb) &&
both(ll, rl, |l, r| l.name.as_str() == r.name.as_str())
self.eq_block(lb, rb) && both(ll, rl, |l, r| l.name.as_str() == r.name.as_str())
}
(&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => {
ls == rs &&
self.eq_expr(le, re) &&
over(la, ra, |l, r| {
self.eq_expr(&l.body, &r.body) &&
both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) &&
over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r))
})
ls == rs && self.eq_expr(le, re) &&
over(la, ra, |l, r| {
self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) &&
over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r))
})
}
(&ExprMethodCall(ref lname, ref ltys, ref largs), &ExprMethodCall(ref rname, ref rtys, ref rargs)) => {
(&ExprMethodCall(ref lname, ref ltys, ref largs),
&ExprMethodCall(ref rname, ref rtys, ref rargs)) => {
// TODO: tys
!self.ignore_fn &&
lname.node == rname.node &&
ltys.is_empty() &&
rtys.is_empty() &&
self.eq_exprs(largs, rargs)
!self.ignore_fn && lname.node == rname.node && ltys.is_empty() && rtys.is_empty() &&
self.eq_exprs(largs, rargs)
}
(&ExprRange(ref lb, ref le), &ExprRange(ref rb, ref re)) => {
both(lb, rb, |l, r| self.eq_expr(l, r)) &&
both(le, re, |l, r| self.eq_expr(l, r))
}
(&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => {
self.eq_expr(le, re) && self.eq_expr(ll, rl)
}
(&ExprRet(ref l), &ExprRet(ref r)) => {
both(l, r, |l, r| self.eq_expr(l, r))
both(lb, rb, |l, r| self.eq_expr(l, r)) && both(le, re, |l, r| self.eq_expr(l, r))
}
(&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => self.eq_expr(le, re) && self.eq_expr(ll, rl),
(&ExprRet(ref l), &ExprRet(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)),
(&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => {
both(lqself, rqself, |l, r| self.eq_qself(l, r)) && self.eq_path(lsubpath, rsubpath)
}
(&ExprTup(ref ltup), &ExprTup(ref rtup)) => self.eq_exprs(ltup, rtup),
(&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => {
li.node == ri.node && self.eq_expr(le, re)
}
(&ExprUnary(lop, ref le), &ExprUnary(rop, ref re)) => {
lop == rop && self.eq_expr(le, re)
}
(&ExprTupField(ref le, li), &ExprTupField(ref re, ri)) => li.node == ri.node && self.eq_expr(le, re),
(&ExprUnary(lop, ref le), &ExprUnary(rop, ref re)) => lop == rop && self.eq_expr(le, re),
(&ExprVec(ref l), &ExprVec(ref r)) => self.eq_exprs(l, r),
(&ExprWhile(ref lc, ref lb, ref ll), &ExprWhile(ref rc, ref rb, ref rl)) => {
self.eq_expr(lc, rc) &&
self.eq_block(lb, rb) &&
both(ll, rl, |l, r| l.name.as_str() == r.name.as_str())
self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.name.as_str() == r.name.as_str())
}
_ => false,
}
@ -172,39 +135,25 @@ fn eq_exprs(&self, left: &[P<Expr>], right: &[P<Expr>]) -> bool {
/// Check whether two patterns are the same.
pub fn eq_pat(&self, left: &Pat, right: &Pat) -> bool {
match (&left.node, &right.node) {
(&PatKind::Box(ref l), &PatKind::Box(ref r)) => {
self.eq_pat(l, r)
}
(&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r),
(&PatKind::TupleStruct(ref lp, ref la), &PatKind::TupleStruct(ref rp, ref ra)) => {
self.eq_path(lp, rp) &&
both(la, ra, |l, r| {
over(l, r, |l, r| self.eq_pat(l, r))
})
self.eq_path(lp, rp) && both(la, ra, |l, r| over(l, r, |l, r| self.eq_pat(l, r)))
}
(&PatKind::Ident(ref lb, ref li, ref lp), &PatKind::Ident(ref rb, ref ri, ref rp)) => {
lb == rb && li.node.name.as_str() == ri.node.name.as_str() &&
both(lp, rp, |l, r| self.eq_pat(l, r))
}
(&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => {
self.eq_expr(l, r)
lb == rb && li.node.name.as_str() == ri.node.name.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r))
}
(&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r),
(&PatKind::QPath(ref ls, ref lp), &PatKind::QPath(ref rs, ref rp)) => {
self.eq_qself(ls, rs) && self.eq_path(lp, rp)
}
(&PatKind::Tup(ref l), &PatKind::Tup(ref r)) => {
over(l, r, |l, r| self.eq_pat(l, r))
}
(&PatKind::Tup(ref l), &PatKind::Tup(ref r)) => over(l, r, |l, r| self.eq_pat(l, r)),
(&PatKind::Range(ref ls, ref le), &PatKind::Range(ref rs, ref re)) => {
self.eq_expr(ls, rs) &&
self.eq_expr(le, re)
}
(&PatKind::Ref(ref le, ref lm), &PatKind::Ref(ref re, ref rm)) => {
lm == rm && self.eq_pat(le, re)
self.eq_expr(ls, rs) && self.eq_expr(le, re)
}
(&PatKind::Ref(ref le, ref lm), &PatKind::Ref(ref re, ref rm)) => lm == rm && self.eq_pat(le, re),
(&PatKind::Vec(ref ls, ref li, ref le), &PatKind::Vec(ref rs, ref ri, ref re)) => {
over(ls, rs, |l, r| self.eq_pat(l, r)) &&
over(le, re, |l, r| self.eq_pat(l, r)) &&
both(li, ri, |l, r| self.eq_pat(l, r))
over(ls, rs, |l, r| self.eq_pat(l, r)) && over(le, re, |l, r| self.eq_pat(l, r)) &&
both(li, ri, |l, r| self.eq_pat(l, r))
}
(&PatKind::Wild, &PatKind::Wild) => true,
_ => false,

View File

@ -137,8 +137,7 @@ pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool {
iter.inspect(|_| len += 1)
.zip(path)
.all(|(nm, p)| nm.name().as_str() == *p)
&& len == path.len()
.all(|(nm, p)| nm.name().as_str() == *p) && len == path.len()
})
}
@ -600,11 +599,10 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'
/// Return the pre-expansion span if is this comes from an expansion of the macro `name`.
pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span> {
loop {
let span_name_span = cx.tcx.sess.codemap().with_expn_info(span.expn_id, |expn| {
expn.map(|ei| {
(ei.callee.name(), ei.call_site)
})
});
let span_name_span = cx.tcx
.sess
.codemap()
.with_expn_info(span.expn_id, |expn| expn.map(|ei| (ei.callee.name(), ei.call_site)));
match span_name_span {
Some((mac_name, new_span)) if mac_name.as_str() == name => return Some(new_span),