2 use rustc_front::hir::*;
3 use syntax::codemap::Spanned;
7 declare_lint!(pub PRECEDENCE, Warn,
8 "catches operations where precedence may be unclear. See the wiki for a \
9 list of cases caught");
12 pub struct Precedence;
14 impl LintPass for Precedence {
15 fn get_lints(&self) -> LintArray {
16 lint_array!(PRECEDENCE)
19 fn check_expr(&mut self, cx: &Context, expr: &Expr) {
20 if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node {
21 if is_bit_op(op) && (is_arith_expr(left) || is_arith_expr(right)) {
22 span_lint(cx, PRECEDENCE, expr.span,
23 "operator precedence can trip the unwary. Consider adding parentheses \
24 to the subexpression");
28 if let ExprUnary(UnNeg, ref rhs) = expr.node {
29 if let ExprMethodCall(_, _, ref args) = rhs.node {
30 if let Some(slf) = args.first() {
31 if let ExprLit(ref lit) = slf.node {
33 LitInt(..) | LitFloat(..) | LitFloatUnsuffixed(..) =>
34 span_lint(cx, PRECEDENCE, expr.span,
35 "unary minus has lower precedence than method call. Consider \
36 adding parentheses to clarify your intent"),
46 fn is_arith_expr(expr : &Expr) -> bool {
48 ExprBinary(Spanned { node: op, ..}, _, _) => is_arith_op(op),
53 fn is_bit_op(op : BinOp_) -> bool {
55 BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => true,
60 fn is_arith_op(op : BinOp_) -> bool {
62 BiAdd | BiSub | BiMul | BiDiv | BiRem => true,