rust-lang / rust-clippy

A bunch of lints to catch common mistakes and improve your Rust code. Book: https://doc.rust-lang.org/clippy/
https://rust-lang.github.io/rust-clippy/
Other
11.29k stars 1.52k forks source link

Add lints against more manual integer ops where direct methods exist #12894

Open ivan-shrimp opened 3 months ago

ivan-shrimp commented 3 months ago

What it does

Checks for more manual reimplementations of various integer operations that are available as methods. (This can, and probably should, be separated into different lints.)

An existing lint of this type is manual_rem_euclid, preferring rem_euclid over ((a % b) + b) % b.

(We can also add midpoint as replacement for the overflow-incorrect (a + b) / 2, once that's stabilized.)

Advantage

Drawbacks

Example

let [a, b, c]: [u32; 3] = bar();
let div = (a + (b - 1)) / b;
if a > 0 { foo(a - 1) }
if b >= c { foo(b - c) }
if a != 0 { foo(b / a) }
if a != 0 { foo(a.ilog2()) }

let single_bit_v1: bool = a.count_ones() == 1;
let single_bit_v2: bool = a & (a - 1) == 0;
let log = 31 - a.leading_zeros();
let logs = (a.ilog(2), a.ilog(10));
let count = (!a).count_ones();
let rot = (a << 2) | (a >> 30);

Could be written as:

let [a, b, c]: [u32; 3] = bar();
let div = a.div_ceil(b);
if let Some(quo) = b.checked_div(a) { foo(quo) }
if let Some(decr) = a.checked_sub(1) { foo(decr) }
if let Some(diff) = b.checked_sub(c) { foo(diff) }
if let Some(log) = a.checked_ilog2() { foo(log) }

let single_bit_v1 = a.is_power_of_two();
let single_bit_v2 = a.is_power_of_two();
let log = a.ilog2();
let logs = (a.ilog2(), a.ilog10());
let count = a.count_zeros();
let rot = a.rotate_left(2);
belyakov-am commented 3 months ago

I'm going to start slowly working on this one, probably creating a separate PR for each new lint

@rustbot claim

samueltardieu commented 2 weeks ago

Someone should reopen it, it looks like the "partially fixes #xxx" has (rightly) be understood by GitHub as "fixes #xxx".