Merge remote-tracking branch 'upstream/master' into rustup
This commit is contained in:
commit
2c0cea7cbc
170 changed files with 5217 additions and 855 deletions
|
|
@ -17,7 +17,7 @@ fn main() {
|
|||
with_span!(
|
||||
span
|
||||
|
||||
fn coverting() {
|
||||
fn converting() {
|
||||
let x = 0u32 as u64;
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -365,3 +365,52 @@ fn avoid_subtract_overflow(q: u32) {
|
|||
fn issue11426() {
|
||||
(&42u8 >> 0xa9008fb6c9d81e42_0e25730562a601c8_u128) as usize;
|
||||
}
|
||||
|
||||
fn issue11642() {
|
||||
fn square(x: i16) -> u32 {
|
||||
let x = x as i32;
|
||||
(x * x) as u32;
|
||||
x.pow(2) as u32;
|
||||
(-2_i32).pow(2) as u32
|
||||
}
|
||||
|
||||
let _a = |x: i32| -> u32 { (x * x * x * x) as u32 };
|
||||
|
||||
(-2_i32).pow(3) as u32;
|
||||
//~^ ERROR: casting `i32` to `u32` may lose the sign of the value
|
||||
|
||||
let x: i32 = 10;
|
||||
(x * x) as u32;
|
||||
(x * x * x) as u32;
|
||||
//~^ ERROR: casting `i32` to `u32` may lose the sign of the value
|
||||
|
||||
let y: i16 = -2;
|
||||
(y * y * y * y * -2) as u16;
|
||||
//~^ ERROR: casting `i16` to `u16` may lose the sign of the value
|
||||
(y * y * y * y * 2) as u16;
|
||||
(y * y * y * 2) as u16;
|
||||
//~^ ERROR: casting `i16` to `u16` may lose the sign of the value
|
||||
(y * y * y * -2) as u16;
|
||||
//~^ ERROR: casting `i16` to `u16` may lose the sign of the value
|
||||
|
||||
fn foo(a: i32, b: i32, c: i32) -> u32 {
|
||||
(a * a * b * b * c * c) as u32;
|
||||
(a * b * c) as u32;
|
||||
//~^ ERROR: casting `i32` to `u32` may lose the sign of the value
|
||||
(a * -b * c) as u32;
|
||||
//~^ ERROR: casting `i32` to `u32` may lose the sign of the value
|
||||
(a * b * c * c) as u32;
|
||||
(a * -2) as u32;
|
||||
//~^ ERROR: casting `i32` to `u32` may lose the sign of the value
|
||||
(a * b * c * -2) as u32;
|
||||
//~^ ERROR: casting `i32` to `u32` may lose the sign of the value
|
||||
(a / b) as u32;
|
||||
(a / b * c) as u32;
|
||||
//~^ ERROR: casting `i32` to `u32` may lose the sign of the value
|
||||
(a / b + b * c) as u32;
|
||||
//~^ ERROR: casting `i32` to `u32` may lose the sign of the value
|
||||
a.pow(3) as u32;
|
||||
//~^ ERROR: casting `i32` to `u32` may lose the sign of the value
|
||||
(a.abs() * b.pow(2) / c.abs()) as u32
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -444,5 +444,77 @@ help: ... or use `try_from` and handle the error accordingly
|
|||
LL | let c = u8::try_from(q / 1000);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 51 previous errors
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> $DIR/cast.rs:379:5
|
||||
|
|
||||
LL | (-2_i32).pow(3) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> $DIR/cast.rs:384:5
|
||||
|
|
||||
LL | (x * x * x) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i16` to `u16` may lose the sign of the value
|
||||
--> $DIR/cast.rs:388:5
|
||||
|
|
||||
LL | (y * y * y * y * -2) as u16;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i16` to `u16` may lose the sign of the value
|
||||
--> $DIR/cast.rs:391:5
|
||||
|
|
||||
LL | (y * y * y * 2) as u16;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i16` to `u16` may lose the sign of the value
|
||||
--> $DIR/cast.rs:393:5
|
||||
|
|
||||
LL | (y * y * y * -2) as u16;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> $DIR/cast.rs:398:9
|
||||
|
|
||||
LL | (a * b * c) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> $DIR/cast.rs:400:9
|
||||
|
|
||||
LL | (a * -b * c) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> $DIR/cast.rs:403:9
|
||||
|
|
||||
LL | (a * -2) as u32;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> $DIR/cast.rs:405:9
|
||||
|
|
||||
LL | (a * b * c * -2) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> $DIR/cast.rs:408:9
|
||||
|
|
||||
LL | (a / b * c) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> $DIR/cast.rs:410:9
|
||||
|
|
||||
LL | (a / b + b * c) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> $DIR/cast.rs:412:9
|
||||
|
|
||||
LL | a.pow(3) as u32;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 63 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
#![warn(clippy::let_unit_value)]
|
||||
|
||||
fn f() {}
|
||||
static FN: fn() = f;
|
||||
|
||||
fn main() {
|
||||
FN();
|
||||
//~^ ERROR: this let-binding has unit value
|
||||
//~| NOTE: `-D clippy::let-unit-value` implied by `-D warnings`
|
||||
}
|
||||
|
|
@ -5,6 +5,4 @@ static FN: fn() = f;
|
|||
|
||||
fn main() {
|
||||
let _: () = FN();
|
||||
//~^ ERROR: this let-binding has unit value
|
||||
//~| NOTE: `-D clippy::let-unit-value` implied by `-D warnings`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
error: this let-binding has unit value
|
||||
--> $DIR/ice-8821.rs:7:5
|
||||
|
|
||||
LL | let _: () = FN();
|
||||
| ^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `FN();`
|
||||
|
|
||||
= note: `-D clippy::let-unit-value` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::let_unit_value)]`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -73,9 +73,7 @@ mod nested_local {
|
|||
|
||||
mod function_def {
|
||||
fn ret_f64() -> f64 {
|
||||
// Even though the output type is specified,
|
||||
// this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
|
||||
1.0_f64
|
||||
1.
|
||||
}
|
||||
|
||||
fn test() {
|
||||
|
|
|
|||
|
|
@ -73,8 +73,6 @@ mod nested_local {
|
|||
|
||||
mod function_def {
|
||||
fn ret_f64() -> f64 {
|
||||
// Even though the output type is specified,
|
||||
// this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
|
||||
1.
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,66 +86,60 @@ LL | let y = 1.;
|
|||
| ^^ help: consider adding suffix: `1.0_f64`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_f64.rs:78:9
|
||||
|
|
||||
LL | 1.
|
||||
| ^^ help: consider adding suffix: `1.0_f64`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_f64.rs:84:27
|
||||
--> $DIR/default_numeric_fallback_f64.rs:82:27
|
||||
|
|
||||
LL | let f = || -> _ { 1. };
|
||||
| ^^ help: consider adding suffix: `1.0_f64`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_f64.rs:88:29
|
||||
--> $DIR/default_numeric_fallback_f64.rs:86:29
|
||||
|
|
||||
LL | let f = || -> f64 { 1. };
|
||||
| ^^ help: consider adding suffix: `1.0_f64`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_f64.rs:102:21
|
||||
--> $DIR/default_numeric_fallback_f64.rs:100:21
|
||||
|
|
||||
LL | generic_arg(1.);
|
||||
| ^^ help: consider adding suffix: `1.0_f64`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_f64.rs:105:32
|
||||
--> $DIR/default_numeric_fallback_f64.rs:103:32
|
||||
|
|
||||
LL | let x: _ = generic_arg(1.);
|
||||
| ^^ help: consider adding suffix: `1.0_f64`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_f64.rs:123:28
|
||||
--> $DIR/default_numeric_fallback_f64.rs:121:28
|
||||
|
|
||||
LL | GenericStruct { x: 1. };
|
||||
| ^^ help: consider adding suffix: `1.0_f64`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_f64.rs:126:36
|
||||
--> $DIR/default_numeric_fallback_f64.rs:124:36
|
||||
|
|
||||
LL | let _ = GenericStruct { x: 1. };
|
||||
| ^^ help: consider adding suffix: `1.0_f64`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_f64.rs:144:24
|
||||
--> $DIR/default_numeric_fallback_f64.rs:142:24
|
||||
|
|
||||
LL | GenericEnum::X(1.);
|
||||
| ^^ help: consider adding suffix: `1.0_f64`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_f64.rs:164:23
|
||||
--> $DIR/default_numeric_fallback_f64.rs:162:23
|
||||
|
|
||||
LL | s.generic_arg(1.);
|
||||
| ^^ help: consider adding suffix: `1.0_f64`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_f64.rs:174:25
|
||||
--> $DIR/default_numeric_fallback_f64.rs:172:25
|
||||
|
|
||||
LL | inline!(let x = 22.;);
|
||||
| ^^^ help: consider adding suffix: `22.0_f64`
|
||||
|
|
||||
= note: this error originates in the macro `__inline_mac_fn_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 24 previous errors
|
||||
error: aborting due to 23 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -74,9 +74,7 @@ mod nested_local {
|
|||
|
||||
mod function_def {
|
||||
fn ret_i32() -> i32 {
|
||||
// Even though the output type is specified,
|
||||
// this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
|
||||
1_i32
|
||||
1
|
||||
}
|
||||
|
||||
fn test() {
|
||||
|
|
@ -186,4 +184,36 @@ fn check_expect_suppression() {
|
|||
let x = 21;
|
||||
}
|
||||
|
||||
mod type_already_inferred {
|
||||
// Should NOT lint if bound to return type
|
||||
fn ret_i32() -> i32 {
|
||||
1
|
||||
}
|
||||
|
||||
// Should NOT lint if bound to return type
|
||||
fn ret_if_i32(b: bool) -> i32 {
|
||||
if b { 100 } else { 0 }
|
||||
}
|
||||
|
||||
// Should NOT lint if bound to return type
|
||||
fn ret_i32_tuple() -> (i32, i32) {
|
||||
(0, 1)
|
||||
}
|
||||
|
||||
// Should NOT lint if bound to return type
|
||||
fn ret_stmt(b: bool) -> (i32, i32) {
|
||||
if b {
|
||||
return (0, 1);
|
||||
}
|
||||
(0, 0)
|
||||
}
|
||||
|
||||
#[allow(clippy::useless_vec)]
|
||||
fn vec_macro() {
|
||||
// Should NOT lint in `vec!` call if the type was already stated
|
||||
let data_i32: Vec<i32> = vec![1, 2, 3];
|
||||
let data_i32 = vec![1_i32, 2_i32, 3_i32];
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -74,8 +74,6 @@ mod nested_local {
|
|||
|
||||
mod function_def {
|
||||
fn ret_i32() -> i32 {
|
||||
// Even though the output type is specified,
|
||||
// this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
|
||||
1
|
||||
}
|
||||
|
||||
|
|
@ -186,4 +184,36 @@ fn check_expect_suppression() {
|
|||
let x = 21;
|
||||
}
|
||||
|
||||
mod type_already_inferred {
|
||||
// Should NOT lint if bound to return type
|
||||
fn ret_i32() -> i32 {
|
||||
1
|
||||
}
|
||||
|
||||
// Should NOT lint if bound to return type
|
||||
fn ret_if_i32(b: bool) -> i32 {
|
||||
if b { 100 } else { 0 }
|
||||
}
|
||||
|
||||
// Should NOT lint if bound to return type
|
||||
fn ret_i32_tuple() -> (i32, i32) {
|
||||
(0, 1)
|
||||
}
|
||||
|
||||
// Should NOT lint if bound to return type
|
||||
fn ret_stmt(b: bool) -> (i32, i32) {
|
||||
if b {
|
||||
return (0, 1);
|
||||
}
|
||||
(0, 0)
|
||||
}
|
||||
|
||||
#[allow(clippy::useless_vec)]
|
||||
fn vec_macro() {
|
||||
// Should NOT lint in `vec!` call if the type was already stated
|
||||
let data_i32: Vec<i32> = vec![1, 2, 3];
|
||||
let data_i32 = vec![1, 2, 3];
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -98,66 +98,78 @@ LL | let y = 1;
|
|||
| ^ help: consider adding suffix: `1_i32`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_i32.rs:79:9
|
||||
|
|
||||
LL | 1
|
||||
| ^ help: consider adding suffix: `1_i32`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_i32.rs:85:27
|
||||
--> $DIR/default_numeric_fallback_i32.rs:83:27
|
||||
|
|
||||
LL | let f = || -> _ { 1 };
|
||||
| ^ help: consider adding suffix: `1_i32`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_i32.rs:89:29
|
||||
--> $DIR/default_numeric_fallback_i32.rs:87:29
|
||||
|
|
||||
LL | let f = || -> i32 { 1 };
|
||||
| ^ help: consider adding suffix: `1_i32`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_i32.rs:103:21
|
||||
--> $DIR/default_numeric_fallback_i32.rs:101:21
|
||||
|
|
||||
LL | generic_arg(1);
|
||||
| ^ help: consider adding suffix: `1_i32`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_i32.rs:106:32
|
||||
--> $DIR/default_numeric_fallback_i32.rs:104:32
|
||||
|
|
||||
LL | let x: _ = generic_arg(1);
|
||||
| ^ help: consider adding suffix: `1_i32`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_i32.rs:124:28
|
||||
--> $DIR/default_numeric_fallback_i32.rs:122:28
|
||||
|
|
||||
LL | GenericStruct { x: 1 };
|
||||
| ^ help: consider adding suffix: `1_i32`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_i32.rs:127:36
|
||||
--> $DIR/default_numeric_fallback_i32.rs:125:36
|
||||
|
|
||||
LL | let _ = GenericStruct { x: 1 };
|
||||
| ^ help: consider adding suffix: `1_i32`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_i32.rs:145:24
|
||||
--> $DIR/default_numeric_fallback_i32.rs:143:24
|
||||
|
|
||||
LL | GenericEnum::X(1);
|
||||
| ^ help: consider adding suffix: `1_i32`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_i32.rs:165:23
|
||||
--> $DIR/default_numeric_fallback_i32.rs:163:23
|
||||
|
|
||||
LL | s.generic_arg(1);
|
||||
| ^ help: consider adding suffix: `1_i32`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_i32.rs:175:25
|
||||
--> $DIR/default_numeric_fallback_i32.rs:173:25
|
||||
|
|
||||
LL | inline!(let x = 22;);
|
||||
| ^^ help: consider adding suffix: `22_i32`
|
||||
|
|
||||
= note: this error originates in the macro `__inline_mac_fn_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 26 previous errors
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_i32.rs:215:29
|
||||
|
|
||||
LL | let data_i32 = vec![1, 2, 3];
|
||||
| ^ help: consider adding suffix: `1_i32`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_i32.rs:215:32
|
||||
|
|
||||
LL | let data_i32 = vec![1, 2, 3];
|
||||
| ^ help: consider adding suffix: `2_i32`
|
||||
|
||||
error: default numeric fallback might occur
|
||||
--> $DIR/default_numeric_fallback_i32.rs:215:35
|
||||
|
|
||||
LL | let data_i32 = vec![1, 2, 3];
|
||||
| ^ help: consider adding suffix: `3_i32`
|
||||
|
||||
error: aborting due to 28 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#![allow(clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, dead_code)]
|
||||
#![warn(clippy::expl_impl_clone_on_copy)]
|
||||
|
||||
|
||||
#[derive(Copy)]
|
||||
struct Qux;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: you are implementing `Clone` explicitly on a `Copy` type
|
||||
--> $DIR/derive.rs:8:1
|
||||
--> $DIR/derive.rs:7:1
|
||||
|
|
||||
LL | / impl Clone for Qux {
|
||||
LL | |
|
||||
|
|
@ -10,7 +10,7 @@ LL | | }
|
|||
| |_^
|
||||
|
|
||||
note: consider deriving `Clone` or removing `Copy`
|
||||
--> $DIR/derive.rs:8:1
|
||||
--> $DIR/derive.rs:7:1
|
||||
|
|
||||
LL | / impl Clone for Qux {
|
||||
LL | |
|
||||
|
|
@ -23,7 +23,7 @@ LL | | }
|
|||
= help: to override `-D warnings` add `#[allow(clippy::expl_impl_clone_on_copy)]`
|
||||
|
||||
error: you are implementing `Clone` explicitly on a `Copy` type
|
||||
--> $DIR/derive.rs:33:1
|
||||
--> $DIR/derive.rs:32:1
|
||||
|
|
||||
LL | / impl<'a> Clone for Lt<'a> {
|
||||
LL | |
|
||||
|
|
@ -34,7 +34,7 @@ LL | | }
|
|||
| |_^
|
||||
|
|
||||
note: consider deriving `Clone` or removing `Copy`
|
||||
--> $DIR/derive.rs:33:1
|
||||
--> $DIR/derive.rs:32:1
|
||||
|
|
||||
LL | / impl<'a> Clone for Lt<'a> {
|
||||
LL | |
|
||||
|
|
@ -45,7 +45,7 @@ LL | | }
|
|||
| |_^
|
||||
|
||||
error: you are implementing `Clone` explicitly on a `Copy` type
|
||||
--> $DIR/derive.rs:45:1
|
||||
--> $DIR/derive.rs:44:1
|
||||
|
|
||||
LL | / impl Clone for BigArray {
|
||||
LL | |
|
||||
|
|
@ -56,7 +56,7 @@ LL | | }
|
|||
| |_^
|
||||
|
|
||||
note: consider deriving `Clone` or removing `Copy`
|
||||
--> $DIR/derive.rs:45:1
|
||||
--> $DIR/derive.rs:44:1
|
||||
|
|
||||
LL | / impl Clone for BigArray {
|
||||
LL | |
|
||||
|
|
@ -67,7 +67,7 @@ LL | | }
|
|||
| |_^
|
||||
|
||||
error: you are implementing `Clone` explicitly on a `Copy` type
|
||||
--> $DIR/derive.rs:57:1
|
||||
--> $DIR/derive.rs:56:1
|
||||
|
|
||||
LL | / impl Clone for FnPtr {
|
||||
LL | |
|
||||
|
|
@ -78,7 +78,7 @@ LL | | }
|
|||
| |_^
|
||||
|
|
||||
note: consider deriving `Clone` or removing `Copy`
|
||||
--> $DIR/derive.rs:57:1
|
||||
--> $DIR/derive.rs:56:1
|
||||
|
|
||||
LL | / impl Clone for FnPtr {
|
||||
LL | |
|
||||
|
|
@ -89,7 +89,7 @@ LL | | }
|
|||
| |_^
|
||||
|
||||
error: you are implementing `Clone` explicitly on a `Copy` type
|
||||
--> $DIR/derive.rs:78:1
|
||||
--> $DIR/derive.rs:77:1
|
||||
|
|
||||
LL | / impl<T: Clone> Clone for Generic2<T> {
|
||||
LL | |
|
||||
|
|
@ -100,7 +100,7 @@ LL | | }
|
|||
| |_^
|
||||
|
|
||||
note: consider deriving `Clone` or removing `Copy`
|
||||
--> $DIR/derive.rs:78:1
|
||||
--> $DIR/derive.rs:77:1
|
||||
|
|
||||
LL | / impl<T: Clone> Clone for Generic2<T> {
|
||||
LL | |
|
||||
|
|
|
|||
|
|
@ -12,16 +12,49 @@ enum Opcode {
|
|||
Div = 3,
|
||||
}
|
||||
|
||||
struct Data {
|
||||
foo: &'static [u8],
|
||||
bar: &'static [u8],
|
||||
}
|
||||
|
||||
fn int_to_opcode(op: u8) -> Option<Opcode> {
|
||||
(op < 4).then(|| unsafe { std::mem::transmute(op) })
|
||||
}
|
||||
|
||||
fn f(op: u8, unrelated: u8) {
|
||||
fn f(op: u8, op2: Data, unrelated: u8) {
|
||||
true.then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
|
||||
(unrelated < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
|
||||
(op < 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) });
|
||||
(op > 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) });
|
||||
(op == 0).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) });
|
||||
|
||||
let _: Option<Opcode> = (op > 0 && op < 10).then(|| unsafe { std::mem::transmute(op) });
|
||||
let _: Option<Opcode> = (op > 0 && op < 10 && unrelated == 0).then(|| unsafe { std::mem::transmute(op) });
|
||||
|
||||
// lint even when the transmutable goes through field/array accesses
|
||||
let _: Option<Opcode> = (op2.foo[0] > 0 && op2.foo[0] < 10).then(|| unsafe { std::mem::transmute(op2.foo[0]) });
|
||||
|
||||
// don't lint: wrong index used in the transmute
|
||||
let _: Option<Opcode> = (op2.foo[0] > 0 && op2.foo[0] < 10).then_some(unsafe { std::mem::transmute(op2.foo[1]) });
|
||||
|
||||
// don't lint: no check for the transmutable in the condition
|
||||
let _: Option<Opcode> = (op2.foo[0] > 0 && op2.bar[1] < 10).then_some(unsafe { std::mem::transmute(op2.bar[0]) });
|
||||
|
||||
// don't lint: wrong variable
|
||||
let _: Option<Opcode> = (op2.foo[0] > 0 && op2.bar[1] < 10).then_some(unsafe { std::mem::transmute(op) });
|
||||
|
||||
// range contains checks
|
||||
let _: Option<Opcode> = (1..=3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
|
||||
let _: Option<Opcode> = ((1..=3).contains(&op) || op == 4).then(|| unsafe { std::mem::transmute(op) });
|
||||
let _: Option<Opcode> = (1..3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
|
||||
let _: Option<Opcode> = (1..).contains(&op).then(|| unsafe { std::mem::transmute(op) });
|
||||
let _: Option<Opcode> = (..3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
|
||||
let _: Option<Opcode> = (..=3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
|
||||
|
||||
// unrelated binding in contains
|
||||
let _: Option<Opcode> = (1..=3)
|
||||
.contains(&unrelated)
|
||||
.then_some(unsafe { std::mem::transmute(op) });
|
||||
}
|
||||
|
||||
unsafe fn f2(op: u8) {
|
||||
|
|
|
|||
|
|
@ -12,16 +12,49 @@ enum Opcode {
|
|||
Div = 3,
|
||||
}
|
||||
|
||||
struct Data {
|
||||
foo: &'static [u8],
|
||||
bar: &'static [u8],
|
||||
}
|
||||
|
||||
fn int_to_opcode(op: u8) -> Option<Opcode> {
|
||||
(op < 4).then_some(unsafe { std::mem::transmute(op) })
|
||||
}
|
||||
|
||||
fn f(op: u8, unrelated: u8) {
|
||||
fn f(op: u8, op2: Data, unrelated: u8) {
|
||||
true.then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
|
||||
(unrelated < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
|
||||
(op < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
|
||||
(op > 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
|
||||
(op == 0).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
|
||||
|
||||
let _: Option<Opcode> = (op > 0 && op < 10).then_some(unsafe { std::mem::transmute(op) });
|
||||
let _: Option<Opcode> = (op > 0 && op < 10 && unrelated == 0).then_some(unsafe { std::mem::transmute(op) });
|
||||
|
||||
// lint even when the transmutable goes through field/array accesses
|
||||
let _: Option<Opcode> = (op2.foo[0] > 0 && op2.foo[0] < 10).then_some(unsafe { std::mem::transmute(op2.foo[0]) });
|
||||
|
||||
// don't lint: wrong index used in the transmute
|
||||
let _: Option<Opcode> = (op2.foo[0] > 0 && op2.foo[0] < 10).then_some(unsafe { std::mem::transmute(op2.foo[1]) });
|
||||
|
||||
// don't lint: no check for the transmutable in the condition
|
||||
let _: Option<Opcode> = (op2.foo[0] > 0 && op2.bar[1] < 10).then_some(unsafe { std::mem::transmute(op2.bar[0]) });
|
||||
|
||||
// don't lint: wrong variable
|
||||
let _: Option<Opcode> = (op2.foo[0] > 0 && op2.bar[1] < 10).then_some(unsafe { std::mem::transmute(op) });
|
||||
|
||||
// range contains checks
|
||||
let _: Option<Opcode> = (1..=3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
|
||||
let _: Option<Opcode> = ((1..=3).contains(&op) || op == 4).then_some(unsafe { std::mem::transmute(op) });
|
||||
let _: Option<Opcode> = (1..3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
|
||||
let _: Option<Opcode> = (1..).contains(&op).then_some(unsafe { std::mem::transmute(op) });
|
||||
let _: Option<Opcode> = (..3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
|
||||
let _: Option<Opcode> = (..=3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
|
||||
|
||||
// unrelated binding in contains
|
||||
let _: Option<Opcode> = (1..=3)
|
||||
.contains(&unrelated)
|
||||
.then_some(unsafe { std::mem::transmute(op) });
|
||||
}
|
||||
|
||||
unsafe fn f2(op: u8) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:16:33
|
||||
--> $DIR/eager_transmute.rs:21:33
|
||||
|
|
||||
LL | (op < 4).then_some(unsafe { std::mem::transmute(op) })
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -12,7 +12,7 @@ LL | (op < 4).then(|| unsafe { std::mem::transmute(op) })
|
|||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:22:33
|
||||
--> $DIR/eager_transmute.rs:27:33
|
||||
|
|
||||
LL | (op < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -23,7 +23,7 @@ LL | (op < 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) });
|
|||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:23:33
|
||||
--> $DIR/eager_transmute.rs:28:33
|
||||
|
|
||||
LL | (op > 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -34,7 +34,7 @@ LL | (op > 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) });
|
|||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:24:34
|
||||
--> $DIR/eager_transmute.rs:29:34
|
||||
|
|
||||
LL | (op == 0).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -45,7 +45,106 @@ LL | (op == 0).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) });
|
|||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:28:24
|
||||
--> $DIR/eager_transmute.rs:31:68
|
||||
|
|
||||
LL | let _: Option<Opcode> = (op > 0 && op < 10).then_some(unsafe { std::mem::transmute(op) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider using `bool::then` to only transmute if the condition holds
|
||||
|
|
||||
LL | let _: Option<Opcode> = (op > 0 && op < 10).then(|| unsafe { std::mem::transmute(op) });
|
||||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:32:86
|
||||
|
|
||||
LL | let _: Option<Opcode> = (op > 0 && op < 10 && unrelated == 0).then_some(unsafe { std::mem::transmute(op) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider using `bool::then` to only transmute if the condition holds
|
||||
|
|
||||
LL | let _: Option<Opcode> = (op > 0 && op < 10 && unrelated == 0).then(|| unsafe { std::mem::transmute(op) });
|
||||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:35:84
|
||||
|
|
||||
LL | let _: Option<Opcode> = (op2.foo[0] > 0 && op2.foo[0] < 10).then_some(unsafe { std::mem::transmute(op2.foo[0]) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider using `bool::then` to only transmute if the condition holds
|
||||
|
|
||||
LL | let _: Option<Opcode> = (op2.foo[0] > 0 && op2.foo[0] < 10).then(|| unsafe { std::mem::transmute(op2.foo[0]) });
|
||||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:47:70
|
||||
|
|
||||
LL | let _: Option<Opcode> = (1..=3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider using `bool::then` to only transmute if the condition holds
|
||||
|
|
||||
LL | let _: Option<Opcode> = (1..=3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
|
||||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:48:83
|
||||
|
|
||||
LL | let _: Option<Opcode> = ((1..=3).contains(&op) || op == 4).then_some(unsafe { std::mem::transmute(op) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider using `bool::then` to only transmute if the condition holds
|
||||
|
|
||||
LL | let _: Option<Opcode> = ((1..=3).contains(&op) || op == 4).then(|| unsafe { std::mem::transmute(op) });
|
||||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:49:69
|
||||
|
|
||||
LL | let _: Option<Opcode> = (1..3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider using `bool::then` to only transmute if the condition holds
|
||||
|
|
||||
LL | let _: Option<Opcode> = (1..3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
|
||||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:50:68
|
||||
|
|
||||
LL | let _: Option<Opcode> = (1..).contains(&op).then_some(unsafe { std::mem::transmute(op) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider using `bool::then` to only transmute if the condition holds
|
||||
|
|
||||
LL | let _: Option<Opcode> = (1..).contains(&op).then(|| unsafe { std::mem::transmute(op) });
|
||||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:51:68
|
||||
|
|
||||
LL | let _: Option<Opcode> = (..3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider using `bool::then` to only transmute if the condition holds
|
||||
|
|
||||
LL | let _: Option<Opcode> = (..3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
|
||||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:52:69
|
||||
|
|
||||
LL | let _: Option<Opcode> = (..=3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider using `bool::then` to only transmute if the condition holds
|
||||
|
|
||||
LL | let _: Option<Opcode> = (..=3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
|
||||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:61:24
|
||||
|
|
||||
LL | (op < 4).then_some(std::mem::transmute::<_, Opcode>(op));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -56,7 +155,7 @@ LL | (op < 4).then(|| std::mem::transmute::<_, Opcode>(op));
|
|||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:57:60
|
||||
--> $DIR/eager_transmute.rs:90:60
|
||||
|
|
||||
LL | let _: Option<NonZeroU8> = (v1 > 0).then_some(unsafe { std::mem::transmute(v1) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -67,7 +166,7 @@ LL | let _: Option<NonZeroU8> = (v1 > 0).then(|| unsafe { std::mem::transmut
|
|||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:63:86
|
||||
--> $DIR/eager_transmute.rs:96:86
|
||||
|
|
||||
LL | let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -78,7 +177,7 @@ LL | let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| u
|
|||
| ~~~~ ++
|
||||
|
||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||
--> $DIR/eager_transmute.rs:69:93
|
||||
--> $DIR/eager_transmute.rs:102:93
|
||||
|
|
||||
LL | let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -88,5 +187,5 @@ help: consider using `bool::then` to only transmute if the condition holds
|
|||
LL | let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
|
||||
| ~~~~ ++
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: aborting due to 17 previous errors
|
||||
|
||||
|
|
|
|||
27
tests/ui/empty_enum_variants_with_brackets.fixed
Normal file
27
tests/ui/empty_enum_variants_with_brackets.fixed
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#![warn(clippy::empty_enum_variants_with_brackets)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub enum PublicTestEnum {
|
||||
NonEmptyBraces { x: i32, y: i32 }, // No error
|
||||
NonEmptyParentheses(i32, i32), // No error
|
||||
EmptyBraces, //~ ERROR: enum variant has empty brackets
|
||||
EmptyParentheses, //~ ERROR: enum variant has empty brackets
|
||||
}
|
||||
|
||||
enum TestEnum {
|
||||
NonEmptyBraces { x: i32, y: i32 }, // No error
|
||||
NonEmptyParentheses(i32, i32), // No error
|
||||
EmptyBraces, //~ ERROR: enum variant has empty brackets
|
||||
EmptyParentheses, //~ ERROR: enum variant has empty brackets
|
||||
AnotherEnum, // No error
|
||||
}
|
||||
|
||||
enum TestEnumWithFeatures {
|
||||
NonEmptyBraces {
|
||||
#[cfg(feature = "thisisneverenabled")]
|
||||
x: i32,
|
||||
}, // No error
|
||||
NonEmptyParentheses(#[cfg(feature = "thisisneverenabled")] i32), // No error
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
27
tests/ui/empty_enum_variants_with_brackets.rs
Normal file
27
tests/ui/empty_enum_variants_with_brackets.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#![warn(clippy::empty_enum_variants_with_brackets)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub enum PublicTestEnum {
|
||||
NonEmptyBraces { x: i32, y: i32 }, // No error
|
||||
NonEmptyParentheses(i32, i32), // No error
|
||||
EmptyBraces {}, //~ ERROR: enum variant has empty brackets
|
||||
EmptyParentheses(), //~ ERROR: enum variant has empty brackets
|
||||
}
|
||||
|
||||
enum TestEnum {
|
||||
NonEmptyBraces { x: i32, y: i32 }, // No error
|
||||
NonEmptyParentheses(i32, i32), // No error
|
||||
EmptyBraces {}, //~ ERROR: enum variant has empty brackets
|
||||
EmptyParentheses(), //~ ERROR: enum variant has empty brackets
|
||||
AnotherEnum, // No error
|
||||
}
|
||||
|
||||
enum TestEnumWithFeatures {
|
||||
NonEmptyBraces {
|
||||
#[cfg(feature = "thisisneverenabled")]
|
||||
x: i32,
|
||||
}, // No error
|
||||
NonEmptyParentheses(#[cfg(feature = "thisisneverenabled")] i32), // No error
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
36
tests/ui/empty_enum_variants_with_brackets.stderr
Normal file
36
tests/ui/empty_enum_variants_with_brackets.stderr
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
error: enum variant has empty brackets
|
||||
--> $DIR/empty_enum_variants_with_brackets.rs:7:16
|
||||
|
|
||||
LL | EmptyBraces {},
|
||||
| ^^^
|
||||
|
|
||||
= note: `-D clippy::empty-enum-variants-with-brackets` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::empty_enum_variants_with_brackets)]`
|
||||
= help: remove the brackets
|
||||
|
||||
error: enum variant has empty brackets
|
||||
--> $DIR/empty_enum_variants_with_brackets.rs:8:21
|
||||
|
|
||||
LL | EmptyParentheses(),
|
||||
| ^^
|
||||
|
|
||||
= help: remove the brackets
|
||||
|
||||
error: enum variant has empty brackets
|
||||
--> $DIR/empty_enum_variants_with_brackets.rs:14:16
|
||||
|
|
||||
LL | EmptyBraces {},
|
||||
| ^^^
|
||||
|
|
||||
= help: remove the brackets
|
||||
|
||||
error: enum variant has empty brackets
|
||||
--> $DIR/empty_enum_variants_with_brackets.rs:15:21
|
||||
|
|
||||
LL | EmptyParentheses(),
|
||||
| ^^
|
||||
|
|
||||
= help: remove the brackets
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
@ -22,9 +22,9 @@ mod rustc_ok {
|
|||
|
||||
#[expect(illegal_floating_point_literal_pattern)]
|
||||
match x {
|
||||
5.0 => {}
|
||||
6.0 => {}
|
||||
_ => {}
|
||||
5.0 => {},
|
||||
6.0 => {},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -41,9 +41,9 @@ mod rustc_warn {
|
|||
#[expect(illegal_floating_point_literal_pattern)]
|
||||
//~^ ERROR: this lint expectation is unfulfilled
|
||||
match x {
|
||||
5 => {}
|
||||
6 => {}
|
||||
_ => {}
|
||||
5 => {},
|
||||
6 => {},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@
|
|||
clippy::unnecessary_operation,
|
||||
clippy::op_ref,
|
||||
clippy::double_parens,
|
||||
clippy::uninlined_format_args
|
||||
clippy::uninlined_format_args,
|
||||
clippy::borrow_deref_ref,
|
||||
clippy::deref_addrof
|
||||
)]
|
||||
|
||||
use std::fmt::Write as _;
|
||||
|
|
@ -40,32 +42,45 @@ fn main() {
|
|||
let x = 0;
|
||||
|
||||
x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
x + 1;
|
||||
x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
1 + x;
|
||||
x - ZERO; //no error, as we skip lookups (for now)
|
||||
x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
((ZERO)) | x; //no error, as we skip lookups (for now)
|
||||
|
||||
x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
x / ONE; //no error, as we skip lookups (for now)
|
||||
|
||||
x / 2; //no false positive
|
||||
|
||||
x & NEG_ONE; //no error, as we skip lookups (for now)
|
||||
x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
let u: u8 = 0;
|
||||
u;
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
1 << 0; // no error, this case is allowed, see issue 3430
|
||||
42;
|
||||
//~^ ERROR: this operation has no effect
|
||||
1;
|
||||
//~^ ERROR: this operation has no effect
|
||||
42;
|
||||
//~^ ERROR: this operation has no effect
|
||||
x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
let mut a = A(String::new());
|
||||
let b = a << 0; // no error: non-integer
|
||||
|
|
@ -73,10 +88,15 @@ fn main() {
|
|||
1 * Meter; // no error: non-integer
|
||||
|
||||
2;
|
||||
//~^ ERROR: this operation has no effect
|
||||
-2;
|
||||
//~^ ERROR: this operation has no effect
|
||||
2 + x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
-2 + x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
x + 1;
|
||||
//~^ ERROR: this operation has no effect
|
||||
(x + 1) % 3; // no error
|
||||
4 % 3; // no error
|
||||
4 % -3; // no error
|
||||
|
|
@ -85,38 +105,110 @@ fn main() {
|
|||
let a = 0;
|
||||
let b = true;
|
||||
(if b { 1 } else { 2 });
|
||||
//~^ ERROR: this operation has no effect
|
||||
(if b { 1 } else { 2 }) + if b { 3 } else { 4 };
|
||||
//~^ ERROR: this operation has no effect
|
||||
(match a { 0 => 10, _ => 20 });
|
||||
//~^ ERROR: this operation has no effect
|
||||
(match a { 0 => 10, _ => 20 }) + match a { 0 => 30, _ => 40 };
|
||||
//~^ ERROR: this operation has no effect
|
||||
(if b { 1 } else { 2 }) + match a { 0 => 30, _ => 40 };
|
||||
//~^ ERROR: this operation has no effect
|
||||
(match a { 0 => 10, _ => 20 }) + if b { 3 } else { 4 };
|
||||
//~^ ERROR: this operation has no effect
|
||||
(if b { 1 } else { 2 });
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
({ a }) + 3;
|
||||
//~^ ERROR: this operation has no effect
|
||||
({ a } * 2);
|
||||
//~^ ERROR: this operation has no effect
|
||||
(loop { let mut c = 0; if c == 10 { break c; } c += 1; }) + { a * 2 };
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
fn f(_: i32) {
|
||||
todo!();
|
||||
}
|
||||
|
||||
f(a + { 8 * 5 });
|
||||
//~^ ERROR: this operation has no effect
|
||||
f(if b { 1 } else { 2 } + 3);
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
const _: i32 = { 2 * 4 } + 3;
|
||||
//~^ ERROR: this operation has no effect
|
||||
const _: i32 = { 1 + 2 * 3 } + 3;
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
a as usize;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let _ = a as usize;
|
||||
//~^ ERROR: this operation has no effect
|
||||
({ a } as usize);
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
2 * { a };
|
||||
//~^ ERROR: this operation has no effect
|
||||
(({ a } + 4));
|
||||
//~^ ERROR: this operation has no effect
|
||||
1;
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
// Issue #9904
|
||||
let x = 0i32;
|
||||
let _: i32 = x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
}
|
||||
|
||||
pub fn decide(a: bool, b: bool) -> u32 {
|
||||
(if a { 1 } else { 2 }) + if b { 3 } else { 5 }
|
||||
}
|
||||
|
||||
/// The following tests are from / for issue #12050
|
||||
/// In short, the lint didn't work for coerced references,
|
||||
/// e.g. let x = &0; let y = x + 0;
|
||||
/// because the suggested fix was `let y = x;` but
|
||||
/// it should have been `let y = *x;`
|
||||
fn issue_12050() {
|
||||
{
|
||||
let x = &0i32;
|
||||
let _: i32 = *x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let _: i32 = *x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
}
|
||||
{
|
||||
let x = &&0i32;
|
||||
let _: i32 = **x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let x = &&0i32;
|
||||
let _: i32 = **x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
}
|
||||
{
|
||||
// this is just silly
|
||||
let x = &&&0i32;
|
||||
let _: i32 = ***x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let _: i32 = ***x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let x = 0i32;
|
||||
let _: i32 = *&x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let _: i32 = **&&x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let _: i32 = *&*&x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let _: i32 = **&&*&x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
}
|
||||
{
|
||||
// this is getting ridiculous, but we should still see the same
|
||||
// error message so let's just keep going
|
||||
let x = &0i32;
|
||||
let _: i32 = ***&&*&x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let _: i32 = ***&&*&x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@
|
|||
clippy::unnecessary_operation,
|
||||
clippy::op_ref,
|
||||
clippy::double_parens,
|
||||
clippy::uninlined_format_args
|
||||
clippy::uninlined_format_args,
|
||||
clippy::borrow_deref_ref,
|
||||
clippy::deref_addrof
|
||||
)]
|
||||
|
||||
use std::fmt::Write as _;
|
||||
|
|
@ -40,32 +42,45 @@ fn main() {
|
|||
let x = 0;
|
||||
|
||||
x + 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
x + (1 - 1);
|
||||
//~^ ERROR: this operation has no effect
|
||||
x + 1;
|
||||
0 + x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
1 + x;
|
||||
x - ZERO; //no error, as we skip lookups (for now)
|
||||
x | (0);
|
||||
//~^ ERROR: this operation has no effect
|
||||
((ZERO)) | x; //no error, as we skip lookups (for now)
|
||||
|
||||
x * 1;
|
||||
//~^ ERROR: this operation has no effect
|
||||
1 * x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
x / ONE; //no error, as we skip lookups (for now)
|
||||
|
||||
x / 2; //no false positive
|
||||
|
||||
x & NEG_ONE; //no error, as we skip lookups (for now)
|
||||
-1 & x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
let u: u8 = 0;
|
||||
u & 255;
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
1 << 0; // no error, this case is allowed, see issue 3430
|
||||
42 << 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
1 >> 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
42 >> 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
&x >> 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
x >> &0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
let mut a = A(String::new());
|
||||
let b = a << 0; // no error: non-integer
|
||||
|
|
@ -73,10 +88,15 @@ fn main() {
|
|||
1 * Meter; // no error: non-integer
|
||||
|
||||
2 % 3;
|
||||
//~^ ERROR: this operation has no effect
|
||||
-2 % 3;
|
||||
//~^ ERROR: this operation has no effect
|
||||
2 % -3 + x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
-2 % -3 + x;
|
||||
//~^ ERROR: this operation has no effect
|
||||
x + 1 % 3;
|
||||
//~^ ERROR: this operation has no effect
|
||||
(x + 1) % 3; // no error
|
||||
4 % 3; // no error
|
||||
4 % -3; // no error
|
||||
|
|
@ -85,38 +105,110 @@ fn main() {
|
|||
let a = 0;
|
||||
let b = true;
|
||||
0 + if b { 1 } else { 2 };
|
||||
//~^ ERROR: this operation has no effect
|
||||
0 + if b { 1 } else { 2 } + if b { 3 } else { 4 };
|
||||
//~^ ERROR: this operation has no effect
|
||||
0 + match a { 0 => 10, _ => 20 };
|
||||
//~^ ERROR: this operation has no effect
|
||||
0 + match a { 0 => 10, _ => 20 } + match a { 0 => 30, _ => 40 };
|
||||
//~^ ERROR: this operation has no effect
|
||||
0 + if b { 1 } else { 2 } + match a { 0 => 30, _ => 40 };
|
||||
//~^ ERROR: this operation has no effect
|
||||
0 + match a { 0 => 10, _ => 20 } + if b { 3 } else { 4 };
|
||||
//~^ ERROR: this operation has no effect
|
||||
(if b { 1 } else { 2 }) + 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
0 + { a } + 3;
|
||||
//~^ ERROR: this operation has no effect
|
||||
0 + { a } * 2;
|
||||
//~^ ERROR: this operation has no effect
|
||||
0 + loop { let mut c = 0; if c == 10 { break c; } c += 1; } + { a * 2 };
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
fn f(_: i32) {
|
||||
todo!();
|
||||
}
|
||||
|
||||
f(1 * a + { 8 * 5 });
|
||||
//~^ ERROR: this operation has no effect
|
||||
f(0 + if b { 1 } else { 2 } + 3);
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
const _: i32 = { 2 * 4 } + 0 + 3;
|
||||
//~^ ERROR: this operation has no effect
|
||||
const _: i32 = 0 + { 1 + 2 * 3 } + 3;
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
0 + a as usize;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let _ = 0 + a as usize;
|
||||
//~^ ERROR: this operation has no effect
|
||||
0 + { a } as usize;
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
2 * (0 + { a });
|
||||
//~^ ERROR: this operation has no effect
|
||||
1 * ({ a } + 4);
|
||||
//~^ ERROR: this operation has no effect
|
||||
1 * 1;
|
||||
//~^ ERROR: this operation has no effect
|
||||
|
||||
// Issue #9904
|
||||
let x = 0i32;
|
||||
let _: i32 = &x + 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
}
|
||||
|
||||
pub fn decide(a: bool, b: bool) -> u32 {
|
||||
0 + if a { 1 } else { 2 } + if b { 3 } else { 5 }
|
||||
}
|
||||
|
||||
/// The following tests are from / for issue #12050
|
||||
/// In short, the lint didn't work for coerced references,
|
||||
/// e.g. let x = &0; let y = x + 0;
|
||||
/// because the suggested fix was `let y = x;` but
|
||||
/// it should have been `let y = *x;`
|
||||
fn issue_12050() {
|
||||
{
|
||||
let x = &0i32;
|
||||
let _: i32 = *x + 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let _: i32 = x + 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
}
|
||||
{
|
||||
let x = &&0i32;
|
||||
let _: i32 = **x + 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let x = &&0i32;
|
||||
let _: i32 = *x + 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
}
|
||||
{
|
||||
// this is just silly
|
||||
let x = &&&0i32;
|
||||
let _: i32 = ***x + 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let _: i32 = **x + 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let x = 0i32;
|
||||
let _: i32 = *&x + 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let _: i32 = **&&x + 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let _: i32 = *&*&x + 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let _: i32 = **&&*&x + 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
}
|
||||
{
|
||||
// this is getting ridiculous, but we should still see the same
|
||||
// error message so let's just keep going
|
||||
let x = &0i32;
|
||||
let _: i32 = **&&*&x + 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
let _: i32 = **&&*&x + 0;
|
||||
//~^ ERROR: this operation has no effect
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:42:5
|
||||
--> $DIR/identity_op.rs:44:5
|
||||
|
|
||||
LL | x + 0;
|
||||
| ^^^^^ help: consider reducing it to: `x`
|
||||
|
|
@ -8,238 +8,310 @@ LL | x + 0;
|
|||
= help: to override `-D warnings` add `#[allow(clippy::identity_op)]`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:43:5
|
||||
--> $DIR/identity_op.rs:46:5
|
||||
|
|
||||
LL | x + (1 - 1);
|
||||
| ^^^^^^^^^^^ help: consider reducing it to: `x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:45:5
|
||||
--> $DIR/identity_op.rs:49:5
|
||||
|
|
||||
LL | 0 + x;
|
||||
| ^^^^^ help: consider reducing it to: `x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:48:5
|
||||
--> $DIR/identity_op.rs:53:5
|
||||
|
|
||||
LL | x | (0);
|
||||
| ^^^^^^^ help: consider reducing it to: `x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:51:5
|
||||
--> $DIR/identity_op.rs:57:5
|
||||
|
|
||||
LL | x * 1;
|
||||
| ^^^^^ help: consider reducing it to: `x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:52:5
|
||||
--> $DIR/identity_op.rs:59:5
|
||||
|
|
||||
LL | 1 * x;
|
||||
| ^^^^^ help: consider reducing it to: `x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:58:5
|
||||
--> $DIR/identity_op.rs:66:5
|
||||
|
|
||||
LL | -1 & x;
|
||||
| ^^^^^^ help: consider reducing it to: `x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:61:5
|
||||
--> $DIR/identity_op.rs:70:5
|
||||
|
|
||||
LL | u & 255;
|
||||
| ^^^^^^^ help: consider reducing it to: `u`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:64:5
|
||||
--> $DIR/identity_op.rs:74:5
|
||||
|
|
||||
LL | 42 << 0;
|
||||
| ^^^^^^^ help: consider reducing it to: `42`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:65:5
|
||||
--> $DIR/identity_op.rs:76:5
|
||||
|
|
||||
LL | 1 >> 0;
|
||||
| ^^^^^^ help: consider reducing it to: `1`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:66:5
|
||||
--> $DIR/identity_op.rs:78:5
|
||||
|
|
||||
LL | 42 >> 0;
|
||||
| ^^^^^^^ help: consider reducing it to: `42`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:67:5
|
||||
--> $DIR/identity_op.rs:80:5
|
||||
|
|
||||
LL | &x >> 0;
|
||||
| ^^^^^^^ help: consider reducing it to: `x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:68:5
|
||||
--> $DIR/identity_op.rs:82:5
|
||||
|
|
||||
LL | x >> &0;
|
||||
| ^^^^^^^ help: consider reducing it to: `x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:75:5
|
||||
--> $DIR/identity_op.rs:90:5
|
||||
|
|
||||
LL | 2 % 3;
|
||||
| ^^^^^ help: consider reducing it to: `2`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:76:5
|
||||
--> $DIR/identity_op.rs:92:5
|
||||
|
|
||||
LL | -2 % 3;
|
||||
| ^^^^^^ help: consider reducing it to: `-2`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:77:5
|
||||
--> $DIR/identity_op.rs:94:5
|
||||
|
|
||||
LL | 2 % -3 + x;
|
||||
| ^^^^^^ help: consider reducing it to: `2`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:78:5
|
||||
--> $DIR/identity_op.rs:96:5
|
||||
|
|
||||
LL | -2 % -3 + x;
|
||||
| ^^^^^^^ help: consider reducing it to: `-2`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:79:9
|
||||
--> $DIR/identity_op.rs:98:9
|
||||
|
|
||||
LL | x + 1 % 3;
|
||||
| ^^^^^ help: consider reducing it to: `1`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:87:5
|
||||
--> $DIR/identity_op.rs:107:5
|
||||
|
|
||||
LL | 0 + if b { 1 } else { 2 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:88:5
|
||||
--> $DIR/identity_op.rs:109:5
|
||||
|
|
||||
LL | 0 + if b { 1 } else { 2 } + if b { 3 } else { 4 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:89:5
|
||||
--> $DIR/identity_op.rs:111:5
|
||||
|
|
||||
LL | 0 + match a { 0 => 10, _ => 20 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(match a { 0 => 10, _ => 20 })`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:90:5
|
||||
--> $DIR/identity_op.rs:113:5
|
||||
|
|
||||
LL | 0 + match a { 0 => 10, _ => 20 } + match a { 0 => 30, _ => 40 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(match a { 0 => 10, _ => 20 })`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:91:5
|
||||
--> $DIR/identity_op.rs:115:5
|
||||
|
|
||||
LL | 0 + if b { 1 } else { 2 } + match a { 0 => 30, _ => 40 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:92:5
|
||||
--> $DIR/identity_op.rs:117:5
|
||||
|
|
||||
LL | 0 + match a { 0 => 10, _ => 20 } + if b { 3 } else { 4 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(match a { 0 => 10, _ => 20 })`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:93:5
|
||||
--> $DIR/identity_op.rs:119:5
|
||||
|
|
||||
LL | (if b { 1 } else { 2 }) + 0;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:95:5
|
||||
--> $DIR/identity_op.rs:122:5
|
||||
|
|
||||
LL | 0 + { a } + 3;
|
||||
| ^^^^^^^^^ help: consider reducing it to: `({ a })`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:96:5
|
||||
--> $DIR/identity_op.rs:124:5
|
||||
|
|
||||
LL | 0 + { a } * 2;
|
||||
| ^^^^^^^^^^^^^ help: consider reducing it to: `({ a } * 2)`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:97:5
|
||||
--> $DIR/identity_op.rs:126:5
|
||||
|
|
||||
LL | 0 + loop { let mut c = 0; if c == 10 { break c; } c += 1; } + { a * 2 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(loop { let mut c = 0; if c == 10 { break c; } c += 1; })`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:102:7
|
||||
--> $DIR/identity_op.rs:133:7
|
||||
|
|
||||
LL | f(1 * a + { 8 * 5 });
|
||||
| ^^^^^ help: consider reducing it to: `a`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:103:7
|
||||
--> $DIR/identity_op.rs:135:7
|
||||
|
|
||||
LL | f(0 + if b { 1 } else { 2 } + 3);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `if b { 1 } else { 2 }`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:104:20
|
||||
--> $DIR/identity_op.rs:138:20
|
||||
|
|
||||
LL | const _: i32 = { 2 * 4 } + 0 + 3;
|
||||
| ^^^^^^^^^^^^^ help: consider reducing it to: `{ 2 * 4 }`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:105:20
|
||||
--> $DIR/identity_op.rs:140:20
|
||||
|
|
||||
LL | const _: i32 = 0 + { 1 + 2 * 3 } + 3;
|
||||
| ^^^^^^^^^^^^^^^^^ help: consider reducing it to: `{ 1 + 2 * 3 }`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:107:5
|
||||
--> $DIR/identity_op.rs:143:5
|
||||
|
|
||||
LL | 0 + a as usize;
|
||||
| ^^^^^^^^^^^^^^ help: consider reducing it to: `a as usize`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:108:13
|
||||
--> $DIR/identity_op.rs:145:13
|
||||
|
|
||||
LL | let _ = 0 + a as usize;
|
||||
| ^^^^^^^^^^^^^^ help: consider reducing it to: `a as usize`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:109:5
|
||||
--> $DIR/identity_op.rs:147:5
|
||||
|
|
||||
LL | 0 + { a } as usize;
|
||||
| ^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `({ a } as usize)`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:111:9
|
||||
--> $DIR/identity_op.rs:150:9
|
||||
|
|
||||
LL | 2 * (0 + { a });
|
||||
| ^^^^^^^^^^^ help: consider reducing it to: `{ a }`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:112:5
|
||||
--> $DIR/identity_op.rs:152:5
|
||||
|
|
||||
LL | 1 * ({ a } + 4);
|
||||
| ^^^^^^^^^^^^^^^ help: consider reducing it to: `(({ a } + 4))`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:113:5
|
||||
--> $DIR/identity_op.rs:154:5
|
||||
|
|
||||
LL | 1 * 1;
|
||||
| ^^^^^ help: consider reducing it to: `1`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:117:18
|
||||
--> $DIR/identity_op.rs:159:18
|
||||
|
|
||||
LL | let _: i32 = &x + 0;
|
||||
| ^^^^^^ help: consider reducing it to: `x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:121:5
|
||||
--> $DIR/identity_op.rs:164:5
|
||||
|
|
||||
LL | 0 + if a { 1 } else { 2 } + if b { 3 } else { 5 }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if a { 1 } else { 2 })`
|
||||
|
||||
error: aborting due to 40 previous errors
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:175:22
|
||||
|
|
||||
LL | let _: i32 = *x + 0;
|
||||
| ^^^^^^ help: consider reducing it to: `*x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:177:22
|
||||
|
|
||||
LL | let _: i32 = x + 0;
|
||||
| ^^^^^ help: consider reducing it to: `*x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:182:22
|
||||
|
|
||||
LL | let _: i32 = **x + 0;
|
||||
| ^^^^^^^ help: consider reducing it to: `**x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:185:22
|
||||
|
|
||||
LL | let _: i32 = *x + 0;
|
||||
| ^^^^^^ help: consider reducing it to: `**x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:191:22
|
||||
|
|
||||
LL | let _: i32 = ***x + 0;
|
||||
| ^^^^^^^^ help: consider reducing it to: `***x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:193:22
|
||||
|
|
||||
LL | let _: i32 = **x + 0;
|
||||
| ^^^^^^^ help: consider reducing it to: `***x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:196:22
|
||||
|
|
||||
LL | let _: i32 = *&x + 0;
|
||||
| ^^^^^^^ help: consider reducing it to: `*&x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:198:22
|
||||
|
|
||||
LL | let _: i32 = **&&x + 0;
|
||||
| ^^^^^^^^^ help: consider reducing it to: `**&&x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:200:22
|
||||
|
|
||||
LL | let _: i32 = *&*&x + 0;
|
||||
| ^^^^^^^^^ help: consider reducing it to: `*&*&x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:202:22
|
||||
|
|
||||
LL | let _: i32 = **&&*&x + 0;
|
||||
| ^^^^^^^^^^^ help: consider reducing it to: `**&&*&x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:209:22
|
||||
|
|
||||
LL | let _: i32 = **&&*&x + 0;
|
||||
| ^^^^^^^^^^^ help: consider reducing it to: `***&&*&x`
|
||||
|
||||
error: this operation has no effect
|
||||
--> $DIR/identity_op.rs:211:22
|
||||
|
|
||||
LL | let _: i32 = **&&*&x + 0;
|
||||
| ^^^^^^^^^^^ help: consider reducing it to: `***&&*&x`
|
||||
|
||||
error: aborting due to 52 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -130,3 +130,8 @@ fn issue11394(b: bool, v: Result<(), ()>) -> Result<(), ()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
const fn issue12103(x: u32) -> Option<u32> {
|
||||
// Should not issue an error in `const` context
|
||||
if x > 42 { Some(150) } else { None }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
//@no-rustfix
|
||||
//@aux-build:proc_macros.rs
|
||||
#![warn(clippy::into_iter_without_iter)]
|
||||
extern crate proc_macros;
|
||||
|
||||
use std::iter::IntoIterator;
|
||||
|
||||
|
|
@ -111,6 +113,43 @@ impl IntoIterator for &Alias {
|
|||
}
|
||||
}
|
||||
|
||||
// Fine to lint, the impls comes from a local macro.
|
||||
pub struct Issue12037;
|
||||
macro_rules! generate_impl {
|
||||
() => {
|
||||
impl<'a> IntoIterator for &'a Issue12037 {
|
||||
type IntoIter = std::slice::Iter<'a, u8>;
|
||||
type Item = &'a u8;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
generate_impl!();
|
||||
|
||||
// Impl comes from an external crate
|
||||
proc_macros::external! {
|
||||
pub struct ImplWithForeignSpan;
|
||||
impl<'a> IntoIterator for &'a ImplWithForeignSpan {
|
||||
type IntoIter = std::slice::Iter<'a, u8>;
|
||||
type Item = &'a u8;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Allowed;
|
||||
#[allow(clippy::into_iter_without_iter)]
|
||||
impl<'a> IntoIterator for &'a Allowed {
|
||||
type IntoIter = std::slice::Iter<'a, u8>;
|
||||
type Item = &'a u8;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
pub mod issue11635 {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: `IntoIterator` implemented for a reference type without an `iter` method
|
||||
--> $DIR/into_iter_without_iter.rs:7:1
|
||||
--> $DIR/into_iter_without_iter.rs:9:1
|
||||
|
|
||||
LL | / impl<'a> IntoIterator for &'a S1 {
|
||||
LL | |
|
||||
|
|
@ -23,7 +23,7 @@ LL + }
|
|||
|
|
||||
|
||||
error: `IntoIterator` implemented for a reference type without an `iter_mut` method
|
||||
--> $DIR/into_iter_without_iter.rs:15:1
|
||||
--> $DIR/into_iter_without_iter.rs:17:1
|
||||
|
|
||||
LL | / impl<'a> IntoIterator for &'a mut S1 {
|
||||
LL | |
|
||||
|
|
@ -45,7 +45,7 @@ LL + }
|
|||
|
|
||||
|
||||
error: `IntoIterator` implemented for a reference type without an `iter` method
|
||||
--> $DIR/into_iter_without_iter.rs:25:1
|
||||
--> $DIR/into_iter_without_iter.rs:27:1
|
||||
|
|
||||
LL | / impl<'a, T> IntoIterator for &'a S2<T> {
|
||||
LL | |
|
||||
|
|
@ -67,7 +67,7 @@ LL + }
|
|||
|
|
||||
|
||||
error: `IntoIterator` implemented for a reference type without an `iter_mut` method
|
||||
--> $DIR/into_iter_without_iter.rs:33:1
|
||||
--> $DIR/into_iter_without_iter.rs:35:1
|
||||
|
|
||||
LL | / impl<'a, T> IntoIterator for &'a mut S2<T> {
|
||||
LL | |
|
||||
|
|
@ -89,7 +89,7 @@ LL + }
|
|||
|
|
||||
|
||||
error: `IntoIterator` implemented for a reference type without an `iter_mut` method
|
||||
--> $DIR/into_iter_without_iter.rs:84:1
|
||||
--> $DIR/into_iter_without_iter.rs:86:1
|
||||
|
|
||||
LL | / impl<'a, T> IntoIterator for &mut S4<'a, T> {
|
||||
LL | |
|
||||
|
|
@ -110,5 +110,31 @@ LL + }
|
|||
LL + }
|
||||
|
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: `IntoIterator` implemented for a reference type without an `iter` method
|
||||
--> $DIR/into_iter_without_iter.rs:120:9
|
||||
|
|
||||
LL | / impl<'a> IntoIterator for &'a Issue12037 {
|
||||
LL | | type IntoIter = std::slice::Iter<'a, u8>;
|
||||
LL | | type Item = &'a u8;
|
||||
LL | | fn into_iter(self) -> Self::IntoIter {
|
||||
LL | | todo!()
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_________^
|
||||
...
|
||||
LL | generate_impl!();
|
||||
| ---------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `generate_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: consider implementing `iter`
|
||||
|
|
||||
LL ~
|
||||
LL + impl Issue12037 {
|
||||
LL + fn iter(&self) -> std::slice::Iter<'a, u8> {
|
||||
LL + <&Self as IntoIterator>::into_iter(self)
|
||||
LL + }
|
||||
LL + }
|
||||
|
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,72 @@
|
|||
#![warn(clippy::iter_filter_is_ok)]
|
||||
#![allow(
|
||||
clippy::map_identity,
|
||||
clippy::result_filter_map,
|
||||
clippy::needless_borrow,
|
||||
clippy::redundant_closure
|
||||
)]
|
||||
|
||||
fn main() {
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
{
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Ok(1), Err(2)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Ok(1), Err(2)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
{
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Ok(1), Err(2)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
|
||||
{
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
.flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
.flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
|
||||
{
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Ok(1), Err(2)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
}
|
||||
|
||||
fn avoid_linting_when_filter_has_side_effects() {
|
||||
// Don't lint below
|
||||
let mut counter = 0;
|
||||
let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| {
|
||||
counter += 1;
|
||||
o.is_ok()
|
||||
});
|
||||
}
|
||||
|
||||
fn avoid_linting_when_commented() {
|
||||
let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| {
|
||||
// Roses are red,
|
||||
// Violets are blue,
|
||||
|
|
@ -24,3 +75,131 @@ fn main() {
|
|||
o.is_ok()
|
||||
});
|
||||
}
|
||||
|
||||
fn ice_12058() {
|
||||
// check that checking the parent node doesn't cause an ICE
|
||||
// by indexing the parameters of a closure without parameters
|
||||
Some(1).or_else(|| {
|
||||
vec![Ok(1), Err(())].into_iter().filter(|z| *z != Ok(2));
|
||||
None
|
||||
});
|
||||
}
|
||||
|
||||
fn avoid_linting_map() {
|
||||
// should not lint
|
||||
let _ = vec![Ok(1), Err(())]
|
||||
.into_iter()
|
||||
.filter(|o| o.is_ok())
|
||||
.map(|o| o.unwrap());
|
||||
|
||||
// should not lint
|
||||
let _ = vec![Ok(1), Err(())].into_iter().filter(|o| o.is_ok()).map(|o| o);
|
||||
}
|
||||
|
||||
fn avoid_false_positive_due_to_is_ok_and_iterator_impl() {
|
||||
#[derive(Default, Clone)]
|
||||
struct Foo {}
|
||||
|
||||
impl Foo {
|
||||
fn is_ok(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Foo {
|
||||
type Item = Foo;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
Some(Foo::default())
|
||||
}
|
||||
}
|
||||
|
||||
let data = vec![Foo::default()];
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(Foo::is_ok);
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(|f| f.is_ok());
|
||||
}
|
||||
|
||||
fn avoid_false_positive_due_to_is_ok_and_into_iterator_impl() {
|
||||
#[derive(Default, Clone)]
|
||||
struct Foo {}
|
||||
|
||||
impl Foo {
|
||||
fn is_ok(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
let data = vec![Foo::default()];
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(Foo::is_ok);
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(|f| f.is_ok());
|
||||
}
|
||||
|
||||
fn avoid_fp_for_trivial() {
|
||||
let _ = vec![Ok(1), Err(()), Ok(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| (Err(()) as Result<i32, ()>).is_ok());
|
||||
}
|
||||
|
||||
fn avoid_false_positive_due_to_method_name() {
|
||||
fn is_ok(x: &Result<i32, i32>) -> bool {
|
||||
x.is_ok()
|
||||
}
|
||||
|
||||
vec![Ok(1), Err(2), Ok(3)].into_iter().filter(is_ok);
|
||||
// should not lint
|
||||
}
|
||||
|
||||
fn avoid_fp_due_to_trait_type() {
|
||||
struct Foo {
|
||||
bar: i32,
|
||||
}
|
||||
impl Foo {
|
||||
fn is_ok(obj: &Result<i32, i32>) -> bool {
|
||||
obj.is_ok()
|
||||
}
|
||||
}
|
||||
vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Foo::is_ok);
|
||||
// should not lint
|
||||
}
|
||||
|
||||
fn avoid_fp_with_call_to_outside_var() {
|
||||
let outside: Result<i32, ()> = Ok(1);
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| outside.is_ok());
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| Result::is_ok(&outside));
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| std::result::Result::is_ok(&outside));
|
||||
}
|
||||
|
||||
fn avoid_fp_with_call_to_outside_var_mix_match_types() {
|
||||
let outside = Some(1);
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| outside.is_some());
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| Option::is_some(&outside));
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| std::option::Option::is_some(&outside));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,72 @@
|
|||
#![warn(clippy::iter_filter_is_ok)]
|
||||
#![allow(
|
||||
clippy::map_identity,
|
||||
clippy::result_filter_map,
|
||||
clippy::needless_borrow,
|
||||
clippy::redundant_closure
|
||||
)]
|
||||
|
||||
fn main() {
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Result::is_ok);
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| a.is_ok());
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
{
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Result::is_ok);
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| a.is_ok());
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { o.is_ok() });
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { o.is_ok() });
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
{
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|&a| a.is_ok());
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|&a| a.is_ok());
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Ok(1), Err(2)].into_iter().filter(|&o| { o.is_ok() });
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
|
||||
{
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
.filter(std::result::Result::is_ok);
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
.filter(|a| std::result::Result::is_ok(a));
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| { std::result::Result::is_ok(a) });
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
|
||||
{
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|ref a| a.is_ok());
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|ref a| a.is_ok());
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Ok(1), Err(2)].into_iter().filter(|ref o| { o.is_ok() });
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
}
|
||||
|
||||
fn avoid_linting_when_filter_has_side_effects() {
|
||||
// Don't lint below
|
||||
let mut counter = 0;
|
||||
let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| {
|
||||
counter += 1;
|
||||
o.is_ok()
|
||||
});
|
||||
}
|
||||
|
||||
fn avoid_linting_when_commented() {
|
||||
let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| {
|
||||
// Roses are red,
|
||||
// Violets are blue,
|
||||
|
|
@ -24,3 +75,131 @@ fn main() {
|
|||
o.is_ok()
|
||||
});
|
||||
}
|
||||
|
||||
fn ice_12058() {
|
||||
// check that checking the parent node doesn't cause an ICE
|
||||
// by indexing the parameters of a closure without parameters
|
||||
Some(1).or_else(|| {
|
||||
vec![Ok(1), Err(())].into_iter().filter(|z| *z != Ok(2));
|
||||
None
|
||||
});
|
||||
}
|
||||
|
||||
fn avoid_linting_map() {
|
||||
// should not lint
|
||||
let _ = vec![Ok(1), Err(())]
|
||||
.into_iter()
|
||||
.filter(|o| o.is_ok())
|
||||
.map(|o| o.unwrap());
|
||||
|
||||
// should not lint
|
||||
let _ = vec![Ok(1), Err(())].into_iter().filter(|o| o.is_ok()).map(|o| o);
|
||||
}
|
||||
|
||||
fn avoid_false_positive_due_to_is_ok_and_iterator_impl() {
|
||||
#[derive(Default, Clone)]
|
||||
struct Foo {}
|
||||
|
||||
impl Foo {
|
||||
fn is_ok(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Foo {
|
||||
type Item = Foo;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
Some(Foo::default())
|
||||
}
|
||||
}
|
||||
|
||||
let data = vec![Foo::default()];
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(Foo::is_ok);
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(|f| f.is_ok());
|
||||
}
|
||||
|
||||
fn avoid_false_positive_due_to_is_ok_and_into_iterator_impl() {
|
||||
#[derive(Default, Clone)]
|
||||
struct Foo {}
|
||||
|
||||
impl Foo {
|
||||
fn is_ok(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
let data = vec![Foo::default()];
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(Foo::is_ok);
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(|f| f.is_ok());
|
||||
}
|
||||
|
||||
fn avoid_fp_for_trivial() {
|
||||
let _ = vec![Ok(1), Err(()), Ok(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| (Err(()) as Result<i32, ()>).is_ok());
|
||||
}
|
||||
|
||||
fn avoid_false_positive_due_to_method_name() {
|
||||
fn is_ok(x: &Result<i32, i32>) -> bool {
|
||||
x.is_ok()
|
||||
}
|
||||
|
||||
vec![Ok(1), Err(2), Ok(3)].into_iter().filter(is_ok);
|
||||
// should not lint
|
||||
}
|
||||
|
||||
fn avoid_fp_due_to_trait_type() {
|
||||
struct Foo {
|
||||
bar: i32,
|
||||
}
|
||||
impl Foo {
|
||||
fn is_ok(obj: &Result<i32, i32>) -> bool {
|
||||
obj.is_ok()
|
||||
}
|
||||
}
|
||||
vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Foo::is_ok);
|
||||
// should not lint
|
||||
}
|
||||
|
||||
fn avoid_fp_with_call_to_outside_var() {
|
||||
let outside: Result<i32, ()> = Ok(1);
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| outside.is_ok());
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| Result::is_ok(&outside));
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| std::result::Result::is_ok(&outside));
|
||||
}
|
||||
|
||||
fn avoid_fp_with_call_to_outside_var_mix_match_types() {
|
||||
let outside = Some(1);
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| outside.is_some());
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| Option::is_some(&outside));
|
||||
|
||||
let _ = vec![Ok(1), Err(2), Ok(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| std::option::Option::is_some(&outside));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,77 @@
|
|||
error: `filter` for `is_ok` on iterator over `Result`s
|
||||
--> $DIR/iter_filter_is_ok.rs:4:52
|
||||
--> $DIR/iter_filter_is_ok.rs:11:56
|
||||
|
|
||||
LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Result::is_ok);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Result::is_ok);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
|
||||
= note: `-D clippy::iter-filter-is-ok` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::iter_filter_is_ok)]`
|
||||
|
||||
error: `filter` for `is_ok` on iterator over `Result`s
|
||||
--> $DIR/iter_filter_is_ok.rs:6:52
|
||||
--> $DIR/iter_filter_is_ok.rs:13:56
|
||||
|
|
||||
LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| a.is_ok());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| a.is_ok());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_ok` on iterator over `Result`s
|
||||
--> $DIR/iter_filter_is_ok.rs:10:45
|
||||
--> $DIR/iter_filter_is_ok.rs:16:49
|
||||
|
|
||||
LL | let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { o.is_ok() });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
LL | let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { o.is_ok() });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: `filter` for `is_ok` on iterator over `Result`s
|
||||
--> $DIR/iter_filter_is_ok.rs:21:56
|
||||
|
|
||||
LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|&a| a.is_ok());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_ok` on iterator over `Result`s
|
||||
--> $DIR/iter_filter_is_ok.rs:24:56
|
||||
|
|
||||
LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|&a| a.is_ok());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_ok` on iterator over `Result`s
|
||||
--> $DIR/iter_filter_is_ok.rs:28:49
|
||||
|
|
||||
LL | let _ = vec![Ok(1), Err(2)].into_iter().filter(|&o| { o.is_ok() });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_ok` on iterator over `Result`s
|
||||
--> $DIR/iter_filter_is_ok.rs:35:14
|
||||
|
|
||||
LL | .filter(std::result::Result::is_ok);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_ok` on iterator over `Result`s
|
||||
--> $DIR/iter_filter_is_ok.rs:40:14
|
||||
|
|
||||
LL | .filter(|a| std::result::Result::is_ok(a));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_ok` on iterator over `Result`s
|
||||
--> $DIR/iter_filter_is_ok.rs:43:56
|
||||
|
|
||||
LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| { std::result::Result::is_ok(a) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_ok` on iterator over `Result`s
|
||||
--> $DIR/iter_filter_is_ok.rs:48:56
|
||||
|
|
||||
LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|ref a| a.is_ok());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_ok` on iterator over `Result`s
|
||||
--> $DIR/iter_filter_is_ok.rs:51:56
|
||||
|
|
||||
LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|ref a| a.is_ok());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_ok` on iterator over `Result`s
|
||||
--> $DIR/iter_filter_is_ok.rs:55:49
|
||||
|
|
||||
LL | let _ = vec![Ok(1), Err(2)].into_iter().filter(|ref o| { o.is_ok() });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +1,70 @@
|
|||
#![warn(clippy::iter_filter_is_some)]
|
||||
#![allow(
|
||||
clippy::map_identity,
|
||||
clippy::result_filter_map,
|
||||
clippy::needless_borrow,
|
||||
clippy::option_filter_map,
|
||||
clippy::redundant_closure
|
||||
)]
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn main() {
|
||||
let _ = vec![Some(1)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
let _ = vec![Some(1)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
{
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Some(1)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
{
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
.flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
.flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
|
||||
{
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
|
||||
{
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
}
|
||||
|
||||
fn avoid_linting_when_filter_has_side_effects() {
|
||||
// Don't lint below
|
||||
let mut counter = 0;
|
||||
let _ = vec![Some(1)].into_iter().filter(|o| {
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().filter(|o| {
|
||||
counter += 1;
|
||||
o.is_some()
|
||||
});
|
||||
}
|
||||
|
||||
let _ = vec![Some(1)].into_iter().filter(|o| {
|
||||
fn avoid_linting_when_commented() {
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().filter(|o| {
|
||||
// Roses are red,
|
||||
// Violets are blue,
|
||||
// `Err` is not an `Option`,
|
||||
|
|
@ -25,3 +72,169 @@ fn main() {
|
|||
o.is_some()
|
||||
});
|
||||
}
|
||||
|
||||
fn ice_12058() {
|
||||
// check that checking the parent node doesn't cause an ICE
|
||||
// by indexing the parameters of a closure without parameters
|
||||
Some(1).or_else(|| {
|
||||
vec![Some(1), None, Some(3)].into_iter().filter(|z| *z != Some(2));
|
||||
None
|
||||
});
|
||||
}
|
||||
|
||||
fn avoid_linting_map() {
|
||||
// should not lint
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
.filter(|o| o.is_some())
|
||||
.map(|o| o.unwrap());
|
||||
|
||||
// should not lint
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
.filter(|o| o.is_some())
|
||||
.map(|o| o);
|
||||
}
|
||||
|
||||
fn avoid_false_positive_due_to_is_some_and_iterator_impl() {
|
||||
#[derive(Default, Clone)]
|
||||
struct Foo {}
|
||||
|
||||
impl Foo {
|
||||
fn is_some(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Foo {
|
||||
type Item = Foo;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
Some(Foo::default())
|
||||
}
|
||||
}
|
||||
|
||||
let data = vec![Foo::default()];
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(Foo::is_some);
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(|f| f.is_some());
|
||||
}
|
||||
|
||||
fn avoid_false_positive_due_to_is_some_and_into_iterator_impl() {
|
||||
#[derive(Default, Clone)]
|
||||
struct Foo {}
|
||||
|
||||
impl Foo {
|
||||
fn is_some(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
let data = vec![Foo::default()];
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(Foo::is_some);
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(|f| f.is_some());
|
||||
}
|
||||
|
||||
fn avoid_unpack_fp() {
|
||||
let _ = vec![(Some(1), None), (None, Some(3))]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|(a, _)| a.is_some());
|
||||
let _ = vec![(Some(1), None), (None, Some(3))]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|(a, _)| a.is_some())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let m = HashMap::from([(1, 1)]);
|
||||
let _ = vec![1, 2, 4].into_iter().filter(|a| m.get(a).is_some());
|
||||
// should not lint
|
||||
}
|
||||
|
||||
fn avoid_fp_for_external() {
|
||||
let value = HashMap::from([(1, 1)]);
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| value.get(&1).is_some());
|
||||
|
||||
let value = Option::Some(1);
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| value.is_some());
|
||||
}
|
||||
|
||||
fn avoid_fp_for_trivial() {
|
||||
let value = HashMap::from([(1, 1)]);
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| Some(1).is_some());
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| None::<i32>.is_some());
|
||||
}
|
||||
|
||||
fn avoid_false_positive_due_to_method_name() {
|
||||
fn is_some(x: &Option<i32>) -> bool {
|
||||
x.is_some()
|
||||
}
|
||||
|
||||
vec![Some(1), None, Some(3)].into_iter().filter(is_some);
|
||||
// should not lint
|
||||
}
|
||||
|
||||
fn avoid_fp_due_to_trait_type() {
|
||||
struct Foo {
|
||||
bar: i32,
|
||||
}
|
||||
impl Foo {
|
||||
fn is_some(obj: &Option<i32>) -> bool {
|
||||
obj.is_some()
|
||||
}
|
||||
}
|
||||
vec![Some(1), None, Some(3)].into_iter().filter(Foo::is_some);
|
||||
// should not lint
|
||||
}
|
||||
|
||||
fn avoid_fp_with_call_to_outside_var() {
|
||||
let outside = Some(1);
|
||||
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| outside.is_some());
|
||||
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| Option::is_some(&outside));
|
||||
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| std::option::Option::is_some(&outside));
|
||||
}
|
||||
|
||||
fn avoid_fp_with_call_to_outside_var_mix_match_types() {
|
||||
let outside: Result<i32, ()> = Ok(1);
|
||||
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| outside.is_ok());
|
||||
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| Result::is_ok(&outside));
|
||||
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| std::result::Result::is_ok(&outside));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,70 @@
|
|||
#![warn(clippy::iter_filter_is_some)]
|
||||
#![allow(
|
||||
clippy::map_identity,
|
||||
clippy::result_filter_map,
|
||||
clippy::needless_borrow,
|
||||
clippy::option_filter_map,
|
||||
clippy::redundant_closure
|
||||
)]
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn main() {
|
||||
let _ = vec![Some(1)].into_iter().filter(Option::is_some);
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
let _ = vec![Some(1)].into_iter().filter(|o| o.is_some());
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
{
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().filter(Option::is_some);
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().filter(|a| a.is_some());
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().filter(|o| { o.is_some() });
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Some(1)].into_iter().filter(|o| { o.is_some() });
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
{
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
.filter(std::option::Option::is_some);
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
.filter(|a| std::option::Option::is_some(a));
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().filter(|a| { std::option::Option::is_some(a) });
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
|
||||
{
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().filter(|&a| a.is_some());
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().filter(|&o| { o.is_some() });
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
|
||||
{
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().filter(|ref a| a.is_some());
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
|
||||
#[rustfmt::skip]
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().filter(|ref o| { o.is_some() });
|
||||
//~^ HELP: consider using `flatten` instead
|
||||
}
|
||||
}
|
||||
|
||||
fn avoid_linting_when_filter_has_side_effects() {
|
||||
// Don't lint below
|
||||
let mut counter = 0;
|
||||
let _ = vec![Some(1)].into_iter().filter(|o| {
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().filter(|o| {
|
||||
counter += 1;
|
||||
o.is_some()
|
||||
});
|
||||
}
|
||||
|
||||
let _ = vec![Some(1)].into_iter().filter(|o| {
|
||||
fn avoid_linting_when_commented() {
|
||||
let _ = vec![Some(1), None, Some(3)].into_iter().filter(|o| {
|
||||
// Roses are red,
|
||||
// Violets are blue,
|
||||
// `Err` is not an `Option`,
|
||||
|
|
@ -25,3 +72,169 @@ fn main() {
|
|||
o.is_some()
|
||||
});
|
||||
}
|
||||
|
||||
fn ice_12058() {
|
||||
// check that checking the parent node doesn't cause an ICE
|
||||
// by indexing the parameters of a closure without parameters
|
||||
Some(1).or_else(|| {
|
||||
vec![Some(1), None, Some(3)].into_iter().filter(|z| *z != Some(2));
|
||||
None
|
||||
});
|
||||
}
|
||||
|
||||
fn avoid_linting_map() {
|
||||
// should not lint
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
.filter(|o| o.is_some())
|
||||
.map(|o| o.unwrap());
|
||||
|
||||
// should not lint
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
.filter(|o| o.is_some())
|
||||
.map(|o| o);
|
||||
}
|
||||
|
||||
fn avoid_false_positive_due_to_is_some_and_iterator_impl() {
|
||||
#[derive(Default, Clone)]
|
||||
struct Foo {}
|
||||
|
||||
impl Foo {
|
||||
fn is_some(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Foo {
|
||||
type Item = Foo;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
Some(Foo::default())
|
||||
}
|
||||
}
|
||||
|
||||
let data = vec![Foo::default()];
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(Foo::is_some);
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(|f| f.is_some());
|
||||
}
|
||||
|
||||
fn avoid_false_positive_due_to_is_some_and_into_iterator_impl() {
|
||||
#[derive(Default, Clone)]
|
||||
struct Foo {}
|
||||
|
||||
impl Foo {
|
||||
fn is_some(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
let data = vec![Foo::default()];
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(Foo::is_some);
|
||||
// should not lint
|
||||
let _ = data.clone().into_iter().filter(|f| f.is_some());
|
||||
}
|
||||
|
||||
fn avoid_unpack_fp() {
|
||||
let _ = vec![(Some(1), None), (None, Some(3))]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|(a, _)| a.is_some());
|
||||
let _ = vec![(Some(1), None), (None, Some(3))]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|(a, _)| a.is_some())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let m = HashMap::from([(1, 1)]);
|
||||
let _ = vec![1, 2, 4].into_iter().filter(|a| m.get(a).is_some());
|
||||
// should not lint
|
||||
}
|
||||
|
||||
fn avoid_fp_for_external() {
|
||||
let value = HashMap::from([(1, 1)]);
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| value.get(&1).is_some());
|
||||
|
||||
let value = Option::Some(1);
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| value.is_some());
|
||||
}
|
||||
|
||||
fn avoid_fp_for_trivial() {
|
||||
let value = HashMap::from([(1, 1)]);
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| Some(1).is_some());
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| None::<i32>.is_some());
|
||||
}
|
||||
|
||||
fn avoid_false_positive_due_to_method_name() {
|
||||
fn is_some(x: &Option<i32>) -> bool {
|
||||
x.is_some()
|
||||
}
|
||||
|
||||
vec![Some(1), None, Some(3)].into_iter().filter(is_some);
|
||||
// should not lint
|
||||
}
|
||||
|
||||
fn avoid_fp_due_to_trait_type() {
|
||||
struct Foo {
|
||||
bar: i32,
|
||||
}
|
||||
impl Foo {
|
||||
fn is_some(obj: &Option<i32>) -> bool {
|
||||
obj.is_some()
|
||||
}
|
||||
}
|
||||
vec![Some(1), None, Some(3)].into_iter().filter(Foo::is_some);
|
||||
// should not lint
|
||||
}
|
||||
|
||||
fn avoid_fp_with_call_to_outside_var() {
|
||||
let outside = Some(1);
|
||||
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| outside.is_some());
|
||||
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| Option::is_some(&outside));
|
||||
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| std::option::Option::is_some(&outside));
|
||||
}
|
||||
|
||||
fn avoid_fp_with_call_to_outside_var_mix_match_types() {
|
||||
let outside: Result<i32, ()> = Ok(1);
|
||||
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| outside.is_ok());
|
||||
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| Result::is_ok(&outside));
|
||||
|
||||
let _ = vec![Some(1), None, Some(3)]
|
||||
.into_iter()
|
||||
// should not lint
|
||||
.filter(|o| std::result::Result::is_ok(&outside));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,65 @@
|
|||
error: `filter` for `is_some` on iterator over `Option`
|
||||
--> $DIR/iter_filter_is_some.rs:4:39
|
||||
--> $DIR/iter_filter_is_some.rs:14:58
|
||||
|
|
||||
LL | let _ = vec![Some(1)].into_iter().filter(Option::is_some);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(Option::is_some);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
|
||||
= note: `-D clippy::iter-filter-is-some` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::iter_filter_is_some)]`
|
||||
|
||||
error: `filter` for `is_some` on iterator over `Option`
|
||||
--> $DIR/iter_filter_is_some.rs:6:39
|
||||
--> $DIR/iter_filter_is_some.rs:16:58
|
||||
|
|
||||
LL | let _ = vec![Some(1)].into_iter().filter(|o| o.is_some());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(|a| a.is_some());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_some` on iterator over `Option`
|
||||
--> $DIR/iter_filter_is_some.rs:10:39
|
||||
--> $DIR/iter_filter_is_some.rs:19:58
|
||||
|
|
||||
LL | let _ = vec![Some(1)].into_iter().filter(|o| { o.is_some() });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(|o| { o.is_some() });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: `filter` for `is_some` on iterator over `Option`
|
||||
--> $DIR/iter_filter_is_some.rs:26:14
|
||||
|
|
||||
LL | .filter(std::option::Option::is_some);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_some` on iterator over `Option`
|
||||
--> $DIR/iter_filter_is_some.rs:31:14
|
||||
|
|
||||
LL | .filter(|a| std::option::Option::is_some(a));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_some` on iterator over `Option`
|
||||
--> $DIR/iter_filter_is_some.rs:34:58
|
||||
|
|
||||
LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(|a| { std::option::Option::is_some(a) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_some` on iterator over `Option`
|
||||
--> $DIR/iter_filter_is_some.rs:39:58
|
||||
|
|
||||
LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(|&a| a.is_some());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_some` on iterator over `Option`
|
||||
--> $DIR/iter_filter_is_some.rs:43:58
|
||||
|
|
||||
LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(|&o| { o.is_some() });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_some` on iterator over `Option`
|
||||
--> $DIR/iter_filter_is_some.rs:48:58
|
||||
|
|
||||
LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(|ref a| a.is_some());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: `filter` for `is_some` on iterator over `Option`
|
||||
--> $DIR/iter_filter_is_some.rs:52:58
|
||||
|
|
||||
LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(|ref o| { o.is_some() });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
//@no-rustfix
|
||||
//@aux-build:proc_macros.rs
|
||||
#![warn(clippy::iter_without_into_iter)]
|
||||
extern crate proc_macros;
|
||||
|
||||
pub struct S1;
|
||||
impl S1 {
|
||||
|
|
@ -121,4 +123,33 @@ impl S12 {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Issue12037;
|
||||
macro_rules! generate_impl {
|
||||
() => {
|
||||
impl Issue12037 {
|
||||
fn iter(&self) -> std::slice::Iter<'_, u8> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
generate_impl!();
|
||||
|
||||
proc_macros::external! {
|
||||
pub struct ImplWithForeignSpan;
|
||||
impl ImplWithForeignSpan {
|
||||
fn iter(&self) -> std::slice::Iter<'_, u8> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Allowed;
|
||||
impl Allowed {
|
||||
#[allow(clippy::iter_without_into_iter)]
|
||||
pub fn iter(&self) -> std::slice::Iter<'_, u8> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: `iter` method without an `IntoIterator` impl for `&S1`
|
||||
--> $DIR/iter_without_into_iter.rs:6:5
|
||||
--> $DIR/iter_without_into_iter.rs:8:5
|
||||
|
|
||||
LL | / pub fn iter(&self) -> std::slice::Iter<'_, u8> {
|
||||
LL | |
|
||||
|
|
@ -22,7 +22,7 @@ LL + }
|
|||
|
|
||||
|
||||
error: `iter_mut` method without an `IntoIterator` impl for `&mut S1`
|
||||
--> $DIR/iter_without_into_iter.rs:10:5
|
||||
--> $DIR/iter_without_into_iter.rs:12:5
|
||||
|
|
||||
LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
|
||||
LL | |
|
||||
|
|
@ -43,7 +43,7 @@ LL + }
|
|||
|
|
||||
|
||||
error: `iter` method without an `IntoIterator` impl for `&S3<'a>`
|
||||
--> $DIR/iter_without_into_iter.rs:26:5
|
||||
--> $DIR/iter_without_into_iter.rs:28:5
|
||||
|
|
||||
LL | / pub fn iter(&self) -> std::slice::Iter<'_, u8> {
|
||||
LL | |
|
||||
|
|
@ -64,7 +64,7 @@ LL + }
|
|||
|
|
||||
|
||||
error: `iter_mut` method without an `IntoIterator` impl for `&mut S3<'a>`
|
||||
--> $DIR/iter_without_into_iter.rs:30:5
|
||||
--> $DIR/iter_without_into_iter.rs:32:5
|
||||
|
|
||||
LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
|
||||
LL | |
|
||||
|
|
@ -85,7 +85,7 @@ LL + }
|
|||
|
|
||||
|
||||
error: `iter` method without an `IntoIterator` impl for `&S8<T>`
|
||||
--> $DIR/iter_without_into_iter.rs:67:5
|
||||
--> $DIR/iter_without_into_iter.rs:69:5
|
||||
|
|
||||
LL | / pub fn iter(&self) -> std::slice::Iter<'static, T> {
|
||||
LL | | todo!()
|
||||
|
|
@ -105,7 +105,7 @@ LL + }
|
|||
|
|
||||
|
||||
error: `iter` method without an `IntoIterator` impl for `&S9<T>`
|
||||
--> $DIR/iter_without_into_iter.rs:75:5
|
||||
--> $DIR/iter_without_into_iter.rs:77:5
|
||||
|
|
||||
LL | / pub fn iter(&self) -> std::slice::Iter<'_, T> {
|
||||
LL | |
|
||||
|
|
@ -126,7 +126,7 @@ LL + }
|
|||
|
|
||||
|
||||
error: `iter_mut` method without an `IntoIterator` impl for `&mut S9<T>`
|
||||
--> $DIR/iter_without_into_iter.rs:79:5
|
||||
--> $DIR/iter_without_into_iter.rs:81:5
|
||||
|
|
||||
LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
|
||||
LL | |
|
||||
|
|
@ -146,5 +146,29 @@ LL + }
|
|||
LL + }
|
||||
|
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
error: `iter` method without an `IntoIterator` impl for `&Issue12037`
|
||||
--> $DIR/iter_without_into_iter.rs:130:13
|
||||
|
|
||||
LL | / fn iter(&self) -> std::slice::Iter<'_, u8> {
|
||||
LL | | todo!()
|
||||
LL | | }
|
||||
| |_____________^
|
||||
...
|
||||
LL | generate_impl!();
|
||||
| ---------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `generate_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: consider implementing `IntoIterator` for `&Issue12037`
|
||||
|
|
||||
LL ~
|
||||
LL + impl IntoIterator for &Issue12037 {
|
||||
LL + type IntoIter = std::slice::Iter<'_, u8>;
|
||||
LL + type Item = &u8;
|
||||
LL + fn into_iter(self) -> Self::IntoIter {
|
||||
LL + self.iter()
|
||||
LL + }
|
||||
LL + }
|
||||
|
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,14 @@ fn main() {
|
|||
let _y = 1; // this is fine
|
||||
let _z = ((), 1); // this as well
|
||||
if true {
|
||||
();
|
||||
// do not lint this, since () is explicit
|
||||
let _a = ();
|
||||
let () = dummy();
|
||||
let () = ();
|
||||
() = dummy();
|
||||
() = ();
|
||||
let _a: () = ();
|
||||
let _a: () = dummy();
|
||||
}
|
||||
|
||||
consume_units_with_for_loop(); // should be fine as well
|
||||
|
|
@ -23,6 +30,8 @@ fn main() {
|
|||
let_and_return!(()) // should be fine
|
||||
}
|
||||
|
||||
fn dummy() {}
|
||||
|
||||
// Related to issue #1964
|
||||
fn consume_units_with_for_loop() {
|
||||
// `for_let_unit` lint should not be triggered by consuming them using for loop.
|
||||
|
|
@ -74,40 +83,29 @@ fn _returns_generic() {
|
|||
x.then(|| T::default())
|
||||
}
|
||||
|
||||
let _: () = f(); // Ok
|
||||
let _: () = f(); // Lint.
|
||||
let _: () = f();
|
||||
let x: () = f();
|
||||
|
||||
let _: () = f2(0i32); // Ok
|
||||
let _: () = f2(0i32); // Lint.
|
||||
let _: () = f2(0i32);
|
||||
let x: () = f2(0i32);
|
||||
|
||||
f3(()); // Lint
|
||||
f3(()); // Lint
|
||||
let _: () = f3(());
|
||||
let x: () = f3(());
|
||||
|
||||
// Should lint:
|
||||
// fn f4<T>(mut x: Vec<T>) -> T {
|
||||
// x.pop().unwrap()
|
||||
// }
|
||||
// let _: () = f4(vec![()]);
|
||||
// let x: () = f4(vec![()]);
|
||||
fn f4<T>(mut x: Vec<T>) -> T {
|
||||
x.pop().unwrap()
|
||||
}
|
||||
let _: () = f4(vec![()]);
|
||||
let x: () = f4(vec![()]);
|
||||
|
||||
// Ok
|
||||
let _: () = {
|
||||
let x = 5;
|
||||
f2(x)
|
||||
};
|
||||
|
||||
let _: () = if true { f() } else { f2(0) }; // Ok
|
||||
let _: () = if true { f() } else { f2(0) }; // Lint
|
||||
let _: () = if true { f() } else { f2(0) };
|
||||
let x: () = if true { f() } else { f2(0) };
|
||||
|
||||
// Ok
|
||||
let _: () = match Some(0) {
|
||||
None => f2(1),
|
||||
Some(0) => f(),
|
||||
Some(1) => f2(3),
|
||||
Some(_) => f2('x'),
|
||||
};
|
||||
|
||||
// Lint
|
||||
match Some(0) {
|
||||
None => f2(1),
|
||||
Some(0) => f(),
|
||||
|
|
@ -155,7 +153,7 @@ fn _returns_generic() {
|
|||
{
|
||||
let _: () = x;
|
||||
let _: () = y;
|
||||
z;
|
||||
let _: () = z;
|
||||
let _: () = x1;
|
||||
let _: () = x2;
|
||||
let _: () = opt;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,14 @@ fn main() {
|
|||
let _y = 1; // this is fine
|
||||
let _z = ((), 1); // this as well
|
||||
if true {
|
||||
// do not lint this, since () is explicit
|
||||
let _a = ();
|
||||
let () = dummy();
|
||||
let () = ();
|
||||
() = dummy();
|
||||
() = ();
|
||||
let _a: () = ();
|
||||
let _a: () = dummy();
|
||||
}
|
||||
|
||||
consume_units_with_for_loop(); // should be fine as well
|
||||
|
|
@ -23,6 +30,8 @@ fn main() {
|
|||
let_and_return!(()) // should be fine
|
||||
}
|
||||
|
||||
fn dummy() {}
|
||||
|
||||
// Related to issue #1964
|
||||
fn consume_units_with_for_loop() {
|
||||
// `for_let_unit` lint should not be triggered by consuming them using for loop.
|
||||
|
|
@ -74,41 +83,30 @@ fn _returns_generic() {
|
|||
x.then(|| T::default())
|
||||
}
|
||||
|
||||
let _: () = f(); // Ok
|
||||
let x: () = f(); // Lint.
|
||||
let _: () = f();
|
||||
let x: () = f();
|
||||
|
||||
let _: () = f2(0i32); // Ok
|
||||
let x: () = f2(0i32); // Lint.
|
||||
let _: () = f2(0i32);
|
||||
let x: () = f2(0i32);
|
||||
|
||||
let _: () = f3(()); // Lint
|
||||
let x: () = f3(()); // Lint
|
||||
let _: () = f3(());
|
||||
let x: () = f3(());
|
||||
|
||||
// Should lint:
|
||||
// fn f4<T>(mut x: Vec<T>) -> T {
|
||||
// x.pop().unwrap()
|
||||
// }
|
||||
// let _: () = f4(vec![()]);
|
||||
// let x: () = f4(vec![()]);
|
||||
fn f4<T>(mut x: Vec<T>) -> T {
|
||||
x.pop().unwrap()
|
||||
}
|
||||
let _: () = f4(vec![()]);
|
||||
let x: () = f4(vec![()]);
|
||||
|
||||
// Ok
|
||||
let _: () = {
|
||||
let x = 5;
|
||||
f2(x)
|
||||
};
|
||||
|
||||
let _: () = if true { f() } else { f2(0) }; // Ok
|
||||
let x: () = if true { f() } else { f2(0) }; // Lint
|
||||
let _: () = if true { f() } else { f2(0) };
|
||||
let x: () = if true { f() } else { f2(0) };
|
||||
|
||||
// Ok
|
||||
let _: () = match Some(0) {
|
||||
None => f2(1),
|
||||
Some(0) => f(),
|
||||
Some(1) => f2(3),
|
||||
Some(_) => f2('x'),
|
||||
};
|
||||
|
||||
// Lint
|
||||
let _: () = match Some(0) {
|
||||
let x = match Some(0) {
|
||||
None => f2(1),
|
||||
Some(0) => f(),
|
||||
Some(1) => f2(3),
|
||||
|
|
|
|||
|
|
@ -8,13 +8,7 @@ LL | let _x = println!("x");
|
|||
= help: to override `-D warnings` add `#[allow(clippy::let_unit_value)]`
|
||||
|
||||
error: this let-binding has unit value
|
||||
--> $DIR/let_unit.rs:16:9
|
||||
|
|
||||
LL | let _a = ();
|
||||
| ^^^^^^^^^^^^ help: omit the `let` binding: `();`
|
||||
|
||||
error: this let-binding has unit value
|
||||
--> $DIR/let_unit.rs:51:5
|
||||
--> $DIR/let_unit.rs:60:5
|
||||
|
|
||||
LL | / let _ = v
|
||||
LL | | .into_iter()
|
||||
|
|
@ -37,45 +31,9 @@ LL + .unwrap();
|
|||
|
|
||||
|
||||
error: this let-binding has unit value
|
||||
--> $DIR/let_unit.rs:78:5
|
||||
--> $DIR/let_unit.rs:109:5
|
||||
|
|
||||
LL | let x: () = f(); // Lint.
|
||||
| ^^^^-^^^^^^^^^^^
|
||||
| |
|
||||
| help: use a wild (`_`) binding: `_`
|
||||
|
||||
error: this let-binding has unit value
|
||||
--> $DIR/let_unit.rs:81:5
|
||||
|
|
||||
LL | let x: () = f2(0i32); // Lint.
|
||||
| ^^^^-^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| help: use a wild (`_`) binding: `_`
|
||||
|
||||
error: this let-binding has unit value
|
||||
--> $DIR/let_unit.rs:83:5
|
||||
|
|
||||
LL | let _: () = f3(()); // Lint
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `f3(());`
|
||||
|
||||
error: this let-binding has unit value
|
||||
--> $DIR/let_unit.rs:84:5
|
||||
|
|
||||
LL | let x: () = f3(()); // Lint
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `f3(());`
|
||||
|
||||
error: this let-binding has unit value
|
||||
--> $DIR/let_unit.rs:100:5
|
||||
|
|
||||
LL | let x: () = if true { f() } else { f2(0) }; // Lint
|
||||
| ^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| help: use a wild (`_`) binding: `_`
|
||||
|
||||
error: this let-binding has unit value
|
||||
--> $DIR/let_unit.rs:111:5
|
||||
|
|
||||
LL | / let _: () = match Some(0) {
|
||||
LL | / let x = match Some(0) {
|
||||
LL | | None => f2(1),
|
||||
LL | | Some(0) => f(),
|
||||
LL | | Some(1) => f2(3),
|
||||
|
|
@ -93,11 +51,5 @@ LL + Some(_) => (),
|
|||
LL + };
|
||||
|
|
||||
|
||||
error: this let-binding has unit value
|
||||
--> $DIR/let_unit.rs:158:13
|
||||
|
|
||||
LL | let _: () = z;
|
||||
| ^^^^^^^^^^^^^^ help: omit the `let` binding: `z;`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
|||
51
tests/ui/manual_is_variant_and.fixed
Normal file
51
tests/ui/manual_is_variant_and.fixed
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
//@aux-build:option_helpers.rs
|
||||
#![warn(clippy::manual_is_variant_and)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate option_helpers;
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn option_methods() {
|
||||
let opt = Some(1);
|
||||
|
||||
// Check for `option.map(_).unwrap_or_default()` use.
|
||||
// Single line case.
|
||||
let _ = opt.is_some_and(|x| x > 1);
|
||||
// Multi-line cases.
|
||||
let _ = opt.is_some_and(|x| {
|
||||
x > 1
|
||||
});
|
||||
let _ = opt.is_some_and(|x| x > 1);
|
||||
let _ = opt
|
||||
.is_some_and(|x| x > 1);
|
||||
|
||||
// won't fix because the return type of the closure is not `bool`
|
||||
let _ = opt.map(|x| x + 1).unwrap_or_default();
|
||||
|
||||
let opt2 = Some('a');
|
||||
let _ = opt2.is_some_and(char::is_alphanumeric); // should lint
|
||||
let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn result_methods() {
|
||||
let res: Result<i32, ()> = Ok(1);
|
||||
|
||||
// multi line cases
|
||||
let _ = res.is_ok_and(|x| {
|
||||
x > 1
|
||||
});
|
||||
let _ = res.is_ok_and(|x| x > 1);
|
||||
|
||||
// won't fix because the return type of the closure is not `bool`
|
||||
let _ = res.map(|x| x + 1).unwrap_or_default();
|
||||
|
||||
let res2: Result<char, ()> = Ok('a');
|
||||
let _ = res2.is_ok_and(char::is_alphanumeric); // should lint
|
||||
let _ = opt_map!(res2, |x| x == 'a').unwrap_or_default(); // should not lint
|
||||
}
|
||||
|
||||
fn main() {
|
||||
option_methods();
|
||||
result_methods();
|
||||
}
|
||||
57
tests/ui/manual_is_variant_and.rs
Normal file
57
tests/ui/manual_is_variant_and.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
//@aux-build:option_helpers.rs
|
||||
#![warn(clippy::manual_is_variant_and)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate option_helpers;
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn option_methods() {
|
||||
let opt = Some(1);
|
||||
|
||||
// Check for `option.map(_).unwrap_or_default()` use.
|
||||
// Single line case.
|
||||
let _ = opt.map(|x| x > 1)
|
||||
// Should lint even though this call is on a separate line.
|
||||
.unwrap_or_default();
|
||||
// Multi-line cases.
|
||||
let _ = opt.map(|x| {
|
||||
x > 1
|
||||
}
|
||||
).unwrap_or_default();
|
||||
let _ = opt.map(|x| x > 1).unwrap_or_default();
|
||||
let _ = opt
|
||||
.map(|x| x > 1)
|
||||
.unwrap_or_default();
|
||||
|
||||
// won't fix because the return type of the closure is not `bool`
|
||||
let _ = opt.map(|x| x + 1).unwrap_or_default();
|
||||
|
||||
let opt2 = Some('a');
|
||||
let _ = opt2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
|
||||
let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn result_methods() {
|
||||
let res: Result<i32, ()> = Ok(1);
|
||||
|
||||
// multi line cases
|
||||
let _ = res.map(|x| {
|
||||
x > 1
|
||||
}
|
||||
).unwrap_or_default();
|
||||
let _ = res.map(|x| x > 1)
|
||||
.unwrap_or_default();
|
||||
|
||||
// won't fix because the return type of the closure is not `bool`
|
||||
let _ = res.map(|x| x + 1).unwrap_or_default();
|
||||
|
||||
let res2: Result<char, ()> = Ok('a');
|
||||
let _ = res2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
|
||||
let _ = opt_map!(res2, |x| x == 'a').unwrap_or_default(); // should not lint
|
||||
}
|
||||
|
||||
fn main() {
|
||||
option_methods();
|
||||
result_methods();
|
||||
}
|
||||
82
tests/ui/manual_is_variant_and.stderr
Normal file
82
tests/ui/manual_is_variant_and.stderr
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
error: called `map(<f>).unwrap_or_default()` on an `Option` value
|
||||
--> $DIR/manual_is_variant_and.rs:13:17
|
||||
|
|
||||
LL | let _ = opt.map(|x| x > 1)
|
||||
| _________________^
|
||||
LL | | // Should lint even though this call is on a separate line.
|
||||
LL | | .unwrap_or_default();
|
||||
| |____________________________^ help: use: `is_some_and(|x| x > 1)`
|
||||
|
|
||||
= note: `-D clippy::manual-is-variant-and` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::manual_is_variant_and)]`
|
||||
|
||||
error: called `map(<f>).unwrap_or_default()` on an `Option` value
|
||||
--> $DIR/manual_is_variant_and.rs:17:17
|
||||
|
|
||||
LL | let _ = opt.map(|x| {
|
||||
| _________________^
|
||||
LL | | x > 1
|
||||
LL | | }
|
||||
LL | | ).unwrap_or_default();
|
||||
| |_________________________^
|
||||
|
|
||||
help: use
|
||||
|
|
||||
LL ~ let _ = opt.is_some_and(|x| {
|
||||
LL + x > 1
|
||||
LL ~ });
|
||||
|
|
||||
|
||||
error: called `map(<f>).unwrap_or_default()` on an `Option` value
|
||||
--> $DIR/manual_is_variant_and.rs:21:17
|
||||
|
|
||||
LL | let _ = opt.map(|x| x > 1).unwrap_or_default();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_some_and(|x| x > 1)`
|
||||
|
||||
error: called `map(<f>).unwrap_or_default()` on an `Option` value
|
||||
--> $DIR/manual_is_variant_and.rs:23:10
|
||||
|
|
||||
LL | .map(|x| x > 1)
|
||||
| __________^
|
||||
LL | | .unwrap_or_default();
|
||||
| |____________________________^ help: use: `is_some_and(|x| x > 1)`
|
||||
|
||||
error: called `map(<f>).unwrap_or_default()` on an `Option` value
|
||||
--> $DIR/manual_is_variant_and.rs:30:18
|
||||
|
|
||||
LL | let _ = opt2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_some_and(char::is_alphanumeric)`
|
||||
|
||||
error: called `map(<f>).unwrap_or_default()` on a `Result` value
|
||||
--> $DIR/manual_is_variant_and.rs:39:17
|
||||
|
|
||||
LL | let _ = res.map(|x| {
|
||||
| _________________^
|
||||
LL | | x > 1
|
||||
LL | | }
|
||||
LL | | ).unwrap_or_default();
|
||||
| |_________________________^
|
||||
|
|
||||
help: use
|
||||
|
|
||||
LL ~ let _ = res.is_ok_and(|x| {
|
||||
LL + x > 1
|
||||
LL ~ });
|
||||
|
|
||||
|
||||
error: called `map(<f>).unwrap_or_default()` on a `Result` value
|
||||
--> $DIR/manual_is_variant_and.rs:43:17
|
||||
|
|
||||
LL | let _ = res.map(|x| x > 1)
|
||||
| _________________^
|
||||
LL | | .unwrap_or_default();
|
||||
| |____________________________^ help: use: `is_ok_and(|x| x > 1)`
|
||||
|
||||
error: called `map(<f>).unwrap_or_default()` on a `Result` value
|
||||
--> $DIR/manual_is_variant_and.rs:50:18
|
||||
|
|
||||
LL | let _ = res2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_ok_and(char::is_alphanumeric)`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
|
@ -4,6 +4,8 @@
|
|||
clippy::iter_cloned_collect,
|
||||
clippy::many_single_char_names,
|
||||
clippy::redundant_clone,
|
||||
clippy::redundant_closure,
|
||||
clippy::useless_asref,
|
||||
clippy::useless_vec
|
||||
)]
|
||||
|
||||
|
|
@ -60,4 +62,26 @@ fn main() {
|
|||
|
||||
let _ = Some(RefCell::new(String::new()).borrow()).map(|s| s.clone());
|
||||
}
|
||||
|
||||
let x = Some(String::new());
|
||||
let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint.
|
||||
let y = x.cloned();
|
||||
//~^ ERROR: you are explicitly cloning with `.map()`
|
||||
let y = x.cloned();
|
||||
//~^ ERROR: you are explicitly cloning with `.map()`
|
||||
let y = x.cloned();
|
||||
//~^ ERROR: you are explicitly cloning with `.map()`
|
||||
|
||||
// Testing with `Result` now.
|
||||
let x: Result<String, ()> = Ok(String::new());
|
||||
let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint.
|
||||
let y = x.cloned();
|
||||
//~^ ERROR: you are explicitly cloning with `.map()`
|
||||
let y = x.cloned();
|
||||
|
||||
// We ensure that no warning is emitted here because `useless_asref` is taking over.
|
||||
let x = Some(String::new());
|
||||
let y = x.as_ref().map(|x| String::clone(x));
|
||||
let x: Result<String, ()> = Ok(String::new());
|
||||
let y = x.as_ref().map(|x| String::clone(x));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
clippy::iter_cloned_collect,
|
||||
clippy::many_single_char_names,
|
||||
clippy::redundant_clone,
|
||||
clippy::redundant_closure,
|
||||
clippy::useless_asref,
|
||||
clippy::useless_vec
|
||||
)]
|
||||
|
||||
|
|
@ -60,4 +62,26 @@ fn main() {
|
|||
|
||||
let _ = Some(RefCell::new(String::new()).borrow()).map(|s| s.clone());
|
||||
}
|
||||
|
||||
let x = Some(String::new());
|
||||
let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint.
|
||||
let y = x.map(|x| String::clone(x));
|
||||
//~^ ERROR: you are explicitly cloning with `.map()`
|
||||
let y = x.map(Clone::clone);
|
||||
//~^ ERROR: you are explicitly cloning with `.map()`
|
||||
let y = x.map(String::clone);
|
||||
//~^ ERROR: you are explicitly cloning with `.map()`
|
||||
|
||||
// Testing with `Result` now.
|
||||
let x: Result<String, ()> = Ok(String::new());
|
||||
let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint.
|
||||
let y = x.map(|x| String::clone(x));
|
||||
//~^ ERROR: you are explicitly cloning with `.map()`
|
||||
let y = x.map(|x| String::clone(x));
|
||||
|
||||
// We ensure that no warning is emitted here because `useless_asref` is taking over.
|
||||
let x = Some(String::new());
|
||||
let y = x.as_ref().map(|x| String::clone(x));
|
||||
let x: Result<String, ()> = Ok(String::new());
|
||||
let y = x.as_ref().map(|x| String::clone(x));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: you are using an explicit closure for copying elements
|
||||
--> $DIR/map_clone.rs:11:22
|
||||
--> $DIR/map_clone.rs:13:22
|
||||
|
|
||||
LL | let _: Vec<i8> = vec![5_i8; 6].iter().map(|x| *x).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![5_i8; 6].iter().copied()`
|
||||
|
|
@ -8,34 +8,64 @@ LL | let _: Vec<i8> = vec![5_i8; 6].iter().map(|x| *x).collect();
|
|||
= help: to override `-D warnings` add `#[allow(clippy::map_clone)]`
|
||||
|
||||
error: you are using an explicit closure for cloning elements
|
||||
--> $DIR/map_clone.rs:12:26
|
||||
--> $DIR/map_clone.rs:14:26
|
||||
|
|
||||
LL | let _: Vec<String> = vec![String::new()].iter().map(|x| x.clone()).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()`
|
||||
|
||||
error: you are using an explicit closure for copying elements
|
||||
--> $DIR/map_clone.rs:13:23
|
||||
--> $DIR/map_clone.rs:15:23
|
||||
|
|
||||
LL | let _: Vec<u32> = vec![42, 43].iter().map(|&x| x).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![42, 43].iter().copied()`
|
||||
|
||||
error: you are using an explicit closure for copying elements
|
||||
--> $DIR/map_clone.rs:15:26
|
||||
--> $DIR/map_clone.rs:17:26
|
||||
|
|
||||
LL | let _: Option<u64> = Some(&16).map(|b| *b);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&16).copied()`
|
||||
|
||||
error: you are using an explicit closure for copying elements
|
||||
--> $DIR/map_clone.rs:16:25
|
||||
--> $DIR/map_clone.rs:18:25
|
||||
|
|
||||
LL | let _: Option<u8> = Some(&1).map(|x| x.clone());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&1).copied()`
|
||||
|
||||
error: you are needlessly cloning iterator elements
|
||||
--> $DIR/map_clone.rs:27:29
|
||||
--> $DIR/map_clone.rs:29:29
|
||||
|
|
||||
LL | let _ = std::env::args().map(|v| v.clone());
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: remove the `map` call
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: you are explicitly cloning with `.map()`
|
||||
--> $DIR/map_clone.rs:68:13
|
||||
|
|
||||
LL | let y = x.map(|x| String::clone(x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
|
||||
|
||||
error: you are explicitly cloning with `.map()`
|
||||
--> $DIR/map_clone.rs:70:13
|
||||
|
|
||||
LL | let y = x.map(Clone::clone);
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
|
||||
|
||||
error: you are explicitly cloning with `.map()`
|
||||
--> $DIR/map_clone.rs:72:13
|
||||
|
|
||||
LL | let y = x.map(String::clone);
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
|
||||
|
||||
error: you are explicitly cloning with `.map()`
|
||||
--> $DIR/map_clone.rs:78:13
|
||||
|
|
||||
LL | let y = x.map(|x| String::clone(x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
|
||||
|
||||
error: you are explicitly cloning with `.map()`
|
||||
--> $DIR/map_clone.rs:80:13
|
||||
|
|
||||
LL | let y = x.map(|x| String::clone(x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
#![feature(never_type)]
|
||||
#![allow(
|
||||
unused_mut,
|
||||
clippy::redundant_allocation,
|
||||
clippy::needless_pass_by_ref_mut
|
||||
)]
|
||||
#![allow(unused_mut, clippy::redundant_allocation, clippy::needless_pass_by_ref_mut)]
|
||||
#![warn(clippy::must_use_candidate)]
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
#![feature(never_type)]
|
||||
#![allow(
|
||||
unused_mut,
|
||||
clippy::redundant_allocation,
|
||||
clippy::needless_pass_by_ref_mut
|
||||
)]
|
||||
#![allow(unused_mut, clippy::redundant_allocation, clippy::needless_pass_by_ref_mut)]
|
||||
#![warn(clippy::must_use_candidate)]
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: this function could have a `#[must_use]` attribute
|
||||
--> $DIR/must_use_candidates.rs:15:1
|
||||
--> $DIR/must_use_candidates.rs:11:1
|
||||
|
|
||||
LL | pub fn pure(i: u8) -> u8 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn pure(i: u8) -> u8`
|
||||
|
|
@ -8,25 +8,25 @@ LL | pub fn pure(i: u8) -> u8 {
|
|||
= help: to override `-D warnings` add `#[allow(clippy::must_use_candidate)]`
|
||||
|
||||
error: this method could have a `#[must_use]` attribute
|
||||
--> $DIR/must_use_candidates.rs:20:5
|
||||
--> $DIR/must_use_candidates.rs:16:5
|
||||
|
|
||||
LL | pub fn inherent_pure(&self) -> u8 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn inherent_pure(&self) -> u8`
|
||||
|
||||
error: this function could have a `#[must_use]` attribute
|
||||
--> $DIR/must_use_candidates.rs:51:1
|
||||
--> $DIR/must_use_candidates.rs:47:1
|
||||
|
|
||||
LL | pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool`
|
||||
|
||||
error: this function could have a `#[must_use]` attribute
|
||||
--> $DIR/must_use_candidates.rs:63:1
|
||||
--> $DIR/must_use_candidates.rs:59:1
|
||||
|
|
||||
LL | pub fn rcd(_x: Rc<u32>) -> bool {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn rcd(_x: Rc<u32>) -> bool`
|
||||
|
||||
error: this function could have a `#[must_use]` attribute
|
||||
--> $DIR/must_use_candidates.rs:71:1
|
||||
--> $DIR/must_use_candidates.rs:67:1
|
||||
|
|
||||
LL | pub fn arcd(_x: Arc<u32>) -> bool {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn arcd(_x: Arc<u32>) -> bool`
|
||||
|
|
|
|||
|
|
@ -18,9 +18,24 @@ fn main() {
|
|||
Mutex::new(&mut x as *mut u32);
|
||||
//~^ ERROR: consider using an `AtomicPtr` instead of a `Mutex` here; if you just want
|
||||
Mutex::new(0u32);
|
||||
//~^ ERROR: consider using an `AtomicUsize` instead of a `Mutex` here; if you just wan
|
||||
//~^ ERROR: consider using an `AtomicU32` instead of a `Mutex` here; if you just wan
|
||||
//~| NOTE: `-D clippy::mutex-integer` implied by `-D warnings`
|
||||
Mutex::new(0i32);
|
||||
//~^ ERROR: consider using an `AtomicIsize` instead of a `Mutex` here; if you just wan
|
||||
//~^ ERROR: consider using an `AtomicI32` instead of a `Mutex` here; if you just wan
|
||||
Mutex::new(0f32); // there are no float atomics, so this should not lint
|
||||
Mutex::new(0u8);
|
||||
//~^ ERROR: consider using an `AtomicU8` instead of a `Mutex` here; if you just wan
|
||||
Mutex::new(0i16);
|
||||
//~^ ERROR: consider using an `AtomicI16` instead of a `Mutex` here; if you just wan
|
||||
let _x: Mutex<i8> = Mutex::new(0);
|
||||
//~^ ERROR: consider using an `AtomicI8` instead of a `Mutex` here; if you just wan
|
||||
const X: i64 = 0;
|
||||
Mutex::new(X);
|
||||
//~^ ERROR: consider using an `AtomicI64` instead of a `Mutex` here; if you just wan
|
||||
|
||||
// there are no 128 atomics, so these two should not lint
|
||||
{
|
||||
Mutex::new(0u128);
|
||||
let _x: Mutex<i128> = Mutex::new(0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ error: consider using an `AtomicPtr` instead of a `Mutex` here; if you just want
|
|||
LL | Mutex::new(&mut x as *mut u32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: consider using an `AtomicUsize` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
|
||||
error: consider using an `AtomicU32` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
|
||||
--> $DIR/mutex_atomic.rs:20:5
|
||||
|
|
||||
LL | Mutex::new(0u32);
|
||||
|
|
@ -40,11 +40,35 @@ LL | Mutex::new(0u32);
|
|||
= note: `-D clippy::mutex-integer` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::mutex_integer)]`
|
||||
|
||||
error: consider using an `AtomicIsize` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
|
||||
error: consider using an `AtomicI32` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
|
||||
--> $DIR/mutex_atomic.rs:23:5
|
||||
|
|
||||
LL | Mutex::new(0i32);
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
error: consider using an `AtomicU8` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
|
||||
--> $DIR/mutex_atomic.rs:26:5
|
||||
|
|
||||
LL | Mutex::new(0u8);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: consider using an `AtomicI16` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
|
||||
--> $DIR/mutex_atomic.rs:28:5
|
||||
|
|
||||
LL | Mutex::new(0i16);
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: consider using an `AtomicI8` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
|
||||
--> $DIR/mutex_atomic.rs:30:25
|
||||
|
|
||||
LL | let _x: Mutex<i8> = Mutex::new(0);
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: consider using an `AtomicI64` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
|
||||
--> $DIR/mutex_atomic.rs:33:5
|
||||
|
|
||||
LL | Mutex::new(X);
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
/// unimplemented!();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// With an explicit return type it should lint too
|
||||
/// ```edition2015
|
||||
/// fn main() -> () {
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
/// unimplemented!();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// This should, too.
|
||||
/// ```rust
|
||||
/// fn main() {
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
/// unimplemented!();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// This one too.
|
||||
/// ```no_run
|
||||
/// // the fn is not always the first line
|
||||
|
|
|
|||
|
|
@ -25,9 +25,13 @@ fn main() {
|
|||
|
||||
permissions.set_mode(0o644);
|
||||
permissions.set_mode(0o704);
|
||||
// no error
|
||||
permissions.set_mode(0b111_000_100);
|
||||
|
||||
// DirBuilderExt::mode
|
||||
let mut builder = DirBuilder::new();
|
||||
builder.mode(0o755);
|
||||
builder.mode(0o406);
|
||||
// no error
|
||||
permissions.set_mode(0b111000100);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,9 +25,13 @@ fn main() {
|
|||
|
||||
permissions.set_mode(644);
|
||||
permissions.set_mode(0o704);
|
||||
// no error
|
||||
permissions.set_mode(0b111_000_100);
|
||||
|
||||
// DirBuilderExt::mode
|
||||
let mut builder = DirBuilder::new();
|
||||
builder.mode(755);
|
||||
builder.mode(0o406);
|
||||
// no error
|
||||
permissions.set_mode(0b111000100);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ LL | permissions.set_mode(644);
|
|||
| ^^^ help: consider using an octal literal instead: `0o644`
|
||||
|
||||
error: using a non-octal value to set unix file permissions
|
||||
--> $DIR/non_octal_unix_permissions.rs:31:18
|
||||
--> $DIR/non_octal_unix_permissions.rs:33:18
|
||||
|
|
||||
LL | builder.mode(755);
|
||||
| ^^^ help: consider using an octal literal instead: `0o755`
|
||||
|
|
|
|||
21
tests/ui/option_as_ref_cloned.fixed
Normal file
21
tests/ui/option_as_ref_cloned.fixed
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#![warn(clippy::option_as_ref_cloned)]
|
||||
#![allow(clippy::clone_on_copy)]
|
||||
|
||||
fn main() {
|
||||
let mut x = Some(String::new());
|
||||
|
||||
let _: Option<String> = x.clone();
|
||||
let _: Option<String> = x.clone();
|
||||
|
||||
let y = x.as_ref();
|
||||
let _: Option<&String> = y.clone();
|
||||
|
||||
macro_rules! cloned_recv {
|
||||
() => {
|
||||
x.as_ref()
|
||||
};
|
||||
}
|
||||
|
||||
// Don't lint when part of the expression is from a macro
|
||||
let _: Option<String> = cloned_recv!().cloned();
|
||||
}
|
||||
21
tests/ui/option_as_ref_cloned.rs
Normal file
21
tests/ui/option_as_ref_cloned.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#![warn(clippy::option_as_ref_cloned)]
|
||||
#![allow(clippy::clone_on_copy)]
|
||||
|
||||
fn main() {
|
||||
let mut x = Some(String::new());
|
||||
|
||||
let _: Option<String> = x.as_ref().cloned();
|
||||
let _: Option<String> = x.as_mut().cloned();
|
||||
|
||||
let y = x.as_ref();
|
||||
let _: Option<&String> = y.as_ref().cloned();
|
||||
|
||||
macro_rules! cloned_recv {
|
||||
() => {
|
||||
x.as_ref()
|
||||
};
|
||||
}
|
||||
|
||||
// Don't lint when part of the expression is from a macro
|
||||
let _: Option<String> = cloned_recv!().cloned();
|
||||
}
|
||||
37
tests/ui/option_as_ref_cloned.stderr
Normal file
37
tests/ui/option_as_ref_cloned.stderr
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
error: cloning an `Option<_>` using `.as_ref().cloned()`
|
||||
--> $DIR/option_as_ref_cloned.rs:7:31
|
||||
|
|
||||
LL | let _: Option<String> = x.as_ref().cloned();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::option-as-ref-cloned` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::option_as_ref_cloned)]`
|
||||
help: this can be written more concisely by cloning the `Option<_>` directly
|
||||
|
|
||||
LL | let _: Option<String> = x.clone();
|
||||
| ~~~~~
|
||||
|
||||
error: cloning an `Option<_>` using `.as_mut().cloned()`
|
||||
--> $DIR/option_as_ref_cloned.rs:8:31
|
||||
|
|
||||
LL | let _: Option<String> = x.as_mut().cloned();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: this can be written more concisely by cloning the `Option<_>` directly
|
||||
|
|
||||
LL | let _: Option<String> = x.clone();
|
||||
| ~~~~~
|
||||
|
||||
error: cloning an `Option<_>` using `.as_ref().cloned()`
|
||||
--> $DIR/option_as_ref_cloned.rs:11:32
|
||||
|
|
||||
LL | let _: Option<&String> = y.as_ref().cloned();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: this can be written more concisely by cloning the `Option<_>` directly
|
||||
|
|
||||
LL | let _: Option<&String> = y.clone();
|
||||
| ~~~~~
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ fn main() {
|
|||
let _no_as_str = string.as_bytes();
|
||||
let _no_as_str = string.is_empty();
|
||||
|
||||
// These methods are not redundant, and are equivelant to
|
||||
// These methods are not redundant, and are equivalent to
|
||||
// doing dereferencing the string and applying the method
|
||||
let _not_redundant = string.as_str().escape_unicode();
|
||||
let _not_redundant = string.as_str().trim();
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ fn main() {
|
|||
let _no_as_str = string.as_bytes();
|
||||
let _no_as_str = string.is_empty();
|
||||
|
||||
// These methods are not redundant, and are equivelant to
|
||||
// These methods are not redundant, and are equivalent to
|
||||
// doing dereferencing the string and applying the method
|
||||
let _not_redundant = string.as_str().escape_unicode();
|
||||
let _not_redundant = string.as_str().trim();
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ fn trivial_regex() {
|
|||
// #6005: unicode classes in bytes::Regex
|
||||
let a_byte_of_unicode = BRegex::new(r"\p{C}");
|
||||
|
||||
// start and end word boundry, introduced in regex 0.10
|
||||
// start and end word boundary, introduced in regex 0.10
|
||||
let _ = BRegex::new(r"\<word\>");
|
||||
let _ = BRegex::new(r"\b{start}word\b{end}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ fn main() {
|
|||
x.split('\n');
|
||||
x.split('\'');
|
||||
x.split('\'');
|
||||
// Issue #11973: Don't escape `"` in `'"'`
|
||||
x.split('"');
|
||||
|
||||
let h = HashSet::<String>::new();
|
||||
h.contains("X"); // should not warn
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ fn main() {
|
|||
x.split("\n");
|
||||
x.split("'");
|
||||
x.split("\'");
|
||||
// Issue #11973: Don't escape `"` in `'"'`
|
||||
x.split("\"");
|
||||
|
||||
let h = HashSet::<String>::new();
|
||||
h.contains("X"); // should not warn
|
||||
|
|
|
|||
|
|
@ -182,58 +182,64 @@ LL | x.split("\'");
|
|||
| ^^^^ help: try using a `char` instead: `'\''`
|
||||
|
||||
error: single-character string constant used as pattern
|
||||
--> $DIR/single_char_pattern.rs:49:31
|
||||
--> $DIR/single_char_pattern.rs:46:13
|
||||
|
|
||||
LL | x.split("\"");
|
||||
| ^^^^ help: try using a `char` instead: `'"'`
|
||||
|
||||
error: single-character string constant used as pattern
|
||||
--> $DIR/single_char_pattern.rs:51:31
|
||||
|
|
||||
LL | x.replace(';', ",").split(","); // issue #2978
|
||||
| ^^^ help: try using a `char` instead: `','`
|
||||
|
||||
error: single-character string constant used as pattern
|
||||
--> $DIR/single_char_pattern.rs:50:19
|
||||
--> $DIR/single_char_pattern.rs:52:19
|
||||
|
|
||||
LL | x.starts_with("\x03"); // issue #2996
|
||||
| ^^^^^^ help: try using a `char` instead: `'\x03'`
|
||||
|
||||
error: single-character string constant used as pattern
|
||||
--> $DIR/single_char_pattern.rs:57:13
|
||||
--> $DIR/single_char_pattern.rs:59:13
|
||||
|
|
||||
LL | x.split(r"a");
|
||||
| ^^^^ help: try using a `char` instead: `'a'`
|
||||
|
||||
error: single-character string constant used as pattern
|
||||
--> $DIR/single_char_pattern.rs:58:13
|
||||
--> $DIR/single_char_pattern.rs:60:13
|
||||
|
|
||||
LL | x.split(r#"a"#);
|
||||
| ^^^^^^ help: try using a `char` instead: `'a'`
|
||||
|
||||
error: single-character string constant used as pattern
|
||||
--> $DIR/single_char_pattern.rs:59:13
|
||||
--> $DIR/single_char_pattern.rs:61:13
|
||||
|
|
||||
LL | x.split(r###"a"###);
|
||||
| ^^^^^^^^^^ help: try using a `char` instead: `'a'`
|
||||
|
||||
error: single-character string constant used as pattern
|
||||
--> $DIR/single_char_pattern.rs:60:13
|
||||
--> $DIR/single_char_pattern.rs:62:13
|
||||
|
|
||||
LL | x.split(r###"'"###);
|
||||
| ^^^^^^^^^^ help: try using a `char` instead: `'\''`
|
||||
|
||||
error: single-character string constant used as pattern
|
||||
--> $DIR/single_char_pattern.rs:61:13
|
||||
--> $DIR/single_char_pattern.rs:63:13
|
||||
|
|
||||
LL | x.split(r###"#"###);
|
||||
| ^^^^^^^^^^ help: try using a `char` instead: `'#'`
|
||||
|
||||
error: single-character string constant used as pattern
|
||||
--> $DIR/single_char_pattern.rs:63:13
|
||||
--> $DIR/single_char_pattern.rs:65:13
|
||||
|
|
||||
LL | x.split(r#"\"#);
|
||||
| ^^^^^^ help: try using a `char` instead: `'\\'`
|
||||
|
||||
error: single-character string constant used as pattern
|
||||
--> $DIR/single_char_pattern.rs:64:13
|
||||
--> $DIR/single_char_pattern.rs:66:13
|
||||
|
|
||||
LL | x.split(r"\");
|
||||
| ^^^^ help: try using a `char` instead: `'\\'`
|
||||
|
||||
error: aborting due to 39 previous errors
|
||||
error: aborting due to 40 previous errors
|
||||
|
||||
|
|
|
|||
145
tests/ui/str_split.fixed
Normal file
145
tests/ui/str_split.fixed
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
#![warn(clippy::str_split_at_newline)]
|
||||
|
||||
use core::str::Split;
|
||||
use std::ops::Deref;
|
||||
|
||||
struct NotStr<'a> {
|
||||
s: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> NotStr<'a> {
|
||||
fn trim(&'a self) -> &'a str {
|
||||
self.s
|
||||
}
|
||||
}
|
||||
|
||||
struct DerefsIntoNotStr<'a> {
|
||||
not_str: &'a NotStr<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Deref for DerefsIntoNotStr<'a> {
|
||||
type Target = NotStr<'a>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.not_str
|
||||
}
|
||||
}
|
||||
|
||||
struct DerefsIntoStr<'a> {
|
||||
s: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> Deref for DerefsIntoStr<'a> {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.s
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! trim_split {
|
||||
( $x:expr, $y:expr ) => {
|
||||
$x.trim().split($y);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! make_str {
|
||||
( $x: expr ) => {
|
||||
format!("x={}", $x)
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s1 = "hello\nworld\n";
|
||||
let s2 = s1.to_owned();
|
||||
|
||||
// CASES THAT SHOULD EMIT A LINT
|
||||
|
||||
// Splitting a `str` variable at "\n" or "\r\n" after trimming should warn
|
||||
let _ = s1.lines();
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s1.lines();
|
||||
let _ = s1.lines();
|
||||
|
||||
// Splitting a `String` variable at "\n" or "\r\n" after trimming should warn
|
||||
let _ = s2.lines();
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s2.lines();
|
||||
let _ = s2.lines();
|
||||
|
||||
// Splitting a variable that derefs into `str` at "\n" or "\r\n" after trimming should warn.
|
||||
let s3 = DerefsIntoStr { s: s1 };
|
||||
let _ = s3.lines();
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s3.lines();
|
||||
let _ = s3.lines();
|
||||
|
||||
// If the `&str` is generated by a macro then the macro should not be expanded in the suggested fix.
|
||||
let _ = make_str!(s1).lines();
|
||||
|
||||
// CASES THAT SHOULD NOT EMIT A LINT
|
||||
|
||||
// Splitting a `str` constant at "\n" or "\r\n" after trimming should not warn
|
||||
let _ = "hello\nworld\n".trim().split('\n');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = "hello\nworld\n".trim().split("\n");
|
||||
let _ = "hello\nworld\n".trim().split("\r\n");
|
||||
|
||||
// Splitting a `str` variable at "\n" or "\r\n" without trimming should not warn, since it is not
|
||||
// equivalent
|
||||
let _ = s1.split('\n');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s1.split("\n");
|
||||
let _ = s1.split("\r\n");
|
||||
|
||||
// Splitting a `String` variable at "\n" or "\r\n" without trimming should not warn.
|
||||
let _ = s2.split('\n');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s2.split("\n");
|
||||
|
||||
// Splitting a variable that derefs into `str` at "\n" or "\r\n" without trimming should not warn.
|
||||
let _ = s3.split('\n');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s3.split("\n");
|
||||
let _ = s3.split("\r\n");
|
||||
let _ = s2.split("\r\n");
|
||||
|
||||
// Splitting a `str` variable at other separators should not warn
|
||||
let _ = s1.trim().split('\r');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s1.trim().split("\r");
|
||||
let _ = s1.trim().split("\n\r");
|
||||
let _ = s1.trim().split("\r \n");
|
||||
|
||||
// Splitting a `String` variable at other separators should not warn
|
||||
let _ = s2.trim().split('\r');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s2.trim().split("\r");
|
||||
let _ = s2.trim().split("\n\r");
|
||||
|
||||
// Splitting a variable that derefs into `str` at other separators should not warn
|
||||
let _ = s3.trim().split('\r');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s3.trim().split("\r");
|
||||
let _ = s3.trim().split("\n\r");
|
||||
let _ = s3.trim().split("\r \n");
|
||||
let _ = s2.trim().split("\r \n");
|
||||
|
||||
// Using `trim` and `split` on other types should not warn
|
||||
let not_str = NotStr { s: s1 };
|
||||
let _ = not_str.trim().split('\n');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = not_str.trim().split("\n");
|
||||
let _ = not_str.trim().split("\r\n");
|
||||
let derefs_into_not_str = DerefsIntoNotStr { not_str: ¬_str };
|
||||
let _ = derefs_into_not_str.trim().split('\n');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = derefs_into_not_str.trim().split("\n");
|
||||
let _ = derefs_into_not_str.trim().split("\r\n");
|
||||
|
||||
// Code generated by macros should not create a warning
|
||||
trim_split!(s1, "\r\n");
|
||||
trim_split!("hello\nworld\n", "\r\n");
|
||||
trim_split!(s2, "\r\n");
|
||||
trim_split!(s3, "\r\n");
|
||||
}
|
||||
145
tests/ui/str_split.rs
Normal file
145
tests/ui/str_split.rs
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
#![warn(clippy::str_split_at_newline)]
|
||||
|
||||
use core::str::Split;
|
||||
use std::ops::Deref;
|
||||
|
||||
struct NotStr<'a> {
|
||||
s: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> NotStr<'a> {
|
||||
fn trim(&'a self) -> &'a str {
|
||||
self.s
|
||||
}
|
||||
}
|
||||
|
||||
struct DerefsIntoNotStr<'a> {
|
||||
not_str: &'a NotStr<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Deref for DerefsIntoNotStr<'a> {
|
||||
type Target = NotStr<'a>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.not_str
|
||||
}
|
||||
}
|
||||
|
||||
struct DerefsIntoStr<'a> {
|
||||
s: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> Deref for DerefsIntoStr<'a> {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.s
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! trim_split {
|
||||
( $x:expr, $y:expr ) => {
|
||||
$x.trim().split($y);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! make_str {
|
||||
( $x: expr ) => {
|
||||
format!("x={}", $x)
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s1 = "hello\nworld\n";
|
||||
let s2 = s1.to_owned();
|
||||
|
||||
// CASES THAT SHOULD EMIT A LINT
|
||||
|
||||
// Splitting a `str` variable at "\n" or "\r\n" after trimming should warn
|
||||
let _ = s1.trim().split('\n');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s1.trim().split("\n");
|
||||
let _ = s1.trim().split("\r\n");
|
||||
|
||||
// Splitting a `String` variable at "\n" or "\r\n" after trimming should warn
|
||||
let _ = s2.trim().split('\n');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s2.trim().split("\n");
|
||||
let _ = s2.trim().split("\r\n");
|
||||
|
||||
// Splitting a variable that derefs into `str` at "\n" or "\r\n" after trimming should warn.
|
||||
let s3 = DerefsIntoStr { s: s1 };
|
||||
let _ = s3.trim().split('\n');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s3.trim().split("\n");
|
||||
let _ = s3.trim().split("\r\n");
|
||||
|
||||
// If the `&str` is generated by a macro then the macro should not be expanded in the suggested fix.
|
||||
let _ = make_str!(s1).trim().split('\n');
|
||||
|
||||
// CASES THAT SHOULD NOT EMIT A LINT
|
||||
|
||||
// Splitting a `str` constant at "\n" or "\r\n" after trimming should not warn
|
||||
let _ = "hello\nworld\n".trim().split('\n');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = "hello\nworld\n".trim().split("\n");
|
||||
let _ = "hello\nworld\n".trim().split("\r\n");
|
||||
|
||||
// Splitting a `str` variable at "\n" or "\r\n" without trimming should not warn, since it is not
|
||||
// equivalent
|
||||
let _ = s1.split('\n');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s1.split("\n");
|
||||
let _ = s1.split("\r\n");
|
||||
|
||||
// Splitting a `String` variable at "\n" or "\r\n" without trimming should not warn.
|
||||
let _ = s2.split('\n');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s2.split("\n");
|
||||
|
||||
// Splitting a variable that derefs into `str` at "\n" or "\r\n" without trimming should not warn.
|
||||
let _ = s3.split('\n');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s3.split("\n");
|
||||
let _ = s3.split("\r\n");
|
||||
let _ = s2.split("\r\n");
|
||||
|
||||
// Splitting a `str` variable at other separators should not warn
|
||||
let _ = s1.trim().split('\r');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s1.trim().split("\r");
|
||||
let _ = s1.trim().split("\n\r");
|
||||
let _ = s1.trim().split("\r \n");
|
||||
|
||||
// Splitting a `String` variable at other separators should not warn
|
||||
let _ = s2.trim().split('\r');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s2.trim().split("\r");
|
||||
let _ = s2.trim().split("\n\r");
|
||||
|
||||
// Splitting a variable that derefs into `str` at other separators should not warn
|
||||
let _ = s3.trim().split('\r');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = s3.trim().split("\r");
|
||||
let _ = s3.trim().split("\n\r");
|
||||
let _ = s3.trim().split("\r \n");
|
||||
let _ = s2.trim().split("\r \n");
|
||||
|
||||
// Using `trim` and `split` on other types should not warn
|
||||
let not_str = NotStr { s: s1 };
|
||||
let _ = not_str.trim().split('\n');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = not_str.trim().split("\n");
|
||||
let _ = not_str.trim().split("\r\n");
|
||||
let derefs_into_not_str = DerefsIntoNotStr { not_str: ¬_str };
|
||||
let _ = derefs_into_not_str.trim().split('\n');
|
||||
#[allow(clippy::single_char_pattern)]
|
||||
let _ = derefs_into_not_str.trim().split("\n");
|
||||
let _ = derefs_into_not_str.trim().split("\r\n");
|
||||
|
||||
// Code generated by macros should not create a warning
|
||||
trim_split!(s1, "\r\n");
|
||||
trim_split!("hello\nworld\n", "\r\n");
|
||||
trim_split!(s2, "\r\n");
|
||||
trim_split!(s3, "\r\n");
|
||||
}
|
||||
65
tests/ui/str_split.stderr
Normal file
65
tests/ui/str_split.stderr
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
error: using `str.trim().split()` with hard-coded newlines
|
||||
--> $DIR/str_split.rs:59:13
|
||||
|
|
||||
LL | let _ = s1.trim().split('\n');
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()`
|
||||
|
|
||||
= note: `-D clippy::str-split-at-newline` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::str_split_at_newline)]`
|
||||
|
||||
error: using `str.trim().split()` with hard-coded newlines
|
||||
--> $DIR/str_split.rs:61:13
|
||||
|
|
||||
LL | let _ = s1.trim().split("\n");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()`
|
||||
|
||||
error: using `str.trim().split()` with hard-coded newlines
|
||||
--> $DIR/str_split.rs:62:13
|
||||
|
|
||||
LL | let _ = s1.trim().split("\r\n");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()`
|
||||
|
||||
error: using `str.trim().split()` with hard-coded newlines
|
||||
--> $DIR/str_split.rs:65:13
|
||||
|
|
||||
LL | let _ = s2.trim().split('\n');
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()`
|
||||
|
||||
error: using `str.trim().split()` with hard-coded newlines
|
||||
--> $DIR/str_split.rs:67:13
|
||||
|
|
||||
LL | let _ = s2.trim().split("\n");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()`
|
||||
|
||||
error: using `str.trim().split()` with hard-coded newlines
|
||||
--> $DIR/str_split.rs:68:13
|
||||
|
|
||||
LL | let _ = s2.trim().split("\r\n");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()`
|
||||
|
||||
error: using `str.trim().split()` with hard-coded newlines
|
||||
--> $DIR/str_split.rs:72:13
|
||||
|
|
||||
LL | let _ = s3.trim().split('\n');
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()`
|
||||
|
||||
error: using `str.trim().split()` with hard-coded newlines
|
||||
--> $DIR/str_split.rs:74:13
|
||||
|
|
||||
LL | let _ = s3.trim().split("\n");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()`
|
||||
|
||||
error: using `str.trim().split()` with hard-coded newlines
|
||||
--> $DIR/str_split.rs:75:13
|
||||
|
|
||||
LL | let _ = s3.trim().split("\r\n");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()`
|
||||
|
||||
error: using `str.trim().split()` with hard-coded newlines
|
||||
--> $DIR/str_split.rs:78:13
|
||||
|
|
||||
LL | let _ = make_str!(s1).trim().split('\n');
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `make_str!(s1).lines()`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
|
|
@ -39,14 +39,14 @@ struct DataStruct {
|
|||
struct DoublePrefix {
|
||||
//~^ ERROR: all fields have the same prefix: `some_data`
|
||||
some_data_a: bool,
|
||||
some_data_b: bool,
|
||||
some_data_b: i8,
|
||||
some_data_c: bool,
|
||||
}
|
||||
|
||||
struct DoublePostfix {
|
||||
//~^ ERROR: all fields have the same postfix: `some_data`
|
||||
a_some_data: bool,
|
||||
b_some_data: bool,
|
||||
b_some_data: i8,
|
||||
c_some_data: bool,
|
||||
}
|
||||
|
||||
|
|
@ -54,18 +54,18 @@ struct DoublePostfix {
|
|||
struct NotSnakeCase {
|
||||
//~^ ERROR: all fields have the same postfix: `someData`
|
||||
a_someData: bool,
|
||||
b_someData: bool,
|
||||
b_someData: i8,
|
||||
c_someData: bool,
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
struct NotSnakeCase2 {
|
||||
//~^ ERROR: all fields have the same prefix: `someData`
|
||||
someData_c: bool,
|
||||
someData_b: bool,
|
||||
someData_b: i8,
|
||||
someData_a_b: bool,
|
||||
}
|
||||
|
||||
// no error, threshold is 3 fiels by default
|
||||
// no error, threshold is 3 fields by default
|
||||
struct Fooo {
|
||||
foo: u8,
|
||||
bar: u8,
|
||||
|
|
@ -328,4 +328,18 @@ external! {
|
|||
|
||||
}
|
||||
|
||||
// Should not warn
|
||||
struct Config {
|
||||
use_foo: bool,
|
||||
use_bar: bool,
|
||||
use_baz: bool,
|
||||
}
|
||||
|
||||
struct Use {
|
||||
use_foo: bool,
|
||||
//~^ ERROR: field name starts with the struct's name
|
||||
use_bar: bool,
|
||||
use_baz: bool,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ error: all fields have the same prefix: `some_data`
|
|||
LL | / struct DoublePrefix {
|
||||
LL | |
|
||||
LL | | some_data_a: bool,
|
||||
LL | | some_data_b: bool,
|
||||
LL | | some_data_b: i8,
|
||||
LL | | some_data_c: bool,
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
@ -58,7 +58,7 @@ error: all fields have the same postfix: `some_data`
|
|||
LL | / struct DoublePostfix {
|
||||
LL | |
|
||||
LL | | a_some_data: bool,
|
||||
LL | | b_some_data: bool,
|
||||
LL | | b_some_data: i8,
|
||||
LL | | c_some_data: bool,
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
@ -71,7 +71,7 @@ error: all fields have the same postfix: `someData`
|
|||
LL | / struct NotSnakeCase {
|
||||
LL | |
|
||||
LL | | a_someData: bool,
|
||||
LL | | b_someData: bool,
|
||||
LL | | b_someData: i8,
|
||||
LL | | c_someData: bool,
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
@ -84,7 +84,7 @@ error: all fields have the same prefix: `someData`
|
|||
LL | / struct NotSnakeCase2 {
|
||||
LL | |
|
||||
LL | | someData_c: bool,
|
||||
LL | | someData_b: bool,
|
||||
LL | | someData_b: i8,
|
||||
LL | | someData_a_b: bool,
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
@ -261,5 +261,23 @@ LL | mk_struct_full_def!(PrefixData, some_data, some_meta, some_other);
|
|||
= help: remove the prefixes
|
||||
= note: this error originates in the macro `mk_struct_full_def` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 21 previous errors
|
||||
error: field name starts with the struct's name
|
||||
--> $DIR/struct_fields.rs:339:5
|
||||
|
|
||||
LL | use_foo: bool,
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: field name starts with the struct's name
|
||||
--> $DIR/struct_fields.rs:341:5
|
||||
|
|
||||
LL | use_bar: bool,
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: field name starts with the struct's name
|
||||
--> $DIR/struct_fields.rs:342:5
|
||||
|
|
||||
LL | use_baz: bool,
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 24 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#![warn(clippy::temporary_assignment)]
|
||||
#![allow(const_item_mutation)]
|
||||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: assignment to temporary
|
||||
--> $DIR/temporary_assignment.rs:48:5
|
||||
--> $DIR/temporary_assignment.rs:47:5
|
||||
|
|
||||
LL | Struct { field: 0 }.field = 1;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -8,7 +8,7 @@ LL | Struct { field: 0 }.field = 1;
|
|||
= help: to override `-D warnings` add `#[allow(clippy::temporary_assignment)]`
|
||||
|
||||
error: assignment to temporary
|
||||
--> $DIR/temporary_assignment.rs:51:5
|
||||
--> $DIR/temporary_assignment.rs:50:5
|
||||
|
|
||||
LL | / MultiStruct {
|
||||
LL | |
|
||||
|
|
@ -19,13 +19,13 @@ LL | | .field = 1;
|
|||
| |______________^
|
||||
|
||||
error: assignment to temporary
|
||||
--> $DIR/temporary_assignment.rs:57:5
|
||||
--> $DIR/temporary_assignment.rs:56:5
|
||||
|
|
||||
LL | ArrayStruct { array: [0] }.array[0] = 1;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: assignment to temporary
|
||||
--> $DIR/temporary_assignment.rs:59:5
|
||||
--> $DIR/temporary_assignment.rs:58:5
|
||||
|
|
||||
LL | (0, 0).0 = 1;
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
|
|||
30
tests/ui/thread_local_initializer_can_be_made_const.fixed
Normal file
30
tests/ui/thread_local_initializer_can_be_made_const.fixed
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#![warn(clippy::thread_local_initializer_can_be_made_const)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
fn main() {
|
||||
// lint and suggest const
|
||||
thread_local! {
|
||||
static BUF_1: RefCell<String> = const { RefCell::new(String::new()) };
|
||||
}
|
||||
//~^^ ERROR: initializer for `thread_local` value can be made `const`
|
||||
|
||||
// don't lint
|
||||
thread_local! {
|
||||
static BUF_2: RefCell<String> = const { RefCell::new(String::new()) };
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static SIMPLE:i32 = const { 1 };
|
||||
}
|
||||
//~^^ ERROR: initializer for `thread_local` value can be made `const`
|
||||
|
||||
// lint and suggest const for all non const items
|
||||
thread_local! {
|
||||
static BUF_3_CAN_BE_MADE_CONST: RefCell<String> = const { RefCell::new(String::new()) };
|
||||
static CONST_MIXED_WITH:i32 = const { 1 };
|
||||
static BUF_4_CAN_BE_MADE_CONST: RefCell<String> = const { RefCell::new(String::new()) };
|
||||
}
|
||||
//~^^^^ ERROR: initializer for `thread_local` value can be made `const`
|
||||
//~^^^ ERROR: initializer for `thread_local` value can be made `const`
|
||||
}
|
||||
30
tests/ui/thread_local_initializer_can_be_made_const.rs
Normal file
30
tests/ui/thread_local_initializer_can_be_made_const.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#![warn(clippy::thread_local_initializer_can_be_made_const)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
fn main() {
|
||||
// lint and suggest const
|
||||
thread_local! {
|
||||
static BUF_1: RefCell<String> = RefCell::new(String::new());
|
||||
}
|
||||
//~^^ ERROR: initializer for `thread_local` value can be made `const`
|
||||
|
||||
// don't lint
|
||||
thread_local! {
|
||||
static BUF_2: RefCell<String> = const { RefCell::new(String::new()) };
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static SIMPLE:i32 = 1;
|
||||
}
|
||||
//~^^ ERROR: initializer for `thread_local` value can be made `const`
|
||||
|
||||
// lint and suggest const for all non const items
|
||||
thread_local! {
|
||||
static BUF_3_CAN_BE_MADE_CONST: RefCell<String> = RefCell::new(String::new());
|
||||
static CONST_MIXED_WITH:i32 = const { 1 };
|
||||
static BUF_4_CAN_BE_MADE_CONST: RefCell<String> = RefCell::new(String::new());
|
||||
}
|
||||
//~^^^^ ERROR: initializer for `thread_local` value can be made `const`
|
||||
//~^^^ ERROR: initializer for `thread_local` value can be made `const`
|
||||
}
|
||||
29
tests/ui/thread_local_initializer_can_be_made_const.stderr
Normal file
29
tests/ui/thread_local_initializer_can_be_made_const.stderr
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
error: initializer for `thread_local` value can be made `const`
|
||||
--> $DIR/thread_local_initializer_can_be_made_const.rs:8:41
|
||||
|
|
||||
LL | static BUF_1: RefCell<String> = RefCell::new(String::new());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `const { RefCell::new(String::new()) }`
|
||||
|
|
||||
= note: `-D clippy::thread-local-initializer-can-be-made-const` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::thread_local_initializer_can_be_made_const)]`
|
||||
|
||||
error: initializer for `thread_local` value can be made `const`
|
||||
--> $DIR/thread_local_initializer_can_be_made_const.rs:18:29
|
||||
|
|
||||
LL | static SIMPLE:i32 = 1;
|
||||
| ^ help: replace with: `const { 1 }`
|
||||
|
||||
error: initializer for `thread_local` value can be made `const`
|
||||
--> $DIR/thread_local_initializer_can_be_made_const.rs:24:59
|
||||
|
|
||||
LL | static BUF_3_CAN_BE_MADE_CONST: RefCell<String> = RefCell::new(String::new());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `const { RefCell::new(String::new()) }`
|
||||
|
||||
error: initializer for `thread_local` value can be made `const`
|
||||
--> $DIR/thread_local_initializer_can_be_made_const.rs:26:59
|
||||
|
|
||||
LL | static BUF_4_CAN_BE_MADE_CONST: RefCell<String> = RefCell::new(String::new());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `const { RefCell::new(String::new()) }`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
8
tests/ui/to_string_in_format_args_incremental.rs
Normal file
8
tests/ui/to_string_in_format_args_incremental.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
//@compile-flags: -C incremental=target/debug/test/incr
|
||||
|
||||
// see https://github.com/rust-lang/rust-clippy/issues/10969
|
||||
|
||||
fn main() {
|
||||
let s = "Hello, world!";
|
||||
println!("{}", s.to_string());
|
||||
}
|
||||
11
tests/ui/to_string_in_format_args_incremental.stderr
Normal file
11
tests/ui/to_string_in_format_args_incremental.stderr
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
error: `to_string` applied to a type that implements `Display` in `println!` args
|
||||
--> $DIR/to_string_in_format_args_incremental.rs:7:21
|
||||
|
|
||||
LL | println!("{}", s.to_string());
|
||||
| ^^^^^^^^^^^^ help: remove this
|
||||
|
|
||||
= note: `-D clippy::to-string-in-format-args` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::to_string_in_format_args)]`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
//@no-rustfix
|
||||
|
||||
#![warn(clippy::unconditional_recursion)]
|
||||
#![allow(clippy::partialeq_ne_impl)]
|
||||
#![allow(clippy::partialeq_ne_impl, clippy::default_constructed_unit_structs)]
|
||||
|
||||
enum Foo {
|
||||
A,
|
||||
|
|
@ -158,6 +158,112 @@ struct S5;
|
|||
impl_partial_eq!(S5);
|
||||
//~^ ERROR: function cannot return without recursing
|
||||
|
||||
struct S6 {
|
||||
field: String,
|
||||
}
|
||||
|
||||
impl PartialEq for S6 {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let mine = &self.field;
|
||||
let theirs = &other.field;
|
||||
mine == theirs // Should not warn!
|
||||
}
|
||||
}
|
||||
|
||||
struct S7<'a> {
|
||||
field: &'a S7<'a>,
|
||||
}
|
||||
|
||||
impl<'a> PartialEq for S7<'a> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
//~^ ERROR: function cannot return without recursing
|
||||
let mine = &self.field;
|
||||
let theirs = &other.field;
|
||||
mine == theirs
|
||||
}
|
||||
}
|
||||
|
||||
struct S8 {
|
||||
num: i32,
|
||||
field: Option<Box<S8>>,
|
||||
}
|
||||
|
||||
impl PartialEq for S8 {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
if self.num != other.num {
|
||||
return false;
|
||||
}
|
||||
|
||||
let (this, other) = match (self.field.as_deref(), other.field.as_deref()) {
|
||||
(Some(x1), Some(x2)) => (x1, x2),
|
||||
(None, None) => return true,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
this == other
|
||||
}
|
||||
}
|
||||
|
||||
struct S9;
|
||||
|
||||
impl std::string::ToString for S9 {
|
||||
fn to_string(&self) -> String {
|
||||
//~^ ERROR: function cannot return without recursing
|
||||
self.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
struct S10;
|
||||
|
||||
impl std::string::ToString for S10 {
|
||||
fn to_string(&self) -> String {
|
||||
//~^ ERROR: function cannot return without recursing
|
||||
let x = self;
|
||||
x.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
struct S11;
|
||||
|
||||
impl std::string::ToString for S11 {
|
||||
fn to_string(&self) -> String {
|
||||
//~^ ERROR: function cannot return without recursing
|
||||
(self as &Self).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
struct S12;
|
||||
|
||||
impl std::default::Default for S12 {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl S12 {
|
||||
fn new() -> Self {
|
||||
//~^ ERROR: function cannot return without recursing
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn bar() -> Self {
|
||||
// Should not warn!
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct S13 {
|
||||
f: u32,
|
||||
}
|
||||
|
||||
impl S13 {
|
||||
fn new() -> Self {
|
||||
// Shoud not warn!
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// test code goes here
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,39 @@ LL | self.eq(other)
|
|||
|
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
|
||||
error: function cannot return without recursing
|
||||
--> $DIR/unconditional_recursion.rs:210:5
|
||||
|
|
||||
LL | fn to_string(&self) -> String {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||
LL |
|
||||
LL | self.to_string()
|
||||
| ---------------- recursive call site
|
||||
|
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
|
||||
error: function cannot return without recursing
|
||||
--> $DIR/unconditional_recursion.rs:219:5
|
||||
|
|
||||
LL | fn to_string(&self) -> String {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||
...
|
||||
LL | x.to_string()
|
||||
| ------------- recursive call site
|
||||
|
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
|
||||
error: function cannot return without recursing
|
||||
--> $DIR/unconditional_recursion.rs:229:5
|
||||
|
|
||||
LL | fn to_string(&self) -> String {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||
LL |
|
||||
LL | (self as &Self).to_string()
|
||||
| --------------------------- recursive call site
|
||||
|
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
|
||||
error: function cannot return without recursing
|
||||
--> $DIR/unconditional_recursion.rs:12:5
|
||||
|
|
||||
|
|
@ -54,6 +87,34 @@ note: recursive call site
|
|||
LL | self == other
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: function cannot return without recursing
|
||||
--> $DIR/unconditional_recursion.rs:28:5
|
||||
|
|
||||
LL | / fn ne(&self, other: &Self) -> bool {
|
||||
LL | | self != &Foo2::B // no error here
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: recursive call site
|
||||
--> $DIR/unconditional_recursion.rs:29:9
|
||||
|
|
||||
LL | self != &Foo2::B // no error here
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: function cannot return without recursing
|
||||
--> $DIR/unconditional_recursion.rs:31:5
|
||||
|
|
||||
LL | / fn eq(&self, other: &Self) -> bool {
|
||||
LL | | self == &Foo2::B // no error here
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: recursive call site
|
||||
--> $DIR/unconditional_recursion.rs:32:9
|
||||
|
|
||||
LL | self == &Foo2::B // no error here
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: function cannot return without recursing
|
||||
--> $DIR/unconditional_recursion.rs:42:5
|
||||
|
|
||||
|
|
@ -247,5 +308,37 @@ LL | impl_partial_eq!(S5);
|
|||
| -------------------- in this macro invocation
|
||||
= note: this error originates in the macro `impl_partial_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 19 previous errors
|
||||
error: function cannot return without recursing
|
||||
--> $DIR/unconditional_recursion.rs:178:5
|
||||
|
|
||||
LL | / fn eq(&self, other: &Self) -> bool {
|
||||
LL | |
|
||||
LL | | let mine = &self.field;
|
||||
LL | | let theirs = &other.field;
|
||||
LL | | mine == theirs
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: recursive call site
|
||||
--> $DIR/unconditional_recursion.rs:182:9
|
||||
|
|
||||
LL | mine == theirs
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: function cannot return without recursing
|
||||
--> $DIR/unconditional_recursion.rs:244:5
|
||||
|
|
||||
LL | / fn new() -> Self {
|
||||
LL | |
|
||||
LL | | Self::default()
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: recursive call site
|
||||
--> $DIR/unconditional_recursion.rs:246:9
|
||||
|
|
||||
LL | Self::default()
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 26 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,18 @@ impl Drop for Issue9427FollowUp {
|
|||
}
|
||||
}
|
||||
|
||||
struct Issue9427Followup2 {
|
||||
ptr: *const (),
|
||||
}
|
||||
impl Issue9427Followup2 {
|
||||
fn from_owned(ptr: *const ()) -> Option<Self> {
|
||||
(!ptr.is_null()).then(|| Self { ptr })
|
||||
}
|
||||
}
|
||||
impl Drop for Issue9427Followup2 {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
struct Issue10437;
|
||||
impl Deref for Issue10437 {
|
||||
type Target = u32;
|
||||
|
|
@ -128,6 +140,7 @@ fn main() {
|
|||
// Should not lint - bool
|
||||
let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop
|
||||
let _ = false.then(|| Issue9427FollowUp); // Issue9427FollowUp has a significant drop
|
||||
let _ = false.then(|| Issue9427Followup2 { ptr: std::ptr::null() });
|
||||
|
||||
// should not lint, bind_instead_of_map takes priority
|
||||
let _ = Some(10).and_then(|idx| Some(ext_arr[idx]));
|
||||
|
|
|
|||
|
|
@ -47,6 +47,18 @@ impl Drop for Issue9427FollowUp {
|
|||
}
|
||||
}
|
||||
|
||||
struct Issue9427Followup2 {
|
||||
ptr: *const (),
|
||||
}
|
||||
impl Issue9427Followup2 {
|
||||
fn from_owned(ptr: *const ()) -> Option<Self> {
|
||||
(!ptr.is_null()).then(|| Self { ptr })
|
||||
}
|
||||
}
|
||||
impl Drop for Issue9427Followup2 {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
struct Issue10437;
|
||||
impl Deref for Issue10437 {
|
||||
type Target = u32;
|
||||
|
|
@ -128,6 +140,7 @@ fn main() {
|
|||
// Should not lint - bool
|
||||
let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop
|
||||
let _ = false.then(|| Issue9427FollowUp); // Issue9427FollowUp has a significant drop
|
||||
let _ = false.then(|| Issue9427Followup2 { ptr: std::ptr::null() });
|
||||
|
||||
// should not lint, bind_instead_of_map takes priority
|
||||
let _ = Some(10).and_then(|idx| Some(ext_arr[idx]));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:71:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:83:13
|
||||
|
|
||||
LL | let _ = opt.unwrap_or_else(|| 2);
|
||||
| ^^^^--------------------
|
||||
|
|
@ -10,7 +10,7 @@ LL | let _ = opt.unwrap_or_else(|| 2);
|
|||
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_lazy_evaluations)]`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:72:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:84:13
|
||||
|
|
||||
LL | let _ = opt.unwrap_or_else(|| astronomers_pi);
|
||||
| ^^^^---------------------------------
|
||||
|
|
@ -18,7 +18,7 @@ LL | let _ = opt.unwrap_or_else(|| astronomers_pi);
|
|||
| help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:73:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:85:13
|
||||
|
|
||||
LL | let _ = opt.unwrap_or_else(|| ext_str.some_field);
|
||||
| ^^^^-------------------------------------
|
||||
|
|
@ -26,7 +26,7 @@ LL | let _ = opt.unwrap_or_else(|| ext_str.some_field);
|
|||
| help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:75:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:87:13
|
||||
|
|
||||
LL | let _ = opt.and_then(|_| ext_opt);
|
||||
| ^^^^---------------------
|
||||
|
|
@ -34,7 +34,7 @@ LL | let _ = opt.and_then(|_| ext_opt);
|
|||
| help: use `and(..)` instead: `and(ext_opt)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:76:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:88:13
|
||||
|
|
||||
LL | let _ = opt.or_else(|| ext_opt);
|
||||
| ^^^^-------------------
|
||||
|
|
@ -42,7 +42,7 @@ LL | let _ = opt.or_else(|| ext_opt);
|
|||
| help: use `or(..)` instead: `or(ext_opt)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:77:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:89:13
|
||||
|
|
||||
LL | let _ = opt.or_else(|| None);
|
||||
| ^^^^----------------
|
||||
|
|
@ -50,7 +50,7 @@ LL | let _ = opt.or_else(|| None);
|
|||
| help: use `or(..)` instead: `or(None)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:78:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:90:13
|
||||
|
|
||||
LL | let _ = opt.get_or_insert_with(|| 2);
|
||||
| ^^^^------------------------
|
||||
|
|
@ -58,7 +58,7 @@ LL | let _ = opt.get_or_insert_with(|| 2);
|
|||
| help: use `get_or_insert(..)` instead: `get_or_insert(2)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:79:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:91:13
|
||||
|
|
||||
LL | let _ = opt.ok_or_else(|| 2);
|
||||
| ^^^^----------------
|
||||
|
|
@ -66,7 +66,7 @@ LL | let _ = opt.ok_or_else(|| 2);
|
|||
| help: use `ok_or(..)` instead: `ok_or(2)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:80:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:92:13
|
||||
|
|
||||
LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
|
||||
| ^^^^^^^^^^^^^^^^^-------------------------------
|
||||
|
|
@ -74,7 +74,7 @@ LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
|
|||
| help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:81:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:93:13
|
||||
|
|
||||
LL | let _ = cond.then(|| astronomers_pi);
|
||||
| ^^^^^-----------------------
|
||||
|
|
@ -82,7 +82,7 @@ LL | let _ = cond.then(|| astronomers_pi);
|
|||
| help: use `then_some(..)` instead: `then_some(astronomers_pi)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:82:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:94:13
|
||||
|
|
||||
LL | let _ = true.then(|| -> _ {});
|
||||
| ^^^^^----------------
|
||||
|
|
@ -90,7 +90,7 @@ LL | let _ = true.then(|| -> _ {});
|
|||
| help: use `then_some(..)` instead: `then_some({})`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:83:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:95:13
|
||||
|
|
||||
LL | let _ = true.then(|| {});
|
||||
| ^^^^^-----------
|
||||
|
|
@ -98,7 +98,7 @@ LL | let _ = true.then(|| {});
|
|||
| help: use `then_some(..)` instead: `then_some({})`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:87:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:99:13
|
||||
|
|
||||
LL | let _ = Some(1).unwrap_or_else(|| *r);
|
||||
| ^^^^^^^^---------------------
|
||||
|
|
@ -106,7 +106,7 @@ LL | let _ = Some(1).unwrap_or_else(|| *r);
|
|||
| help: use `unwrap_or(..)` instead: `unwrap_or(*r)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:89:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:101:13
|
||||
|
|
||||
LL | let _ = Some(1).unwrap_or_else(|| *b);
|
||||
| ^^^^^^^^---------------------
|
||||
|
|
@ -114,7 +114,7 @@ LL | let _ = Some(1).unwrap_or_else(|| *b);
|
|||
| help: use `unwrap_or(..)` instead: `unwrap_or(*b)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:91:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:103:13
|
||||
|
|
||||
LL | let _ = Some(1).as_ref().unwrap_or_else(|| &r);
|
||||
| ^^^^^^^^^^^^^^^^^---------------------
|
||||
|
|
@ -122,7 +122,7 @@ LL | let _ = Some(1).as_ref().unwrap_or_else(|| &r);
|
|||
| help: use `unwrap_or(..)` instead: `unwrap_or(&r)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:92:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:104:13
|
||||
|
|
||||
LL | let _ = Some(1).as_ref().unwrap_or_else(|| &b);
|
||||
| ^^^^^^^^^^^^^^^^^---------------------
|
||||
|
|
@ -130,7 +130,7 @@ LL | let _ = Some(1).as_ref().unwrap_or_else(|| &b);
|
|||
| help: use `unwrap_or(..)` instead: `unwrap_or(&b)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:95:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:107:13
|
||||
|
|
||||
LL | let _ = Some(10).unwrap_or_else(|| 2);
|
||||
| ^^^^^^^^^--------------------
|
||||
|
|
@ -138,7 +138,7 @@ LL | let _ = Some(10).unwrap_or_else(|| 2);
|
|||
| help: use `unwrap_or(..)` instead: `unwrap_or(2)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:96:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:108:13
|
||||
|
|
||||
LL | let _ = Some(10).and_then(|_| ext_opt);
|
||||
| ^^^^^^^^^---------------------
|
||||
|
|
@ -146,7 +146,7 @@ LL | let _ = Some(10).and_then(|_| ext_opt);
|
|||
| help: use `and(..)` instead: `and(ext_opt)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:97:28
|
||||
--> $DIR/unnecessary_lazy_eval.rs:109:28
|
||||
|
|
||||
LL | let _: Option<usize> = None.or_else(|| ext_opt);
|
||||
| ^^^^^-------------------
|
||||
|
|
@ -154,7 +154,7 @@ LL | let _: Option<usize> = None.or_else(|| ext_opt);
|
|||
| help: use `or(..)` instead: `or(ext_opt)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:98:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:110:13
|
||||
|
|
||||
LL | let _ = None.get_or_insert_with(|| 2);
|
||||
| ^^^^^------------------------
|
||||
|
|
@ -162,7 +162,7 @@ LL | let _ = None.get_or_insert_with(|| 2);
|
|||
| help: use `get_or_insert(..)` instead: `get_or_insert(2)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:99:35
|
||||
--> $DIR/unnecessary_lazy_eval.rs:111:35
|
||||
|
|
||||
LL | let _: Result<usize, usize> = None.ok_or_else(|| 2);
|
||||
| ^^^^^----------------
|
||||
|
|
@ -170,7 +170,7 @@ LL | let _: Result<usize, usize> = None.ok_or_else(|| 2);
|
|||
| help: use `ok_or(..)` instead: `ok_or(2)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:100:28
|
||||
--> $DIR/unnecessary_lazy_eval.rs:112:28
|
||||
|
|
||||
LL | let _: Option<usize> = None.or_else(|| None);
|
||||
| ^^^^^----------------
|
||||
|
|
@ -178,7 +178,7 @@ LL | let _: Option<usize> = None.or_else(|| None);
|
|||
| help: use `or(..)` instead: `or(None)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:103:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:115:13
|
||||
|
|
||||
LL | let _ = deep.0.unwrap_or_else(|| 2);
|
||||
| ^^^^^^^--------------------
|
||||
|
|
@ -186,7 +186,7 @@ LL | let _ = deep.0.unwrap_or_else(|| 2);
|
|||
| help: use `unwrap_or(..)` instead: `unwrap_or(2)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:104:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:116:13
|
||||
|
|
||||
LL | let _ = deep.0.and_then(|_| ext_opt);
|
||||
| ^^^^^^^---------------------
|
||||
|
|
@ -194,7 +194,7 @@ LL | let _ = deep.0.and_then(|_| ext_opt);
|
|||
| help: use `and(..)` instead: `and(ext_opt)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:105:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:117:13
|
||||
|
|
||||
LL | let _ = deep.0.or_else(|| None);
|
||||
| ^^^^^^^----------------
|
||||
|
|
@ -202,7 +202,7 @@ LL | let _ = deep.0.or_else(|| None);
|
|||
| help: use `or(..)` instead: `or(None)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:106:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:118:13
|
||||
|
|
||||
LL | let _ = deep.0.get_or_insert_with(|| 2);
|
||||
| ^^^^^^^------------------------
|
||||
|
|
@ -210,7 +210,7 @@ LL | let _ = deep.0.get_or_insert_with(|| 2);
|
|||
| help: use `get_or_insert(..)` instead: `get_or_insert(2)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:107:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:119:13
|
||||
|
|
||||
LL | let _ = deep.0.ok_or_else(|| 2);
|
||||
| ^^^^^^^----------------
|
||||
|
|
@ -218,7 +218,7 @@ LL | let _ = deep.0.ok_or_else(|| 2);
|
|||
| help: use `ok_or(..)` instead: `ok_or(2)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:137:28
|
||||
--> $DIR/unnecessary_lazy_eval.rs:150:28
|
||||
|
|
||||
LL | let _: Option<usize> = None.or_else(|| Some(3));
|
||||
| ^^^^^-------------------
|
||||
|
|
@ -226,7 +226,7 @@ LL | let _: Option<usize> = None.or_else(|| Some(3));
|
|||
| help: use `or(..)` instead: `or(Some(3))`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:138:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:151:13
|
||||
|
|
||||
LL | let _ = deep.0.or_else(|| Some(3));
|
||||
| ^^^^^^^-------------------
|
||||
|
|
@ -234,7 +234,7 @@ LL | let _ = deep.0.or_else(|| Some(3));
|
|||
| help: use `or(..)` instead: `or(Some(3))`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Option::None`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:139:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:152:13
|
||||
|
|
||||
LL | let _ = opt.or_else(|| Some(3));
|
||||
| ^^^^-------------------
|
||||
|
|
@ -242,7 +242,7 @@ LL | let _ = opt.or_else(|| Some(3));
|
|||
| help: use `or(..)` instead: `or(Some(3))`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Result::Err`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:145:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:158:13
|
||||
|
|
||||
LL | let _ = res2.unwrap_or_else(|_| 2);
|
||||
| ^^^^^---------------------
|
||||
|
|
@ -250,7 +250,7 @@ LL | let _ = res2.unwrap_or_else(|_| 2);
|
|||
| help: use `unwrap_or(..)` instead: `unwrap_or(2)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Result::Err`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:146:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:159:13
|
||||
|
|
||||
LL | let _ = res2.unwrap_or_else(|_| astronomers_pi);
|
||||
| ^^^^^----------------------------------
|
||||
|
|
@ -258,7 +258,7 @@ LL | let _ = res2.unwrap_or_else(|_| astronomers_pi);
|
|||
| help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Result::Err`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:147:13
|
||||
--> $DIR/unnecessary_lazy_eval.rs:160:13
|
||||
|
|
||||
LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field);
|
||||
| ^^^^^--------------------------------------
|
||||
|
|
@ -266,7 +266,7 @@ LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field);
|
|||
| help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Result::Err`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:169:35
|
||||
--> $DIR/unnecessary_lazy_eval.rs:182:35
|
||||
|
|
||||
LL | let _: Result<usize, usize> = res.and_then(|_| Err(2));
|
||||
| ^^^^--------------------
|
||||
|
|
@ -274,7 +274,7 @@ LL | let _: Result<usize, usize> = res.and_then(|_| Err(2));
|
|||
| help: use `and(..)` instead: `and(Err(2))`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Result::Err`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:170:35
|
||||
--> $DIR/unnecessary_lazy_eval.rs:183:35
|
||||
|
|
||||
LL | let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
|
||||
| ^^^^---------------------------------
|
||||
|
|
@ -282,7 +282,7 @@ LL | let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
|
|||
| help: use `and(..)` instead: `and(Err(astronomers_pi))`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Result::Err`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:171:35
|
||||
--> $DIR/unnecessary_lazy_eval.rs:184:35
|
||||
|
|
||||
LL | let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field));
|
||||
| ^^^^-------------------------------------
|
||||
|
|
@ -290,7 +290,7 @@ LL | let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field))
|
|||
| help: use `and(..)` instead: `and(Err(ext_str.some_field))`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Result::Err`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:173:35
|
||||
--> $DIR/unnecessary_lazy_eval.rs:186:35
|
||||
|
|
||||
LL | let _: Result<usize, usize> = res.or_else(|_| Ok(2));
|
||||
| ^^^^------------------
|
||||
|
|
@ -298,7 +298,7 @@ LL | let _: Result<usize, usize> = res.or_else(|_| Ok(2));
|
|||
| help: use `or(..)` instead: `or(Ok(2))`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Result::Err`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:174:35
|
||||
--> $DIR/unnecessary_lazy_eval.rs:187:35
|
||||
|
|
||||
LL | let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
|
||||
| ^^^^-------------------------------
|
||||
|
|
@ -306,7 +306,7 @@ LL | let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
|
|||
| help: use `or(..)` instead: `or(Ok(astronomers_pi))`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Result::Err`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:175:35
|
||||
--> $DIR/unnecessary_lazy_eval.rs:188:35
|
||||
|
|
||||
LL | let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
|
||||
| ^^^^-----------------------------------
|
||||
|
|
@ -314,7 +314,7 @@ LL | let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
|
|||
| help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
|
||||
|
||||
error: unnecessary closure used to substitute value for `Result::Err`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:176:35
|
||||
--> $DIR/unnecessary_lazy_eval.rs:189:35
|
||||
|
|
||||
LL | let _: Result<usize, usize> = res.
|
||||
| ___________________________________^
|
||||
|
|
@ -329,7 +329,7 @@ LL | | or_else(|_| Ok(ext_str.some_field));
|
|||
| help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:206:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:219:14
|
||||
|
|
||||
LL | let _x = false.then(|| i32::MAX + 1);
|
||||
| ^^^^^^---------------------
|
||||
|
|
@ -337,7 +337,7 @@ LL | let _x = false.then(|| i32::MAX + 1);
|
|||
| help: use `then_some(..)` instead: `then_some(i32::MAX + 1)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:208:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:221:14
|
||||
|
|
||||
LL | let _x = false.then(|| i32::MAX * 2);
|
||||
| ^^^^^^---------------------
|
||||
|
|
@ -345,7 +345,7 @@ LL | let _x = false.then(|| i32::MAX * 2);
|
|||
| help: use `then_some(..)` instead: `then_some(i32::MAX * 2)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:210:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:223:14
|
||||
|
|
||||
LL | let _x = false.then(|| i32::MAX - 1);
|
||||
| ^^^^^^---------------------
|
||||
|
|
@ -353,7 +353,7 @@ LL | let _x = false.then(|| i32::MAX - 1);
|
|||
| help: use `then_some(..)` instead: `then_some(i32::MAX - 1)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:212:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:225:14
|
||||
|
|
||||
LL | let _x = false.then(|| i32::MIN - 1);
|
||||
| ^^^^^^---------------------
|
||||
|
|
@ -361,7 +361,7 @@ LL | let _x = false.then(|| i32::MIN - 1);
|
|||
| help: use `then_some(..)` instead: `then_some(i32::MIN - 1)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:214:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:227:14
|
||||
|
|
||||
LL | let _x = false.then(|| (1 + 2 * 3 - 2 / 3 + 9) << 2);
|
||||
| ^^^^^^-------------------------------------
|
||||
|
|
@ -369,7 +369,7 @@ LL | let _x = false.then(|| (1 + 2 * 3 - 2 / 3 + 9) << 2);
|
|||
| help: use `then_some(..)` instead: `then_some((1 + 2 * 3 - 2 / 3 + 9) << 2)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:216:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:229:14
|
||||
|
|
||||
LL | let _x = false.then(|| 255u8 << 7);
|
||||
| ^^^^^^-------------------
|
||||
|
|
@ -377,7 +377,7 @@ LL | let _x = false.then(|| 255u8 << 7);
|
|||
| help: use `then_some(..)` instead: `then_some(255u8 << 7)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:218:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:231:14
|
||||
|
|
||||
LL | let _x = false.then(|| 255u8 << 8);
|
||||
| ^^^^^^-------------------
|
||||
|
|
@ -385,7 +385,7 @@ LL | let _x = false.then(|| 255u8 << 8);
|
|||
| help: use `then_some(..)` instead: `then_some(255u8 << 8)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:220:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:233:14
|
||||
|
|
||||
LL | let _x = false.then(|| 255u8 >> 8);
|
||||
| ^^^^^^-------------------
|
||||
|
|
@ -393,7 +393,7 @@ LL | let _x = false.then(|| 255u8 >> 8);
|
|||
| help: use `then_some(..)` instead: `then_some(255u8 >> 8)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:223:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:236:14
|
||||
|
|
||||
LL | let _x = false.then(|| i32::MAX + -1);
|
||||
| ^^^^^^----------------------
|
||||
|
|
@ -401,7 +401,7 @@ LL | let _x = false.then(|| i32::MAX + -1);
|
|||
| help: use `then_some(..)` instead: `then_some(i32::MAX + -1)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:225:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:238:14
|
||||
|
|
||||
LL | let _x = false.then(|| -i32::MAX);
|
||||
| ^^^^^^------------------
|
||||
|
|
@ -409,7 +409,7 @@ LL | let _x = false.then(|| -i32::MAX);
|
|||
| help: use `then_some(..)` instead: `then_some(-i32::MAX)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:227:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:240:14
|
||||
|
|
||||
LL | let _x = false.then(|| -i32::MIN);
|
||||
| ^^^^^^------------------
|
||||
|
|
@ -417,7 +417,7 @@ LL | let _x = false.then(|| -i32::MIN);
|
|||
| help: use `then_some(..)` instead: `then_some(-i32::MIN)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:230:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:243:14
|
||||
|
|
||||
LL | let _x = false.then(|| 255 >> -7);
|
||||
| ^^^^^^------------------
|
||||
|
|
@ -425,7 +425,7 @@ LL | let _x = false.then(|| 255 >> -7);
|
|||
| help: use `then_some(..)` instead: `then_some(255 >> -7)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:232:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:245:14
|
||||
|
|
||||
LL | let _x = false.then(|| 255 << -1);
|
||||
| ^^^^^^------------------
|
||||
|
|
@ -433,7 +433,7 @@ LL | let _x = false.then(|| 255 << -1);
|
|||
| help: use `then_some(..)` instead: `then_some(255 << -1)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:234:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:247:14
|
||||
|
|
||||
LL | let _x = false.then(|| 1 / 0);
|
||||
| ^^^^^^--------------
|
||||
|
|
@ -441,7 +441,7 @@ LL | let _x = false.then(|| 1 / 0);
|
|||
| help: use `then_some(..)` instead: `then_some(1 / 0)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:236:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:249:14
|
||||
|
|
||||
LL | let _x = false.then(|| x << -1);
|
||||
| ^^^^^^----------------
|
||||
|
|
@ -449,7 +449,7 @@ LL | let _x = false.then(|| x << -1);
|
|||
| help: use `then_some(..)` instead: `then_some(x << -1)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:238:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:251:14
|
||||
|
|
||||
LL | let _x = false.then(|| x << 2);
|
||||
| ^^^^^^---------------
|
||||
|
|
@ -457,7 +457,7 @@ LL | let _x = false.then(|| x << 2);
|
|||
| help: use `then_some(..)` instead: `then_some(x << 2)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:248:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:261:14
|
||||
|
|
||||
LL | let _x = false.then(|| x / 0);
|
||||
| ^^^^^^--------------
|
||||
|
|
@ -465,7 +465,7 @@ LL | let _x = false.then(|| x / 0);
|
|||
| help: use `then_some(..)` instead: `then_some(x / 0)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:250:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:263:14
|
||||
|
|
||||
LL | let _x = false.then(|| x % 0);
|
||||
| ^^^^^^--------------
|
||||
|
|
@ -473,7 +473,7 @@ LL | let _x = false.then(|| x % 0);
|
|||
| help: use `then_some(..)` instead: `then_some(x % 0)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:253:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:266:14
|
||||
|
|
||||
LL | let _x = false.then(|| 1 / -1);
|
||||
| ^^^^^^---------------
|
||||
|
|
@ -481,7 +481,7 @@ LL | let _x = false.then(|| 1 / -1);
|
|||
| help: use `then_some(..)` instead: `then_some(1 / -1)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:255:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:268:14
|
||||
|
|
||||
LL | let _x = false.then(|| i32::MIN / -1);
|
||||
| ^^^^^^----------------------
|
||||
|
|
@ -489,7 +489,7 @@ LL | let _x = false.then(|| i32::MIN / -1);
|
|||
| help: use `then_some(..)` instead: `then_some(i32::MIN / -1)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:258:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:271:14
|
||||
|
|
||||
LL | let _x = false.then(|| i32::MIN / 0);
|
||||
| ^^^^^^---------------------
|
||||
|
|
@ -497,7 +497,7 @@ LL | let _x = false.then(|| i32::MIN / 0);
|
|||
| help: use `then_some(..)` instead: `then_some(i32::MIN / 0)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:260:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:273:14
|
||||
|
|
||||
LL | let _x = false.then(|| 4 / 2);
|
||||
| ^^^^^^--------------
|
||||
|
|
@ -505,7 +505,7 @@ LL | let _x = false.then(|| 4 / 2);
|
|||
| help: use `then_some(..)` instead: `then_some(4 / 2)`
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> $DIR/unnecessary_lazy_eval.rs:268:14
|
||||
--> $DIR/unnecessary_lazy_eval.rs:281:14
|
||||
|
|
||||
LL | let _x = false.then(|| f1 + f2);
|
||||
| ^^^^^^----------------
|
||||
|
|
|
|||
|
|
@ -73,4 +73,25 @@ mod issue_10084 {
|
|||
}
|
||||
}
|
||||
|
||||
mod issue_12048 {
|
||||
pub const X: u8 = 0;
|
||||
|
||||
/// Returns a pointer to five.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use foo::point_to_five;
|
||||
///
|
||||
/// let five_pointer = point_to_five();
|
||||
/// // Safety: this pointer always points to a valid five.
|
||||
/// let five = unsafe { *five_pointer };
|
||||
/// assert_eq!(five, 5);
|
||||
/// ```
|
||||
pub fn point_to_five() -> *const u8 {
|
||||
static FIVE: u8 = 5;
|
||||
&FIVE
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,18 @@
|
|||
#[allow(clippy::single_char_pattern)]
|
||||
#![allow(clippy::single_char_pattern)]
|
||||
|
||||
struct Issue12068;
|
||||
|
||||
impl AsRef<str> for Issue12068 {
|
||||
fn as_ref(&self) -> &str {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for Issue12068 {
|
||||
fn to_string(&self) -> String {
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = "a".split('a').next().unwrap();
|
||||
|
|
@ -9,6 +23,8 @@ fn main() {
|
|||
//~^ ERROR: unnecessary use of `to_owned`
|
||||
let _ = "a".split("a").next().unwrap();
|
||||
//~^ ERROR: unnecessary use of `to_owned`
|
||||
let _ = Issue12068.as_ref().split('a').next().unwrap();
|
||||
//~^ ERROR: unnecessary use of `to_string`
|
||||
|
||||
let _ = [1].split(|x| *x == 2).next().unwrap();
|
||||
//~^ ERROR: unnecessary use of `to_vec`
|
||||
|
|
|
|||
|
|
@ -1,4 +1,18 @@
|
|||
#[allow(clippy::single_char_pattern)]
|
||||
#![allow(clippy::single_char_pattern)]
|
||||
|
||||
struct Issue12068;
|
||||
|
||||
impl AsRef<str> for Issue12068 {
|
||||
fn as_ref(&self) -> &str {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for Issue12068 {
|
||||
fn to_string(&self) -> String {
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = "a".to_string().split('a').next().unwrap();
|
||||
|
|
@ -9,6 +23,8 @@ fn main() {
|
|||
//~^ ERROR: unnecessary use of `to_owned`
|
||||
let _ = "a".to_owned().split("a").next().unwrap();
|
||||
//~^ ERROR: unnecessary use of `to_owned`
|
||||
let _ = Issue12068.to_string().split('a').next().unwrap();
|
||||
//~^ ERROR: unnecessary use of `to_string`
|
||||
|
||||
let _ = [1].to_vec().split(|x| *x == 2).next().unwrap();
|
||||
//~^ ERROR: unnecessary use of `to_vec`
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: unnecessary use of `to_string`
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:4:13
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:18:13
|
||||
|
|
||||
LL | let _ = "a".to_string().split('a').next().unwrap();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split('a')`
|
||||
|
|
@ -8,46 +8,52 @@ LL | let _ = "a".to_string().split('a').next().unwrap();
|
|||
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_to_owned)]`
|
||||
|
||||
error: unnecessary use of `to_string`
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:6:13
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:20:13
|
||||
|
|
||||
LL | let _ = "a".to_string().split("a").next().unwrap();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split("a")`
|
||||
|
||||
error: unnecessary use of `to_owned`
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:8:13
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:22:13
|
||||
|
|
||||
LL | let _ = "a".to_owned().split('a').next().unwrap();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split('a')`
|
||||
|
||||
error: unnecessary use of `to_owned`
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:10:13
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:24:13
|
||||
|
|
||||
LL | let _ = "a".to_owned().split("a").next().unwrap();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split("a")`
|
||||
|
||||
error: unnecessary use of `to_string`
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:26:13
|
||||
|
|
||||
LL | let _ = Issue12068.to_string().split('a').next().unwrap();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Issue12068.as_ref().split('a')`
|
||||
|
||||
error: unnecessary use of `to_vec`
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:13:13
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:29:13
|
||||
|
|
||||
LL | let _ = [1].to_vec().split(|x| *x == 2).next().unwrap();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)`
|
||||
|
||||
error: unnecessary use of `to_vec`
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:15:13
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:31:13
|
||||
|
|
||||
LL | let _ = [1].to_vec().split(|x| *x == 2).next().unwrap();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)`
|
||||
|
||||
error: unnecessary use of `to_owned`
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:17:13
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:33:13
|
||||
|
|
||||
LL | let _ = [1].to_owned().split(|x| *x == 2).next().unwrap();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)`
|
||||
|
||||
error: unnecessary use of `to_owned`
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:19:13
|
||||
--> $DIR/unnecessary_to_owned_on_split.rs:35:13
|
||||
|
|
||||
LL | let _ = [1].to_owned().split(|x| *x == 2).next().unwrap();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
#![allow(
|
||||
clippy::explicit_auto_deref,
|
||||
clippy::uninlined_format_args,
|
||||
clippy::needless_pass_by_ref_mut
|
||||
clippy::map_clone,
|
||||
clippy::needless_pass_by_ref_mut,
|
||||
clippy::redundant_closure
|
||||
)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
|
@ -132,6 +134,16 @@ fn generic_ok<U: AsMut<T> + AsRef<T> + ?Sized, T: Debug + ?Sized>(mru: &mut U) {
|
|||
foo_rt(mru.as_ref());
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
let x = Some(String::new());
|
||||
let z = x.clone();
|
||||
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
||||
let z = x.clone();
|
||||
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
||||
let z = x.clone();
|
||||
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
||||
}
|
||||
|
||||
fn main() {
|
||||
not_ok();
|
||||
ok();
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
#![allow(
|
||||
clippy::explicit_auto_deref,
|
||||
clippy::uninlined_format_args,
|
||||
clippy::needless_pass_by_ref_mut
|
||||
clippy::map_clone,
|
||||
clippy::needless_pass_by_ref_mut,
|
||||
clippy::redundant_closure
|
||||
)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
|
@ -132,6 +134,16 @@ fn generic_ok<U: AsMut<T> + AsRef<T> + ?Sized, T: Debug + ?Sized>(mru: &mut U) {
|
|||
foo_rt(mru.as_ref());
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
let x = Some(String::new());
|
||||
let z = x.as_ref().map(String::clone);
|
||||
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
||||
let z = x.as_ref().map(|z| z.clone());
|
||||
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
||||
let z = x.as_ref().map(|z| String::clone(z));
|
||||
//~^ ERROR: this call to `as_ref.map(...)` does nothing
|
||||
}
|
||||
|
||||
fn main() {
|
||||
not_ok();
|
||||
ok();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:46:18
|
||||
--> $DIR/useless_asref.rs:48:18
|
||||
|
|
||||
LL | foo_rstr(rstr.as_ref());
|
||||
| ^^^^^^^^^^^^^ help: try: `rstr`
|
||||
|
|
@ -11,64 +11,82 @@ LL | #![deny(clippy::useless_asref)]
|
|||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:48:20
|
||||
--> $DIR/useless_asref.rs:50:20
|
||||
|
|
||||
LL | foo_rslice(rslice.as_ref());
|
||||
| ^^^^^^^^^^^^^^^ help: try: `rslice`
|
||||
|
||||
error: this call to `as_mut` does nothing
|
||||
--> $DIR/useless_asref.rs:52:21
|
||||
--> $DIR/useless_asref.rs:54:21
|
||||
|
|
||||
LL | foo_mrslice(mrslice.as_mut());
|
||||
| ^^^^^^^^^^^^^^^^ help: try: `mrslice`
|
||||
|
||||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:54:20
|
||||
--> $DIR/useless_asref.rs:56:20
|
||||
|
|
||||
LL | foo_rslice(mrslice.as_ref());
|
||||
| ^^^^^^^^^^^^^^^^ help: try: `mrslice`
|
||||
|
||||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:61:20
|
||||
--> $DIR/useless_asref.rs:63:20
|
||||
|
|
||||
LL | foo_rslice(rrrrrslice.as_ref());
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: try: `rrrrrslice`
|
||||
|
||||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:63:18
|
||||
--> $DIR/useless_asref.rs:65:18
|
||||
|
|
||||
LL | foo_rstr(rrrrrstr.as_ref());
|
||||
| ^^^^^^^^^^^^^^^^^ help: try: `rrrrrstr`
|
||||
|
||||
error: this call to `as_mut` does nothing
|
||||
--> $DIR/useless_asref.rs:68:21
|
||||
--> $DIR/useless_asref.rs:70:21
|
||||
|
|
||||
LL | foo_mrslice(mrrrrrslice.as_mut());
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try: `mrrrrrslice`
|
||||
|
||||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:70:20
|
||||
--> $DIR/useless_asref.rs:72:20
|
||||
|
|
||||
LL | foo_rslice(mrrrrrslice.as_ref());
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try: `mrrrrrslice`
|
||||
|
||||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:74:16
|
||||
--> $DIR/useless_asref.rs:76:16
|
||||
|
|
||||
LL | foo_rrrrmr((&&&&MoreRef).as_ref());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&&&&MoreRef)`
|
||||
|
||||
error: this call to `as_mut` does nothing
|
||||
--> $DIR/useless_asref.rs:124:13
|
||||
--> $DIR/useless_asref.rs:126:13
|
||||
|
|
||||
LL | foo_mrt(mrt.as_mut());
|
||||
| ^^^^^^^^^^^^ help: try: `mrt`
|
||||
|
||||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:126:12
|
||||
--> $DIR/useless_asref.rs:128:12
|
||||
|
|
||||
LL | foo_rt(mrt.as_ref());
|
||||
| ^^^^^^^^^^^^ help: try: `mrt`
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
error: this call to `as_ref.map(...)` does nothing
|
||||
--> $DIR/useless_asref.rs:139:13
|
||||
|
|
||||
LL | let z = x.as_ref().map(String::clone);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()`
|
||||
|
||||
error: this call to `as_ref.map(...)` does nothing
|
||||
--> $DIR/useless_asref.rs:141:13
|
||||
|
|
||||
LL | let z = x.as_ref().map(|z| z.clone());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()`
|
||||
|
||||
error: this call to `as_ref.map(...)` does nothing
|
||||
--> $DIR/useless_asref.rs:143:13
|
||||
|
|
||||
LL | let z = x.as_ref().map(|z| String::clone(z));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()`
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ mod issue11300 {
|
|||
foo2::<(), _>([1, 2, 3].into_iter());
|
||||
|
||||
// This should lint. Removing the `.into_iter()` means that `I` gets substituted with `[i32; 3]`,
|
||||
// and `i32: Helper2<[i32, 3]>` is true, so this call is indeed unncessary.
|
||||
// and `i32: Helper2<[i32, 3]>` is true, so this call is indeed unnecessary.
|
||||
foo3([1, 2, 3]);
|
||||
}
|
||||
|
||||
|
|
@ -253,7 +253,7 @@ mod issue11300 {
|
|||
|
||||
S1.foo([1, 2]);
|
||||
|
||||
// ICE that occured in itertools
|
||||
// ICE that occurred in itertools
|
||||
trait Itertools {
|
||||
fn interleave_shortest<J>(self, other: J)
|
||||
where
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ mod issue11300 {
|
|||
foo2::<(), _>([1, 2, 3].into_iter());
|
||||
|
||||
// This should lint. Removing the `.into_iter()` means that `I` gets substituted with `[i32; 3]`,
|
||||
// and `i32: Helper2<[i32, 3]>` is true, so this call is indeed unncessary.
|
||||
// and `i32: Helper2<[i32, 3]>` is true, so this call is indeed unnecessary.
|
||||
foo3([1, 2, 3].into_iter());
|
||||
}
|
||||
|
||||
|
|
@ -253,7 +253,7 @@ mod issue11300 {
|
|||
|
||||
S1.foo([1, 2].into_iter());
|
||||
|
||||
// ICE that occured in itertools
|
||||
// ICE that occurred in itertools
|
||||
trait Itertools {
|
||||
fn interleave_shortest<J>(self, other: J)
|
||||
where
|
||||
|
|
|
|||
|
|
@ -210,3 +210,10 @@ fn issue11861() {
|
|||
// should not lint
|
||||
m!(vec![1]);
|
||||
}
|
||||
|
||||
fn issue_11958() {
|
||||
fn f(_s: &[String]) {}
|
||||
|
||||
// should not lint, `String` is not `Copy`
|
||||
f(&vec!["test".to_owned(); 2]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -210,3 +210,10 @@ fn issue11861() {
|
|||
// should not lint
|
||||
m!(vec![1]);
|
||||
}
|
||||
|
||||
fn issue_11958() {
|
||||
fn f(_s: &[String]) {}
|
||||
|
||||
// should not lint, `String` is not `Copy`
|
||||
f(&vec!["test".to_owned(); 2]);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue