New lint: manual_midpoint
This commit is contained in:
parent
06175f43b3
commit
baadee8fd3
15 changed files with 344 additions and 28 deletions
74
tests/ui/manual_midpoint.fixed
Normal file
74
tests/ui/manual_midpoint.fixed
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#![warn(clippy::manual_midpoint)]
|
||||
|
||||
macro_rules! mac {
|
||||
($a: expr, $b: expr) => {
|
||||
($a + $b) / 2
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! add {
|
||||
($a: expr, $b: expr) => {
|
||||
($a + $b)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! two {
|
||||
() => {
|
||||
2
|
||||
};
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.84"]
|
||||
fn older_msrv() {
|
||||
let a: u32 = 10;
|
||||
let _ = (a + 5) / 2;
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.85"]
|
||||
fn main() {
|
||||
let a: u32 = 10;
|
||||
let _ = u32::midpoint(a, 5); //~ ERROR: manual implementation of `midpoint`
|
||||
|
||||
let f: f32 = 10.0;
|
||||
let _ = f32::midpoint(f, 5.0); //~ ERROR: manual implementation of `midpoint`
|
||||
|
||||
let _: u32 = 5 + u32::midpoint(8, 8) + 2; //~ ERROR: manual implementation of `midpoint`
|
||||
let _: u32 = const { u32::midpoint(8, 8) }; //~ ERROR: manual implementation of `midpoint`
|
||||
let _: f64 = const { f64::midpoint(8.0f64, 8.) }; //~ ERROR: manual implementation of `midpoint`
|
||||
let _: u32 = u32::midpoint(u32::default(), u32::default()); //~ ERROR: manual implementation of `midpoint`
|
||||
let _: u32 = u32::midpoint(two!(), two!()); //~ ERROR: manual implementation of `midpoint`
|
||||
|
||||
// Do not lint in presence of an addition with more than 2 operands
|
||||
let _: u32 = (10 + 20 + 30) / 2;
|
||||
|
||||
// Do not lint if whole or part is coming from a macro
|
||||
let _ = mac!(10, 20);
|
||||
let _: u32 = add!(10u32, 20u32) / 2;
|
||||
let _: u32 = (10 + 20) / two!();
|
||||
|
||||
// Do not lint if a literal is not present
|
||||
let _ = (f + 5.0) / (1.0 + 1.0);
|
||||
|
||||
// Do not lint on signed integer types
|
||||
let i: i32 = 10;
|
||||
let _ = (i + 5) / 2;
|
||||
|
||||
// Do not lint on (x+1)/2 or (1+x)/2 as this looks more like a `div_ceil()` operation
|
||||
let _ = (i + 1) / 2;
|
||||
let _ = (1 + i) / 2;
|
||||
|
||||
// But if we see (x+1.0)/2.0 or (x+1.0)/2.0, it is probably a midpoint operation
|
||||
let _ = f32::midpoint(f, 1.0); //~ ERROR: manual implementation of `midpoint`
|
||||
let _ = f32::midpoint(1.0, f); //~ ERROR: manual implementation of `midpoint`
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.86"]
|
||||
fn older_signed_midpoint(i: i32) {
|
||||
// Do not lint
|
||||
let _ = (i + 10) / 2;
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.87"]
|
||||
fn signed_midpoint(i: i32) {
|
||||
let _ = i32::midpoint(i, 10); //~ ERROR: manual implementation of `midpoint`
|
||||
}
|
||||
74
tests/ui/manual_midpoint.rs
Normal file
74
tests/ui/manual_midpoint.rs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#![warn(clippy::manual_midpoint)]
|
||||
|
||||
macro_rules! mac {
|
||||
($a: expr, $b: expr) => {
|
||||
($a + $b) / 2
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! add {
|
||||
($a: expr, $b: expr) => {
|
||||
($a + $b)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! two {
|
||||
() => {
|
||||
2
|
||||
};
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.84"]
|
||||
fn older_msrv() {
|
||||
let a: u32 = 10;
|
||||
let _ = (a + 5) / 2;
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.85"]
|
||||
fn main() {
|
||||
let a: u32 = 10;
|
||||
let _ = (a + 5) / 2; //~ ERROR: manual implementation of `midpoint`
|
||||
|
||||
let f: f32 = 10.0;
|
||||
let _ = (f + 5.0) / 2.0; //~ ERROR: manual implementation of `midpoint`
|
||||
|
||||
let _: u32 = 5 + (8 + 8) / 2 + 2; //~ ERROR: manual implementation of `midpoint`
|
||||
let _: u32 = const { (8 + 8) / 2 }; //~ ERROR: manual implementation of `midpoint`
|
||||
let _: f64 = const { (8.0f64 + 8.) / 2. }; //~ ERROR: manual implementation of `midpoint`
|
||||
let _: u32 = (u32::default() + u32::default()) / 2; //~ ERROR: manual implementation of `midpoint`
|
||||
let _: u32 = (two!() + two!()) / 2; //~ ERROR: manual implementation of `midpoint`
|
||||
|
||||
// Do not lint in presence of an addition with more than 2 operands
|
||||
let _: u32 = (10 + 20 + 30) / 2;
|
||||
|
||||
// Do not lint if whole or part is coming from a macro
|
||||
let _ = mac!(10, 20);
|
||||
let _: u32 = add!(10u32, 20u32) / 2;
|
||||
let _: u32 = (10 + 20) / two!();
|
||||
|
||||
// Do not lint if a literal is not present
|
||||
let _ = (f + 5.0) / (1.0 + 1.0);
|
||||
|
||||
// Do not lint on signed integer types
|
||||
let i: i32 = 10;
|
||||
let _ = (i + 5) / 2;
|
||||
|
||||
// Do not lint on (x+1)/2 or (1+x)/2 as this looks more like a `div_ceil()` operation
|
||||
let _ = (i + 1) / 2;
|
||||
let _ = (1 + i) / 2;
|
||||
|
||||
// But if we see (x+1.0)/2.0 or (x+1.0)/2.0, it is probably a midpoint operation
|
||||
let _ = (f + 1.0) / 2.0; //~ ERROR: manual implementation of `midpoint`
|
||||
let _ = (1.0 + f) / 2.0; //~ ERROR: manual implementation of `midpoint`
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.86"]
|
||||
fn older_signed_midpoint(i: i32) {
|
||||
// Do not lint
|
||||
let _ = (i + 10) / 2;
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.87"]
|
||||
fn signed_midpoint(i: i32) {
|
||||
let _ = (i + 10) / 2; //~ ERROR: manual implementation of `midpoint`
|
||||
}
|
||||
65
tests/ui/manual_midpoint.stderr
Normal file
65
tests/ui/manual_midpoint.stderr
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
error: manual implementation of `midpoint` which can overflow
|
||||
--> tests/ui/manual_midpoint.rs:30:13
|
||||
|
|
||||
LL | let _ = (a + 5) / 2;
|
||||
| ^^^^^^^^^^^ help: use `u32::midpoint` instead: `u32::midpoint(a, 5)`
|
||||
|
|
||||
= note: `-D clippy::manual-midpoint` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::manual_midpoint)]`
|
||||
|
||||
error: manual implementation of `midpoint` which can overflow
|
||||
--> tests/ui/manual_midpoint.rs:33:13
|
||||
|
|
||||
LL | let _ = (f + 5.0) / 2.0;
|
||||
| ^^^^^^^^^^^^^^^ help: use `f32::midpoint` instead: `f32::midpoint(f, 5.0)`
|
||||
|
||||
error: manual implementation of `midpoint` which can overflow
|
||||
--> tests/ui/manual_midpoint.rs:35:22
|
||||
|
|
||||
LL | let _: u32 = 5 + (8 + 8) / 2 + 2;
|
||||
| ^^^^^^^^^^^ help: use `u32::midpoint` instead: `u32::midpoint(8, 8)`
|
||||
|
||||
error: manual implementation of `midpoint` which can overflow
|
||||
--> tests/ui/manual_midpoint.rs:36:26
|
||||
|
|
||||
LL | let _: u32 = const { (8 + 8) / 2 };
|
||||
| ^^^^^^^^^^^ help: use `u32::midpoint` instead: `u32::midpoint(8, 8)`
|
||||
|
||||
error: manual implementation of `midpoint` which can overflow
|
||||
--> tests/ui/manual_midpoint.rs:37:26
|
||||
|
|
||||
LL | let _: f64 = const { (8.0f64 + 8.) / 2. };
|
||||
| ^^^^^^^^^^^^^^^^^^ help: use `f64::midpoint` instead: `f64::midpoint(8.0f64, 8.)`
|
||||
|
||||
error: manual implementation of `midpoint` which can overflow
|
||||
--> tests/ui/manual_midpoint.rs:38:18
|
||||
|
|
||||
LL | let _: u32 = (u32::default() + u32::default()) / 2;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `u32::midpoint` instead: `u32::midpoint(u32::default(), u32::default())`
|
||||
|
||||
error: manual implementation of `midpoint` which can overflow
|
||||
--> tests/ui/manual_midpoint.rs:39:18
|
||||
|
|
||||
LL | let _: u32 = (two!() + two!()) / 2;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: use `u32::midpoint` instead: `u32::midpoint(two!(), two!())`
|
||||
|
||||
error: manual implementation of `midpoint` which can overflow
|
||||
--> tests/ui/manual_midpoint.rs:61:13
|
||||
|
|
||||
LL | let _ = (f + 1.0) / 2.0;
|
||||
| ^^^^^^^^^^^^^^^ help: use `f32::midpoint` instead: `f32::midpoint(f, 1.0)`
|
||||
|
||||
error: manual implementation of `midpoint` which can overflow
|
||||
--> tests/ui/manual_midpoint.rs:62:13
|
||||
|
|
||||
LL | let _ = (1.0 + f) / 2.0;
|
||||
| ^^^^^^^^^^^^^^^ help: use `f32::midpoint` instead: `f32::midpoint(1.0, f)`
|
||||
|
||||
error: manual implementation of `midpoint` which can overflow
|
||||
--> tests/ui/manual_midpoint.rs:73:13
|
||||
|
|
||||
LL | let _ = (i + 10) / 2;
|
||||
| ^^^^^^^^^^^^ help: use `i32::midpoint` instead: `i32::midpoint(i, 10)`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
clippy::equatable_if_let,
|
||||
clippy::let_unit_value,
|
||||
clippy::redundant_locals,
|
||||
clippy::manual_midpoint,
|
||||
clippy::manual_unwrap_or_default,
|
||||
clippy::manual_unwrap_or
|
||||
)]
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
clippy::equatable_if_let,
|
||||
clippy::let_unit_value,
|
||||
clippy::redundant_locals,
|
||||
clippy::manual_midpoint,
|
||||
clippy::manual_unwrap_or_default,
|
||||
clippy::manual_unwrap_or
|
||||
)]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:12:5
|
||||
--> tests/ui/option_if_let_else.rs:13:5
|
||||
|
|
||||
LL | / if let Some(x) = string {
|
||||
LL | |
|
||||
|
|
@ -13,19 +13,19 @@ LL | | }
|
|||
= help: to override `-D warnings` add `#[allow(clippy::option_if_let_else)]`
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:31:13
|
||||
--> tests/ui/option_if_let_else.rs:32:13
|
||||
|
|
||||
LL | let _ = if let Some(s) = *string { s.len() } else { 0 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())`
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:33:13
|
||||
--> tests/ui/option_if_let_else.rs:34:13
|
||||
|
|
||||
LL | let _ = if let Some(s) = &num { s } else { &0 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:35:13
|
||||
--> tests/ui/option_if_let_else.rs:36:13
|
||||
|
|
||||
LL | let _ = if let Some(s) = &mut num {
|
||||
| _____________^
|
||||
|
|
@ -47,13 +47,13 @@ LL ~ });
|
|||
|
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:42:13
|
||||
--> tests/ui/option_if_let_else.rs:43:13
|
||||
|
|
||||
LL | let _ = if let Some(ref s) = num { s } else { &0 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:44:13
|
||||
--> tests/ui/option_if_let_else.rs:45:13
|
||||
|
|
||||
LL | let _ = if let Some(mut s) = num {
|
||||
| _____________^
|
||||
|
|
@ -75,7 +75,7 @@ LL ~ });
|
|||
|
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:51:13
|
||||
--> tests/ui/option_if_let_else.rs:52:13
|
||||
|
|
||||
LL | let _ = if let Some(ref mut s) = num {
|
||||
| _____________^
|
||||
|
|
@ -97,7 +97,7 @@ LL ~ });
|
|||
|
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:61:5
|
||||
--> tests/ui/option_if_let_else.rs:62:5
|
||||
|
|
||||
LL | / if let Some(x) = arg {
|
||||
LL | |
|
||||
|
|
@ -118,7 +118,7 @@ LL + })
|
|||
|
|
||||
|
||||
error: use Option::map_or_else instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:75:13
|
||||
--> tests/ui/option_if_let_else.rs:76:13
|
||||
|
|
||||
LL | let _ = if let Some(x) = arg {
|
||||
| _____________^
|
||||
|
|
@ -131,7 +131,7 @@ LL | | };
|
|||
| |_____^ help: try: `arg.map_or_else(side_effect, |x| x)`
|
||||
|
||||
error: use Option::map_or_else instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:85:13
|
||||
--> tests/ui/option_if_let_else.rs:86:13
|
||||
|
|
||||
LL | let _ = if let Some(x) = arg {
|
||||
| _____________^
|
||||
|
|
@ -154,7 +154,7 @@ LL ~ }, |x| x * x * x * x);
|
|||
|
|
||||
|
||||
error: use Option::map_or_else instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:119:13
|
||||
--> tests/ui/option_if_let_else.rs:120:13
|
||||
|
|
||||
LL | / if let Some(idx) = s.find('.') {
|
||||
LL | |
|
||||
|
|
@ -165,7 +165,7 @@ LL | | }
|
|||
| |_____________^ help: try: `s.find('.').map_or_else(|| vec![s.to_string()], |idx| vec![s[..idx].to_string(), s[idx..].to_string()])`
|
||||
|
||||
error: use Option::map_or_else instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:131:5
|
||||
--> tests/ui/option_if_let_else.rs:132:5
|
||||
|
|
||||
LL | / if let Ok(binding) = variable {
|
||||
LL | |
|
||||
|
|
@ -189,13 +189,13 @@ LL + })
|
|||
|
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:156:13
|
||||
--> tests/ui/option_if_let_else.rs:157:13
|
||||
|
|
||||
LL | let _ = if let Some(x) = optional { x + 2 } else { 5 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)`
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:167:13
|
||||
--> tests/ui/option_if_let_else.rs:168:13
|
||||
|
|
||||
LL | let _ = if let Some(x) = Some(0) {
|
||||
| _____________^
|
||||
|
|
@ -217,13 +217,13 @@ LL ~ });
|
|||
|
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:196:13
|
||||
--> tests/ui/option_if_let_else.rs:197:13
|
||||
|
|
||||
LL | let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or(s.len(), |x| s.len() + x)`
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:201:13
|
||||
--> tests/ui/option_if_let_else.rs:202:13
|
||||
|
|
||||
LL | let _ = if let Some(x) = Some(0) {
|
||||
| _____________^
|
||||
|
|
@ -245,7 +245,7 @@ LL ~ });
|
|||
|
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:241:13
|
||||
--> tests/ui/option_if_let_else.rs:242:13
|
||||
|
|
||||
LL | let _ = match s {
|
||||
| _____________^
|
||||
|
|
@ -256,7 +256,7 @@ LL | | };
|
|||
| |_____^ help: try: `s.map_or(1, |string| string.len())`
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:246:13
|
||||
--> tests/ui/option_if_let_else.rs:247:13
|
||||
|
|
||||
LL | let _ = match Some(10) {
|
||||
| _____________^
|
||||
|
|
@ -267,7 +267,7 @@ LL | | };
|
|||
| |_____^ help: try: `Some(10).map_or(5, |a| a + 1)`
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:253:13
|
||||
--> tests/ui/option_if_let_else.rs:254:13
|
||||
|
|
||||
LL | let _ = match res {
|
||||
| _____________^
|
||||
|
|
@ -278,7 +278,7 @@ LL | | };
|
|||
| |_____^ help: try: `res.map_or(1, |a| a + 1)`
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:258:13
|
||||
--> tests/ui/option_if_let_else.rs:259:13
|
||||
|
|
||||
LL | let _ = match res {
|
||||
| _____________^
|
||||
|
|
@ -289,13 +289,13 @@ LL | | };
|
|||
| |_____^ help: try: `res.map_or(1, |a| a + 1)`
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:263:13
|
||||
--> tests/ui/option_if_let_else.rs:264:13
|
||||
|
|
||||
LL | let _ = if let Ok(a) = res { a + 1 } else { 5 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)`
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:281:17
|
||||
--> tests/ui/option_if_let_else.rs:282:17
|
||||
|
|
||||
LL | let _ = match initial {
|
||||
| _________________^
|
||||
|
|
@ -306,7 +306,7 @@ LL | | };
|
|||
| |_________^ help: try: `initial.as_ref().map_or(42, |value| do_something(value))`
|
||||
|
||||
error: use Option::map_or instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:289:17
|
||||
--> tests/ui/option_if_let_else.rs:290:17
|
||||
|
|
||||
LL | let _ = match initial {
|
||||
| _________________^
|
||||
|
|
@ -317,7 +317,7 @@ LL | | };
|
|||
| |_________^ help: try: `initial.as_mut().map_or(42, |value| do_something2(value))`
|
||||
|
||||
error: use Option::map_or_else instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:313:24
|
||||
--> tests/ui/option_if_let_else.rs:314:24
|
||||
|
|
||||
LL | let mut _hashmap = if let Some(hm) = &opt {
|
||||
| ________________________^
|
||||
|
|
@ -329,7 +329,7 @@ LL | | };
|
|||
| |_____^ help: try: `opt.as_ref().map_or_else(HashMap::new, |hm| hm.clone())`
|
||||
|
||||
error: use Option::map_or_else instead of an if let/else
|
||||
--> tests/ui/option_if_let_else.rs:320:19
|
||||
--> tests/ui/option_if_let_else.rs:321:19
|
||||
|
|
||||
LL | let mut _hm = if let Some(hm) = &opt { hm.clone() } else { new_map!() };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.as_ref().map_or_else(|| new_map!(), |hm| hm.clone())`
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//@compile-flags: -Zdeduplicate-diagnostics=yes
|
||||
|
||||
#![warn(clippy::suspicious_operation_groupings)]
|
||||
#![allow(dead_code, unused_parens, clippy::eq_op)]
|
||||
#![allow(dead_code, unused_parens, clippy::eq_op, clippy::manual_midpoint)]
|
||||
|
||||
struct Vec3 {
|
||||
x: f64,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//@compile-flags: -Zdeduplicate-diagnostics=yes
|
||||
|
||||
#![warn(clippy::suspicious_operation_groupings)]
|
||||
#![allow(dead_code, unused_parens, clippy::eq_op)]
|
||||
#![allow(dead_code, unused_parens, clippy::eq_op, clippy::manual_midpoint)]
|
||||
|
||||
struct Vec3 {
|
||||
x: f64,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue