mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-18 19:43:43 +00:00
Move eq_op::is_exp_equal to utils
This commit is contained in:
parent
0c6e385493
commit
54b70ed8e1
71
src/eq_op.rs
71
src/eq_op.rs
@ -1,10 +1,8 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use rustc_front::util as ast_util;
|
||||
use syntax::ptr::P;
|
||||
|
||||
use consts::constant;
|
||||
use utils::span_lint;
|
||||
use utils::{is_exp_equal, span_lint};
|
||||
|
||||
/// **What it does:** This lint checks for equal operands to comparisons and bitwise binary operators (`&`, `|` and `^`). It is `Warn` by default.
|
||||
///
|
||||
@ -40,57 +38,6 @@ impl LateLintPass for EqOp {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_exp_equal(cx: &LateContext, left : &Expr, right : &Expr) -> bool {
|
||||
if let (Some(l), Some(r)) = (constant(cx, left), constant(cx, right)) {
|
||||
if l == r {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
match (&left.node, &right.node) {
|
||||
(&ExprField(ref lfexp, ref lfident),
|
||||
&ExprField(ref rfexp, ref rfident)) =>
|
||||
lfident.node == rfident.node && is_exp_equal(cx, lfexp, rfexp),
|
||||
(&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node,
|
||||
(&ExprPath(ref lqself, ref lsubpath),
|
||||
&ExprPath(ref rqself, ref rsubpath)) =>
|
||||
both(lqself, rqself, is_qself_equal) &&
|
||||
is_path_equal(lsubpath, rsubpath),
|
||||
(&ExprTup(ref ltup), &ExprTup(ref rtup)) =>
|
||||
is_exps_equal(cx, ltup, rtup),
|
||||
(&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(cx, l, r),
|
||||
(&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) =>
|
||||
is_exp_equal(cx, lx, rx) && is_cast_ty_equal(lt, rt),
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn is_exps_equal(cx: &LateContext, left : &[P<Expr>], right : &[P<Expr>]) -> bool {
|
||||
over(left, right, |l, r| is_exp_equal(cx, l, r))
|
||||
}
|
||||
|
||||
fn is_path_equal(left : &Path, right : &Path) -> bool {
|
||||
// The == of idents doesn't work with different contexts,
|
||||
// we have to be explicit about hygiene
|
||||
left.global == right.global && over(&left.segments, &right.segments,
|
||||
|l, r| l.identifier.name == r.identifier.name
|
||||
&& l.parameters == r.parameters)
|
||||
}
|
||||
|
||||
fn is_qself_equal(left : &QSelf, right : &QSelf) -> bool {
|
||||
left.ty.node == right.ty.node && left.position == right.position
|
||||
}
|
||||
|
||||
fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool
|
||||
where F: FnMut(&X, &X) -> bool {
|
||||
left.len() == right.len() && left.iter().zip(right).all(|(x, y)|
|
||||
eq_fn(x, y))
|
||||
}
|
||||
|
||||
fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn : F) -> bool
|
||||
where F: FnMut(&X, &X) -> bool {
|
||||
l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false,
|
||||
|y| eq_fn(x, y)))
|
||||
}
|
||||
|
||||
fn is_cmp_or_bit(op : &BinOp) -> bool {
|
||||
match op.node {
|
||||
@ -99,19 +46,3 @@ fn is_cmp_or_bit(op : &BinOp) -> bool {
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn is_cast_ty_equal(left: &Ty, right: &Ty) -> bool {
|
||||
match (&left.node, &right.node) {
|
||||
(&TyVec(ref lvec), &TyVec(ref rvec)) => is_cast_ty_equal(lvec, rvec),
|
||||
(&TyPtr(ref lmut), &TyPtr(ref rmut)) =>
|
||||
lmut.mutbl == rmut.mutbl &&
|
||||
is_cast_ty_equal(&*lmut.ty, &*rmut.ty),
|
||||
(&TyRptr(_, ref lrmut), &TyRptr(_, ref rrmut)) =>
|
||||
lrmut.mutbl == rrmut.mutbl &&
|
||||
is_cast_ty_equal(&*lrmut.ty, &*rrmut.ty),
|
||||
(&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) =>
|
||||
both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath),
|
||||
(&TyInfer, &TyInfer) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,7 @@ use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use syntax::codemap::Spanned;
|
||||
|
||||
use eq_op::is_exp_equal;
|
||||
use utils::{match_type, span_lint, walk_ptrs_ty, get_parent_expr};
|
||||
use utils::{is_exp_equal, match_type, span_lint, walk_ptrs_ty, get_parent_expr};
|
||||
use utils::STRING_PATH;
|
||||
|
||||
/// **What it does:** This lint matches code of the form `x = x + y` (without `let`!). It is `Allow` by default.
|
||||
|
69
src/utils.rs
69
src/utils.rs
@ -10,6 +10,7 @@ use syntax::ast::Lit_::*;
|
||||
use syntax::ast;
|
||||
use syntax::errors::DiagnosticBuilder;
|
||||
use syntax::ptr::P;
|
||||
use consts::constant;
|
||||
|
||||
use rustc::session::Session;
|
||||
use std::str::FromStr;
|
||||
@ -493,3 +494,71 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_exp_equal(cx: &LateContext, left : &Expr, right : &Expr) -> bool {
|
||||
if let (Some(l), Some(r)) = (constant(cx, left), constant(cx, right)) {
|
||||
if l == r {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
match (&left.node, &right.node) {
|
||||
(&ExprField(ref lfexp, ref lfident),
|
||||
&ExprField(ref rfexp, ref rfident)) =>
|
||||
lfident.node == rfident.node && is_exp_equal(cx, lfexp, rfexp),
|
||||
(&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node,
|
||||
(&ExprPath(ref lqself, ref lsubpath),
|
||||
&ExprPath(ref rqself, ref rsubpath)) =>
|
||||
both(lqself, rqself, is_qself_equal) &&
|
||||
is_path_equal(lsubpath, rsubpath),
|
||||
(&ExprTup(ref ltup), &ExprTup(ref rtup)) =>
|
||||
is_exps_equal(cx, ltup, rtup),
|
||||
(&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(cx, l, r),
|
||||
(&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) =>
|
||||
is_exp_equal(cx, lx, rx) && is_cast_ty_equal(lt, rt),
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn is_exps_equal(cx: &LateContext, left : &[P<Expr>], right : &[P<Expr>]) -> bool {
|
||||
over(left, right, |l, r| is_exp_equal(cx, l, r))
|
||||
}
|
||||
|
||||
fn is_path_equal(left : &Path, right : &Path) -> bool {
|
||||
// The == of idents doesn't work with different contexts,
|
||||
// we have to be explicit about hygiene
|
||||
left.global == right.global && over(&left.segments, &right.segments,
|
||||
|l, r| l.identifier.name == r.identifier.name
|
||||
&& l.parameters == r.parameters)
|
||||
}
|
||||
|
||||
fn is_qself_equal(left : &QSelf, right : &QSelf) -> bool {
|
||||
left.ty.node == right.ty.node && left.position == right.position
|
||||
}
|
||||
|
||||
fn over<X, F>(left: &[X], right: &[X], mut eq_fn: F) -> bool
|
||||
where F: FnMut(&X, &X) -> bool {
|
||||
left.len() == right.len() && left.iter().zip(right).all(|(x, y)|
|
||||
eq_fn(x, y))
|
||||
}
|
||||
|
||||
fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn : F) -> bool
|
||||
where F: FnMut(&X, &X) -> bool {
|
||||
l.as_ref().map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false,
|
||||
|y| eq_fn(x, y)))
|
||||
}
|
||||
|
||||
fn is_cast_ty_equal(left: &Ty, right: &Ty) -> bool {
|
||||
match (&left.node, &right.node) {
|
||||
(&TyVec(ref lvec), &TyVec(ref rvec)) => is_cast_ty_equal(lvec, rvec),
|
||||
(&TyPtr(ref lmut), &TyPtr(ref rmut)) =>
|
||||
lmut.mutbl == rmut.mutbl &&
|
||||
is_cast_ty_equal(&*lmut.ty, &*rmut.ty),
|
||||
(&TyRptr(_, ref lrmut), &TyRptr(_, ref rrmut)) =>
|
||||
lrmut.mutbl == rrmut.mutbl &&
|
||||
is_cast_ty_equal(&*lrmut.ty, &*rrmut.ty),
|
||||
(&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) =>
|
||||
both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath),
|
||||
(&TyInfer, &TyInfer) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user