]> git.proxmox.com Git - rustc.git/blame - src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs
New upstream version 1.76.0+dfsg1
[rustc.git] / src / tools / clippy / clippy_lints / src / suspicious_xor_used_as_pow.rs
CommitLineData
add651ee
FG
1use clippy_utils::diagnostics::span_lint_and_sugg;
2use clippy_utils::numeric_literal::NumericLiteral;
3use clippy_utils::source::snippet;
4use rustc_ast::LitKind;
487cf647
FG
5use rustc_errors::Applicability;
6use rustc_hir::{BinOpKind, Expr, ExprKind};
7use rustc_lint::{LateContext, LateLintPass, LintContext};
8use rustc_middle::lint::in_external_macro;
4b012472 9use rustc_session::declare_lint_pass;
487cf647
FG
10
11declare_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}
29declare_lint_pass!(ConfusingXorAndPow => [SUSPICIOUS_XOR_USED_AS_POW]);
30
31impl 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}