Description
What it does
Checks for manual implementations that returns x with only the least significant bit set, and suggests using x.isolate_lowest_one() instead.
Common manual implementation patterns for this calculation include x & -x or x & x.wrapping_neg(). The - operator is available for signed integer types. The wrapping_neg method is available for both signed and unsigned integer types.
The isolate_lowest_one method will be stabilized in Rust 1.97.0 and will be available for all signed and unsigned primitive integer types and NonZero<T> where T is any signed and unsigned primitive integer type.
Advantage
- Improve readability and clarity compared to manual implementations.
- Eliminate the overflow when
xis the smallest value that can be represented by a signed integer type (e.g.,i32::MIN) and the-operator is used. - Preserve non-zero type information by returning
NonZero<u32>instead ofu32forNonZero<T>.
x & -x is a well-known trick for finding the least significant bit, but it is opaque to those who don't know this trick.
Drawbacks
Requires MSRV 1.97.0.
Example
let x: u32 = 5;
let lsb = x & x.wrapping_neg();
let x = NonZeroU32::new(5).unwrap();
let lsb = NonZeroU32::new(x.get() & x.get().wrapping_neg()).unwrap();
Could be written as:
let x: u32 = 5;
let lsb = x.isolate_lowest_one();
let x = NonZeroU32::new(5).unwrap();
let lsb = x.isolate_lowest_one();
Comparison with existing lints
No response
Additional Context
No response