Skip to content

Commit f9687e0

Browse files
Add lint for use of ^ operator as exponentiation.
1 parent be5d17f commit f9687e0

File tree

7 files changed

+88
-2
lines changed

7 files changed

+88
-2
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,7 @@ All notable changes to this project will be documented in this file.
11571157
[`wrong_pub_self_convention`]: https://rust-lang.github.io/rust-clippy/master/index.html#wrong_pub_self_convention
11581158
[`wrong_self_convention`]: https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention
11591159
[`wrong_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#wrong_transmute
1160+
[`xor_used_as_pow`]: https://rust-lang.github.io/rust-clippy/master/index.html#xor_used_as_pow
11601161
[`zero_divided_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_divided_by_zero
11611162
[`zero_prefixed_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_prefixed_literal
11621163
[`zero_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_ptr

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
99

10-
[There are 305 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
10+
[There are 306 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
1111

1212
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
1313

clippy_lints/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ pub mod use_self;
273273
pub mod vec;
274274
pub mod wildcard_dependencies;
275275
pub mod write;
276+
pub mod xor_used_as_pow;
276277
pub mod zero_div_zero;
277278
// end lints modules, do not remove this comment, it’s used in `update_lints`
278279

@@ -582,6 +583,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
582583
reg.register_late_lint_pass(box path_buf_push_overwrite::PathBufPushOverwrite);
583584
reg.register_late_lint_pass(box checked_conversions::CheckedConversions);
584585
reg.register_late_lint_pass(box integer_division::IntegerDivision);
586+
reg.register_early_lint_pass(box xor_used_as_pow::XorUsedAsPow);
585587

586588
reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![
587589
arithmetic::FLOAT_ARITHMETIC,
@@ -889,6 +891,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
889891
write::WRITELN_EMPTY_STRING,
890892
write::WRITE_LITERAL,
891893
write::WRITE_WITH_NEWLINE,
894+
xor_used_as_pow::XOR_USED_AS_POW,
892895
zero_div_zero::ZERO_DIVIDED_BY_ZERO,
893896
]);
894897

@@ -1105,6 +1108,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
11051108
types::UNIT_CMP,
11061109
unicode::ZERO_WIDTH_SPACE,
11071110
unused_io_amount::UNUSED_IO_AMOUNT,
1111+
xor_used_as_pow::XOR_USED_AS_POW,
11081112
]);
11091113

11101114
reg.register_lint_group("clippy::perf", Some("clippy_perf"), vec![

clippy_lints/src/xor_used_as_pow.rs

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use crate::utils::span_lint_and_sugg;
2+
use if_chain::if_chain;
3+
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
4+
use rustc::{declare_lint_pass, declare_tool_lint};
5+
use rustc_errors::Applicability;
6+
use syntax::ast::{BinOpKind, Expr, ExprKind, LitKind};
7+
8+
declare_clippy_lint! {
9+
/// **What it does:** Checks for use of `^` operator when exponentiation was intended.
10+
///
11+
/// **Why is this bad?** This is most probably a typo.
12+
///
13+
/// **Known problems:** None.
14+
///
15+
/// **Example:**
16+
///
17+
/// ```rust,ignore
18+
/// // Bad
19+
/// 2 ^ 16;
20+
///
21+
/// // Good
22+
/// 1 << 16;
23+
/// 2i32.pow(16);
24+
/// ```
25+
pub XOR_USED_AS_POW,
26+
correctness,
27+
"use of `^` operator when exponentiation was intended"
28+
}
29+
30+
declare_lint_pass!(XorUsedAsPow => [XOR_USED_AS_POW]);
31+
32+
impl EarlyLintPass for XorUsedAsPow {
33+
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
34+
if_chain! {
35+
if let ExprKind::Binary(op, left, right) = &expr.node;
36+
if BinOpKind::BitXor == op.node;
37+
if let ExprKind::Lit(lit) = &left.node;
38+
if let LitKind::Int(2, _) = lit.node;
39+
if let ExprKind::Lit(lit) = &right.node;
40+
if let LitKind::Int(right, _) = lit.node;
41+
then {
42+
span_lint_and_sugg(
43+
cx,
44+
XOR_USED_AS_POW,
45+
expr.span,
46+
"`^` is not an exponentiation operator but was used as one",
47+
"did you mean to write",
48+
format!("1 << {}", right),
49+
Applicability::MaybeIncorrect,
50+
)
51+
}
52+
}
53+
}
54+
}

src/lintlist/mod.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub use lint::Lint;
66
pub use lint::LINT_LEVELS;
77

88
// begin lint list, do not remove this comment, it’s used in `update_lints`
9-
pub const ALL_LINTS: [Lint; 305] = [
9+
pub const ALL_LINTS: [Lint; 306] = [
1010
Lint {
1111
name: "absurd_extreme_comparisons",
1212
group: "correctness",
@@ -2114,6 +2114,13 @@ pub const ALL_LINTS: [Lint; 305] = [
21142114
deprecation: None,
21152115
module: "transmute",
21162116
},
2117+
Lint {
2118+
name: "xor_used_as_pow",
2119+
group: "correctness",
2120+
desc: "use of `^` operator when exponentiation was intended",
2121+
deprecation: None,
2122+
module: "xor_used_as_pow",
2123+
},
21172124
Lint {
21182125
name: "zero_divided_by_zero",
21192126
group: "complexity",

tests/ui/xor_used_as_pow.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![warn(clippy::xor_used_as_pow)]
2+
3+
fn main() {
4+
println!("{}", 2 ^ 16);
5+
// Should be allowed
6+
let x = 16;
7+
println!("{}", 2 ^ x);
8+
let y = 2;
9+
println!("{}", y ^ 16);
10+
}

tests/ui/xor_used_as_pow.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: `^` is not an exponentiation operator but was used as one
2+
--> $DIR/xor_used_as_pow.rs:4:20
3+
|
4+
LL | println!("{}", 2 ^ 16);
5+
| ^^^^^^ help: did you mean to write: `1 << 16`
6+
|
7+
= note: `-D clippy::xor-used-as-pow` implied by `-D warnings`
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)