From 4dcbad1b086368beb97dc9d20b154a634c5c84af Mon Sep 17 00:00:00 2001 From: llogiq Date: Fri, 21 Aug 2015 12:19:07 +0200 Subject: [PATCH] const folding for eq_op --- src/eq_op.rs | 128 +++++++++++++++++++++++++------------------------ src/strings.rs | 13 ++--- 2 files changed, 73 insertions(+), 68 deletions(-) diff --git a/src/eq_op.rs b/src/eq_op.rs index 50b61e23356..6202dcc3670 100644 --- a/src/eq_op.rs +++ b/src/eq_op.rs @@ -4,6 +4,7 @@ use syntax::ast_util as ast_util; use syntax::ptr::P; use syntax::codemap as code; +use consts::constant; use utils::span_lint; declare_lint! { @@ -22,7 +23,7 @@ impl LintPass for EqOp { fn check_expr(&mut self, cx: &Context, e: &Expr) { if let ExprBinary(ref op, ref left, ref right) = e.node { - if is_cmp_or_bit(op) && is_exp_equal(left, right) { + if is_cmp_or_bit(op) && is_exp_equal(cx, left, right) { span_lint(cx, EQ_OP, e.span, &format!( "equal expressions as operands to {}", ast_util::binop_to_string(op.node))); @@ -31,45 +32,48 @@ impl LintPass for EqOp { } } -pub fn is_exp_equal(left : &Expr, right : &Expr) -> bool { +pub fn is_exp_equal(cx: &Context, left : &Expr, right : &Expr) -> bool { match (&left.node, &right.node) { (&ExprBinary(ref lop, ref ll, ref lr), &ExprBinary(ref rop, ref rl, ref rr)) => lop.node == rop.node && - is_exp_equal(ll, rl) && is_exp_equal(lr, rr), + is_exp_equal(cx, ll, rl) && is_exp_equal(cx, lr, rr), (&ExprBox(ref lpl, ref lbox), &ExprBox(ref rpl, ref rbox)) => - both(lpl, rpl, |l, r| is_exp_equal(l, r)) && - is_exp_equal(lbox, rbox), + both(lpl, rpl, |l, r| is_exp_equal(cx, l, r)) && + is_exp_equal(cx, lbox, rbox), (&ExprCall(ref lcallee, ref largs), - &ExprCall(ref rcallee, ref rargs)) => is_exp_equal(lcallee, - rcallee) && is_exps_equal(largs, rargs), + &ExprCall(ref rcallee, ref rargs)) => is_exp_equal(cx, lcallee, + rcallee) && is_exps_equal(cx, largs, rargs), (&ExprCast(ref lc, ref lty), &ExprCast(ref rc, ref rty)) => - is_ty_equal(lty, rty) && is_exp_equal(lc, rc), + is_ty_equal(cx, lty, rty) && is_exp_equal(cx, lc, rc), (&ExprField(ref lfexp, ref lfident), &ExprField(ref rfexp, ref rfident)) => - lfident.node == rfident.node && is_exp_equal(lfexp, rfexp), + lfident.node == rfident.node && is_exp_equal(cx, lfexp, rfexp), (&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node, (&ExprMethodCall(ref lident, ref lcty, ref lmargs), &ExprMethodCall(ref rident, ref rcty, ref rmargs)) => - lident.node == rident.node && is_tys_equal(lcty, rcty) && - is_exps_equal(lmargs, rmargs), - (&ExprParen(ref lparen), _) => is_exp_equal(lparen, right), - (_, &ExprParen(ref rparen)) => is_exp_equal(left, rparen), + lident.node == rident.node && is_tys_equal(cx, lcty, rcty) && + is_exps_equal(cx, lmargs, rmargs), + (&ExprParen(ref lparen), _) => is_exp_equal(cx, lparen, right), + (_, &ExprParen(ref rparen)) => is_exp_equal(cx, left, rparen), (&ExprPath(ref lqself, ref lsubpath), &ExprPath(ref rqself, ref rsubpath)) => both(lqself, rqself, |l, r| is_qself_equal(l, r)) && is_path_equal(lsubpath, rsubpath), (&ExprTup(ref ltup), &ExprTup(ref rtup)) => - is_exps_equal(ltup, rtup), + is_exps_equal(cx, ltup, rtup), (&ExprUnary(lunop, ref l), &ExprUnary(runop, ref r)) => - lunop == runop && is_exp_equal(l, r), - (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(l, r), + lunop == runop && is_exp_equal(cx, l, r), + (&ExprVec(ref l), &ExprVec(ref r)) => is_exps_equal(cx, l, r), + _ => false + } || match (constant(cx, left), constant(cx, right)) { + (Some(l), Some(r)) => l == r, _ => false } } -fn is_exps_equal(left : &[P], right : &[P]) -> bool { - over(left, right, |l, r| is_exp_equal(l, r)) +fn is_exps_equal(cx: &Context, left : &[P], right : &[P]) -> bool { + over(left, right, |l, r| is_exp_equal(cx, l, r)) } fn is_path_equal(left : &Path, right : &Path) -> bool { @@ -85,29 +89,29 @@ fn is_qself_equal(left : &QSelf, right : &QSelf) -> bool { left.ty.node == right.ty.node && left.position == right.position } -fn is_ty_equal(left : &Ty, right : &Ty) -> bool { +fn is_ty_equal(cx: &Context, left : &Ty, right : &Ty) -> bool { match (&left.node, &right.node) { - (&TyVec(ref lvec), &TyVec(ref rvec)) => is_ty_equal(lvec, rvec), + (&TyVec(ref lvec), &TyVec(ref rvec)) => is_ty_equal(cx, lvec, rvec), (&TyFixedLengthVec(ref lfvty, ref lfvexp), &TyFixedLengthVec(ref rfvty, ref rfvexp)) => - is_ty_equal(lfvty, rfvty) && is_exp_equal(lfvexp, rfvexp), - (&TyPtr(ref lmut), &TyPtr(ref rmut)) => is_mut_ty_equal(lmut, rmut), + is_ty_equal(cx, lfvty, rfvty) && is_exp_equal(cx, lfvexp, rfvexp), + (&TyPtr(ref lmut), &TyPtr(ref rmut)) => is_mut_ty_equal(cx, lmut, rmut), (&TyRptr(ref ltime, ref lrmut), &TyRptr(ref rtime, ref rrmut)) => both(ltime, rtime, is_lifetime_equal) && - is_mut_ty_equal(lrmut, rrmut), + is_mut_ty_equal(cx, lrmut, rrmut), (&TyBareFn(ref lbare), &TyBareFn(ref rbare)) => - is_bare_fn_ty_equal(lbare, rbare), - (&TyTup(ref ltup), &TyTup(ref rtup)) => is_tys_equal(ltup, rtup), + is_bare_fn_ty_equal(cx, lbare, rbare), + (&TyTup(ref ltup), &TyTup(ref rtup)) => is_tys_equal(cx, ltup, rtup), (&TyPath(ref lq, ref lpath), &TyPath(ref rq, ref rpath)) => both(lq, rq, is_qself_equal) && is_path_equal(lpath, rpath), (&TyObjectSum(ref lsumty, ref lobounds), &TyObjectSum(ref rsumty, ref robounds)) => - is_ty_equal(lsumty, rsumty) && + is_ty_equal(cx, lsumty, rsumty) && is_param_bounds_equal(lobounds, robounds), (&TyPolyTraitRef(ref ltbounds), &TyPolyTraitRef(ref rtbounds)) => is_param_bounds_equal(ltbounds, rtbounds), - (&TyParen(ref lty), &TyParen(ref rty)) => is_ty_equal(lty, rty), - (&TyTypeof(ref lof), &TyTypeof(ref rof)) => is_exp_equal(lof, rof), + (&TyParen(ref lty), &TyParen(ref rty)) => is_ty_equal(cx, lty, rty), + (&TyTypeof(ref lof), &TyTypeof(ref rof)) => is_exp_equal(cx, lof, rof), (&TyInfer, &TyInfer) => true, _ => false } @@ -136,41 +140,41 @@ fn is_param_bounds_equal(left : &TyParamBounds, right : &TyParamBounds) over(left, right, is_param_bound_equal) } -fn is_mut_ty_equal(left : &MutTy, right : &MutTy) -> bool { - left.mutbl == right.mutbl && is_ty_equal(&left.ty, &right.ty) +fn is_mut_ty_equal(cx: &Context, left : &MutTy, right : &MutTy) -> bool { + left.mutbl == right.mutbl && is_ty_equal(cx, &left.ty, &right.ty) } -fn is_bare_fn_ty_equal(left : &BareFnTy, right : &BareFnTy) -> bool { +fn is_bare_fn_ty_equal(cx: &Context, left : &BareFnTy, right : &BareFnTy) -> bool { left.unsafety == right.unsafety && left.abi == right.abi && is_lifetimedefs_equal(&left.lifetimes, &right.lifetimes) && - is_fndecl_equal(&left.decl, &right.decl) + is_fndecl_equal(cx, &left.decl, &right.decl) } -fn is_fndecl_equal(left : &P, right : &P) -> bool { +fn is_fndecl_equal(cx: &Context, left : &P, right : &P) -> bool { left.variadic == right.variadic && - is_args_equal(&left.inputs, &right.inputs) && - is_fnret_ty_equal(&left.output, &right.output) + is_args_equal(cx, &left.inputs, &right.inputs) && + is_fnret_ty_equal(cx, &left.output, &right.output) } -fn is_fnret_ty_equal(left : &FunctionRetTy, right : &FunctionRetTy) - -> bool { +fn is_fnret_ty_equal(cx: &Context, left : &FunctionRetTy, + right : &FunctionRetTy) -> bool { match (left, right) { (&NoReturn(_), &NoReturn(_)) | (&DefaultReturn(_), &DefaultReturn(_)) => true, - (&Return(ref lty), &Return(ref rty)) => is_ty_equal(lty, rty), + (&Return(ref lty), &Return(ref rty)) => is_ty_equal(cx, lty, rty), _ => false } } -fn is_arg_equal(l: &Arg, r : &Arg) -> bool { - is_ty_equal(&l.ty, &r.ty) && is_pat_equal(&l.pat, &r.pat) +fn is_arg_equal(cx: &Context, l: &Arg, r : &Arg) -> bool { + is_ty_equal(cx, &l.ty, &r.ty) && is_pat_equal(cx, &l.pat, &r.pat) } -fn is_args_equal(left : &[Arg], right : &[Arg]) -> bool { - over(left, right, is_arg_equal) +fn is_args_equal(cx: &Context, left : &[Arg], right : &[Arg]) -> bool { + over(left, right, |l, r| is_arg_equal(cx, l, r)) } -fn is_pat_equal(left : &Pat, right : &Pat) -> bool { +fn is_pat_equal(cx: &Context, left : &Pat, right : &Pat) -> bool { match(&left.node, &right.node) { (&PatWild(lwild), &PatWild(rwild)) => lwild == rwild, (&PatIdent(ref lmode, ref lident, Option::None), @@ -179,51 +183,51 @@ fn is_pat_equal(left : &Pat, right : &Pat) -> bool { (&PatIdent(ref lmode, ref lident, Option::Some(ref lpat)), &PatIdent(ref rmode, ref rident, Option::Some(ref rpat))) => lmode == rmode && is_ident_equal(&lident.node, &rident.node) && - is_pat_equal(lpat, rpat), + is_pat_equal(cx, lpat, rpat), (&PatEnum(ref lpath, ref lenum), &PatEnum(ref rpath, ref renum)) => is_path_equal(lpath, rpath) && both(lenum, renum, |l, r| - is_pats_equal(l, r)), + is_pats_equal(cx, l, r)), (&PatStruct(ref lpath, ref lfieldpat, lbool), &PatStruct(ref rpath, ref rfieldpat, rbool)) => lbool == rbool && is_path_equal(lpath, rpath) && - is_spanned_fieldpats_equal(lfieldpat, rfieldpat), - (&PatTup(ref ltup), &PatTup(ref rtup)) => is_pats_equal(ltup, rtup), + is_spanned_fieldpats_equal(cx, lfieldpat, rfieldpat), + (&PatTup(ref ltup), &PatTup(ref rtup)) => is_pats_equal(cx, ltup, rtup), (&PatBox(ref lboxed), &PatBox(ref rboxed)) => - is_pat_equal(lboxed, rboxed), + is_pat_equal(cx, lboxed, rboxed), (&PatRegion(ref lpat, ref lmut), &PatRegion(ref rpat, ref rmut)) => - is_pat_equal(lpat, rpat) && lmut == rmut, - (&PatLit(ref llit), &PatLit(ref rlit)) => is_exp_equal(llit, rlit), + is_pat_equal(cx, lpat, rpat) && lmut == rmut, + (&PatLit(ref llit), &PatLit(ref rlit)) => is_exp_equal(cx, llit, rlit), (&PatRange(ref lfrom, ref lto), &PatRange(ref rfrom, ref rto)) => - is_exp_equal(lfrom, rfrom) && is_exp_equal(lto, rto), + is_exp_equal(cx, lfrom, rfrom) && is_exp_equal(cx, lto, rto), (&PatVec(ref lfirst, Option::None, ref llast), &PatVec(ref rfirst, Option::None, ref rlast)) => - is_pats_equal(lfirst, rfirst) && is_pats_equal(llast, rlast), + is_pats_equal(cx, lfirst, rfirst) && is_pats_equal(cx, llast, rlast), (&PatVec(ref lfirst, Option::Some(ref lpat), ref llast), &PatVec(ref rfirst, Option::Some(ref rpat), ref rlast)) => - is_pats_equal(lfirst, rfirst) && is_pat_equal(lpat, rpat) && - is_pats_equal(llast, rlast), + is_pats_equal(cx, lfirst, rfirst) && is_pat_equal(cx, lpat, rpat) && + is_pats_equal(cx, llast, rlast), // I don't match macros for now, the code is slow enough as is ;-) _ => false } } -fn is_spanned_fieldpats_equal(left : &[code::Spanned], +fn is_spanned_fieldpats_equal(cx: &Context, left : &[code::Spanned], right : &[code::Spanned]) -> bool { - over(left, right, |l, r| is_fieldpat_equal(&l.node, &r.node)) + over(left, right, |l, r| is_fieldpat_equal(cx, &l.node, &r.node)) } -fn is_fieldpat_equal(left : &FieldPat, right : &FieldPat) -> bool { +fn is_fieldpat_equal(cx: &Context, left : &FieldPat, right : &FieldPat) -> bool { left.is_shorthand == right.is_shorthand && is_ident_equal(&left.ident, &right.ident) && - is_pat_equal(&left.pat, &right.pat) + is_pat_equal(cx, &left.pat, &right.pat) } fn is_ident_equal(left : &Ident, right : &Ident) -> bool { &left.name == &right.name && left.ctxt == right.ctxt } -fn is_pats_equal(left : &[P], right : &[P]) -> bool { - over(left, right, |l, r| is_pat_equal(l, r)) +fn is_pats_equal(cx: &Context, left : &[P], right : &[P]) -> bool { + over(left, right, |l, r| is_pat_equal(cx, l, r)) } fn is_lifetimedef_equal(left : &LifetimeDef, right : &LifetimeDef) @@ -241,8 +245,8 @@ fn is_lifetime_equal(left : &Lifetime, right : &Lifetime) -> bool { left.name == right.name } -fn is_tys_equal(left : &[P], right : &[P]) -> bool { - over(left, right, |l, r| is_ty_equal(l, r)) +fn is_tys_equal(cx: &Context, left : &[P], right : &[P]) -> bool { + over(left, right, |l, r| is_ty_equal(cx, l, r)) } fn over(left: &[X], right: &[X], mut eq_fn: F) -> bool diff --git a/src/strings.rs b/src/strings.rs index 7981b785850..b1da93d71e3 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -41,7 +41,7 @@ impl LintPass for StringAdd { if let Some(ref p) = parent { if let &ExprAssign(ref target, _) = &p.node { // avoid duplicate matches - if is_exp_equal(target, left) { return; } + if is_exp_equal(cx, target, left) { return; } } } } @@ -51,7 +51,7 @@ impl LintPass for StringAdd { Consider using `String::push_str()` instead") } } else if let &ExprAssign(ref target, ref src) = &e.node { - if is_string(cx, target) && is_add(src, target) { + if is_string(cx, target) && is_add(cx, src, target) { span_lint(cx, STRING_ADD_ASSIGN, e.span, "you assigned the result of adding something to this string. \ Consider using `String::push_str()` instead") @@ -67,13 +67,14 @@ fn is_string(cx: &Context, e: &Expr) -> bool { } else { false } } -fn is_add(src: &Expr, target: &Expr) -> bool { +fn is_add(cx: &Context, src: &Expr, target: &Expr) -> bool { match &src.node { &ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) => - is_exp_equal(target, left), + is_exp_equal(cx, target, left), &ExprBlock(ref block) => block.stmts.is_empty() && - block.expr.as_ref().map_or(false, |expr| is_add(&*expr, target)), - &ExprParen(ref expr) => is_add(&*expr, target), + block.expr.as_ref().map_or(false, + |expr| is_add(cx, &*expr, target)), + &ExprParen(ref expr) => is_add(cx, &*expr, target), _ => false } }