Auto merge of #9031 - evantypanski:manual_rem_euclid, r=Jarcho

Add [`manual_rem_euclid`] lint

Closes #8883

Adds a lint for checking manual use of `rem_euclid(n)`

changelog: Add [`manual_rem_euclid`] lint
This commit is contained in:
bors 2022-06-24 17:49:53 +00:00
commit e17864e2ff
13 changed files with 325 additions and 6 deletions

View file

@ -127,3 +127,11 @@ macro_rules! ptr_as_ptr_cast {
$ptr as *const i32
};
}
#[macro_export]
macro_rules! manual_rem_euclid {
() => {
let value: i32 = 5;
let _: i32 = ((value % 4) + 4) % 4;
};
}

View file

@ -0,0 +1,55 @@
// run-rustfix
// aux-build:macro_rules.rs
#![warn(clippy::manual_rem_euclid)]
#[macro_use]
extern crate macro_rules;
macro_rules! internal_rem_euclid {
() => {
let value: i32 = 5;
let _: i32 = value.rem_euclid(4);
};
}
fn main() {
let value: i32 = 5;
let _: i32 = value.rem_euclid(4);
let _: i32 = value.rem_euclid(4);
let _: i32 = value.rem_euclid(4);
let _: i32 = value.rem_euclid(4);
let _: i32 = 1 + value.rem_euclid(4);
let _: i32 = (3 + value % 4) % 4;
let _: i32 = (-4 + value % -4) % -4;
let _: i32 = ((5 % 4) + 4) % 4;
// Make sure the lint does not trigger if it would cause an error, like with an ambiguous
// integer type
let not_annotated = 24;
let _ = ((not_annotated % 4) + 4) % 4;
let inferred: _ = 24;
let _ = ((inferred % 4) + 4) % 4;
// For lint to apply the constant must always be on the RHS of the previous value for %
let _: i32 = 4 % ((value % 4) + 4);
let _: i32 = ((4 % value) + 4) % 4;
// Lint in internal macros
internal_rem_euclid!();
// Do not lint in external macros
manual_rem_euclid!();
}
// Should lint for params too
pub fn rem_euclid_4(num: i32) -> i32 {
num.rem_euclid(4)
}
// Constant version came later, should still lint
pub const fn const_rem_euclid_4(num: i32) -> i32 {
num.rem_euclid(4)
}

View file

@ -0,0 +1,55 @@
// run-rustfix
// aux-build:macro_rules.rs
#![warn(clippy::manual_rem_euclid)]
#[macro_use]
extern crate macro_rules;
macro_rules! internal_rem_euclid {
() => {
let value: i32 = 5;
let _: i32 = ((value % 4) + 4) % 4;
};
}
fn main() {
let value: i32 = 5;
let _: i32 = ((value % 4) + 4) % 4;
let _: i32 = (4 + (value % 4)) % 4;
let _: i32 = (value % 4 + 4) % 4;
let _: i32 = (4 + value % 4) % 4;
let _: i32 = 1 + (4 + value % 4) % 4;
let _: i32 = (3 + value % 4) % 4;
let _: i32 = (-4 + value % -4) % -4;
let _: i32 = ((5 % 4) + 4) % 4;
// Make sure the lint does not trigger if it would cause an error, like with an ambiguous
// integer type
let not_annotated = 24;
let _ = ((not_annotated % 4) + 4) % 4;
let inferred: _ = 24;
let _ = ((inferred % 4) + 4) % 4;
// For lint to apply the constant must always be on the RHS of the previous value for %
let _: i32 = 4 % ((value % 4) + 4);
let _: i32 = ((4 % value) + 4) % 4;
// Lint in internal macros
internal_rem_euclid!();
// Do not lint in external macros
manual_rem_euclid!();
}
// Should lint for params too
pub fn rem_euclid_4(num: i32) -> i32 {
((num % 4) + 4) % 4
}
// Constant version came later, should still lint
pub const fn const_rem_euclid_4(num: i32) -> i32 {
((num % 4) + 4) % 4
}

View file

@ -0,0 +1,57 @@
error: manual `rem_euclid` implementation
--> $DIR/manual_rem_euclid.rs:19:18
|
LL | let _: i32 = ((value % 4) + 4) % 4;
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
|
= note: `-D clippy::manual-rem-euclid` implied by `-D warnings`
error: manual `rem_euclid` implementation
--> $DIR/manual_rem_euclid.rs:20:18
|
LL | let _: i32 = (4 + (value % 4)) % 4;
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
error: manual `rem_euclid` implementation
--> $DIR/manual_rem_euclid.rs:21:18
|
LL | let _: i32 = (value % 4 + 4) % 4;
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
error: manual `rem_euclid` implementation
--> $DIR/manual_rem_euclid.rs:22:18
|
LL | let _: i32 = (4 + value % 4) % 4;
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
error: manual `rem_euclid` implementation
--> $DIR/manual_rem_euclid.rs:23:22
|
LL | let _: i32 = 1 + (4 + value % 4) % 4;
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
error: manual `rem_euclid` implementation
--> $DIR/manual_rem_euclid.rs:12:22
|
LL | let _: i32 = ((value % 4) + 4) % 4;
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
...
LL | internal_rem_euclid!();
| ---------------------- in this macro invocation
|
= note: this error originates in the macro `internal_rem_euclid` (in Nightly builds, run with -Z macro-backtrace for more info)
error: manual `rem_euclid` implementation
--> $DIR/manual_rem_euclid.rs:49:5
|
LL | ((num % 4) + 4) % 4
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `num.rem_euclid(4)`
error: manual `rem_euclid` implementation
--> $DIR/manual_rem_euclid.rs:54:5
|
LL | ((num % 4) + 4) % 4
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `num.rem_euclid(4)`
error: aborting due to 8 previous errors

View file

@ -155,6 +155,11 @@ fn cast_abs_to_unsigned() {
assert_eq!(10u32, x.abs() as u32);
}
fn manual_rem_euclid() {
let x: i32 = 10;
let _: i32 = ((x % 4) + 4) % 4;
}
fn main() {
filter_map_next();
checked_conversion();
@ -174,6 +179,7 @@ fn main() {
int_from_bool();
err_expect();
cast_abs_to_unsigned();
manual_rem_euclid();
}
mod just_under_msrv {
@ -211,3 +217,12 @@ mod just_above_msrv {
}
}
}
mod const_rem_euclid {
#![feature(custom_inner_attributes)]
#![clippy::msrv = "1.50.0"]
pub const fn const_rem_euclid_4(num: i32) -> i32 {
((num % 4) + 4) % 4
}
}

View file

@ -1,12 +1,12 @@
error: stripping a prefix manually
--> $DIR/min_rust_version_attr.rs:198:24
--> $DIR/min_rust_version_attr.rs:204:24
|
LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
| ^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::manual-strip` implied by `-D warnings`
note: the prefix was tested here
--> $DIR/min_rust_version_attr.rs:197:9
--> $DIR/min_rust_version_attr.rs:203:9
|
LL | if s.starts_with("hello, ") {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -17,13 +17,13 @@ LL ~ assert_eq!(<stripped>.to_uppercase(), "WORLD!");
|
error: stripping a prefix manually
--> $DIR/min_rust_version_attr.rs:210:24
--> $DIR/min_rust_version_attr.rs:216:24
|
LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
| ^^^^^^^^^^^^^^^^^^^^
|
note: the prefix was tested here
--> $DIR/min_rust_version_attr.rs:209:9
--> $DIR/min_rust_version_attr.rs:215:9
|
LL | if s.starts_with("hello, ") {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^