]>
Commit | Line | Data |
---|---|---|
17df50a5 | 1 | use clippy_utils::consts::{self, Constant}; |
a2a8927a XL |
2 | use clippy_utils::diagnostics::span_lint_and_sugg; |
3 | use clippy_utils::source::snippet_with_applicability; | |
f20569fa | 4 | use if_chain::if_chain; |
a2a8927a | 5 | use rustc_errors::Applicability; |
f20569fa XL |
6 | use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; |
7 | use rustc_lint::{LateContext, LateLintPass}; | |
8 | use rustc_session::{declare_lint_pass, declare_tool_lint}; | |
9 | use rustc_span::source_map::Span; | |
10 | ||
f20569fa | 11 | declare_clippy_lint! { |
94222f64 XL |
12 | /// ### What it does |
13 | /// Checks for multiplication by -1 as a form of negation. | |
f20569fa | 14 | /// |
94222f64 XL |
15 | /// ### Why is this bad? |
16 | /// It's more readable to just negate. | |
f20569fa | 17 | /// |
94222f64 XL |
18 | /// ### Known problems |
19 | /// This only catches integers (for now). | |
f20569fa | 20 | /// |
94222f64 | 21 | /// ### Example |
923072b8 | 22 | /// ```rust,ignore |
a2a8927a | 23 | /// let a = x * -1; |
923072b8 | 24 | /// ``` |
a2a8927a | 25 | /// |
923072b8 FG |
26 | /// Use instead: |
27 | /// ```rust,ignore | |
28 | /// let a = -x; | |
f20569fa | 29 | /// ``` |
a2a8927a | 30 | #[clippy::version = "pre 1.29.0"] |
f20569fa XL |
31 | pub NEG_MULTIPLY, |
32 | style, | |
a2a8927a | 33 | "multiplying integers by `-1`" |
f20569fa XL |
34 | } |
35 | ||
36 | declare_lint_pass!(NegMultiply => [NEG_MULTIPLY]); | |
37 | ||
f20569fa XL |
38 | impl<'tcx> LateLintPass<'tcx> for NegMultiply { |
39 | fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { | |
cdc7bbd5 | 40 | if let ExprKind::Binary(ref op, left, right) = e.kind { |
f20569fa XL |
41 | if BinOpKind::Mul == op.node { |
42 | match (&left.kind, &right.kind) { | |
43 | (&ExprKind::Unary(..), &ExprKind::Unary(..)) => {}, | |
cdc7bbd5 XL |
44 | (&ExprKind::Unary(UnOp::Neg, lit), _) => check_mul(cx, e.span, lit, right), |
45 | (_, &ExprKind::Unary(UnOp::Neg, lit)) => check_mul(cx, e.span, lit, left), | |
f20569fa XL |
46 | _ => {}, |
47 | } | |
48 | } | |
49 | } | |
50 | } | |
51 | } | |
52 | ||
53 | fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) { | |
54 | if_chain! { | |
55 | if let ExprKind::Lit(ref l) = lit.kind; | |
04454e1e | 56 | if consts::lit_to_mir_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1); |
f20569fa | 57 | if cx.typeck_results().expr_ty(exp).is_integral(); |
a2a8927a | 58 | |
f20569fa | 59 | then { |
a2a8927a XL |
60 | let mut applicability = Applicability::MachineApplicable; |
61 | let suggestion = format!("-{}", snippet_with_applicability(cx, exp.span, "..", &mut applicability)); | |
62 | span_lint_and_sugg( | |
63 | cx, | |
64 | NEG_MULTIPLY, | |
65 | span, | |
66 | "this multiplication by -1 can be written more succinctly", | |
67 | "consider using", | |
68 | suggestion, | |
69 | applicability, | |
70 | ); | |
f20569fa XL |
71 | } |
72 | } | |
73 | } |