-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathneg_multiply.rs
82 lines (78 loc) · 2.69 KB
/
neg_multiply.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use clippy_utils::consts::{self, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
use clippy_utils::sugg::has_enclosing_paren;
use rustc_ast::util::parser::ExprPrecedence;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
use rustc_span::Span;
declare_clippy_lint! {
/// ### What it does
/// Checks for multiplication by -1 as a form of negation.
///
/// ### Why is this bad?
/// It's more readable to just negate.
///
/// ### Example
/// ```rust,ignore
/// let a = x * -1;
/// ```
///
/// Use instead:
/// ```rust,ignore
/// let a = -x;
/// ```
#[clippy::version = "pre 1.29.0"]
pub NEG_MULTIPLY,
style,
"multiplying integers by `-1`"
}
declare_lint_pass!(NegMultiply => [NEG_MULTIPLY]);
impl<'tcx> LateLintPass<'tcx> for NegMultiply {
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
if let ExprKind::Binary(ref op, left, right) = e.kind
&& BinOpKind::Mul == op.node
{
match (&left.kind, &right.kind) {
(&ExprKind::Unary(..), &ExprKind::Unary(..)) => {},
(&ExprKind::Unary(UnOp::Neg, lit), _) => check_mul(cx, e.span, lit, right),
(_, &ExprKind::Unary(UnOp::Neg, lit)) => check_mul(cx, e.span, lit, left),
_ => {},
}
}
}
}
fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
const F16_ONE: u16 = 1.0_f16.to_bits();
const F128_ONE: u128 = 1.0_f128.to_bits();
if let ExprKind::Lit(l) = lit.kind
&& matches!(
consts::lit_to_mir_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)),
Constant::Int(1)
| Constant::F16(F16_ONE)
| Constant::F32(1.0)
| Constant::F64(1.0)
| Constant::F128(F128_ONE)
)
&& cx.typeck_results().expr_ty(exp).is_numeric()
{
let mut applicability = Applicability::MachineApplicable;
let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability);
let suggestion = if !from_macro && exp.precedence() < ExprPrecedence::Prefix && !has_enclosing_paren(&snip) {
format!("-({snip})")
} else {
format!("-{snip}")
};
span_lint_and_sugg(
cx,
NEG_MULTIPLY,
span,
"this multiplication by -1 can be written more succinctly",
"consider using",
suggestion,
applicability,
);
}
}