]>
Commit | Line | Data |
---|---|---|
add651ee FG |
1 | use clippy_utils::diagnostics::span_lint_and_sugg; |
2 | use clippy_utils::numeric_literal::NumericLiteral; | |
3 | use clippy_utils::source::snippet; | |
4 | use rustc_ast::LitKind; | |
487cf647 FG |
5 | use rustc_errors::Applicability; |
6 | use rustc_hir::{BinOpKind, Expr, ExprKind}; | |
7 | use rustc_lint::{LateContext, LateLintPass, LintContext}; | |
8 | use rustc_middle::lint::in_external_macro; | |
4b012472 | 9 | use rustc_session::declare_lint_pass; |
487cf647 FG |
10 | |
11 | declare_clippy_lint! { | |
12 | /// ### What it does | |
13 | /// Warns for a Bitwise XOR (`^`) operator being probably confused as a powering. It will not trigger if any of the numbers are not in decimal. | |
14 | /// ### Why is this bad? | |
9ffffee4 | 15 | /// It's most probably a typo and may lead to unexpected behaviours. |
487cf647 | 16 | /// ### Example |
ed00b5ec | 17 | /// ```no_run |
487cf647 FG |
18 | /// let x = 3_i32 ^ 4_i32; |
19 | /// ``` | |
20 | /// Use instead: | |
ed00b5ec | 21 | /// ```no_run |
487cf647 FG |
22 | /// let x = 3_i32.pow(4); |
23 | /// ``` | |
9ffffee4 | 24 | #[clippy::version = "1.67.0"] |
487cf647 FG |
25 | pub SUSPICIOUS_XOR_USED_AS_POW, |
26 | restriction, | |
27 | "XOR (`^`) operator possibly used as exponentiation operator" | |
28 | } | |
29 | declare_lint_pass!(ConfusingXorAndPow => [SUSPICIOUS_XOR_USED_AS_POW]); | |
30 | ||
31 | impl LateLintPass<'_> for ConfusingXorAndPow { | |
32 | fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { | |
add651ee FG |
33 | if !in_external_macro(cx.sess(), expr.span) |
34 | && let ExprKind::Binary(op, left, right) = &expr.kind | |
35 | && op.node == BinOpKind::BitXor | |
ed00b5ec | 36 | && left.span.eq_ctxt(right.span) |
add651ee FG |
37 | && let ExprKind::Lit(lit_left) = &left.kind |
38 | && let ExprKind::Lit(lit_right) = &right.kind | |
39 | && matches!(lit_right.node, LitKind::Int(..) | LitKind::Float(..)) | |
40 | && matches!(lit_left.node, LitKind::Int(..) | LitKind::Float(..)) | |
ed00b5ec FG |
41 | && NumericLiteral::from_lit_kind(&snippet(cx, lit_right.span, ".."), &lit_right.node) |
42 | .is_some_and(|x| x.is_decimal()) | |
43 | { | |
44 | span_lint_and_sugg( | |
45 | cx, | |
46 | SUSPICIOUS_XOR_USED_AS_POW, | |
47 | expr.span, | |
48 | "`^` is not the exponentiation operator", | |
49 | "did you mean to write", | |
50 | format!("{}.pow({})", lit_left.node, lit_right.node), | |
51 | Applicability::MaybeIncorrect, | |
52 | ); | |
53 | } | |
487cf647 FG |
54 | } |
55 | } |