Also simplify if the closure body is an index expression

This commit is contained in:
Dániel Buga 2020-06-15 15:26:02 +02:00
parent 848af39310
commit a7cc5d4068
4 changed files with 116 additions and 82 deletions

View file

@ -2753,6 +2753,16 @@ fn lint_lazy_eval<'a, 'tcx>(
// Closures returning literals can be unconditionally simplified
hir::ExprKind::Lit(_) => true,
hir::ExprKind::Index(ref object, ref index) => {
// arguments are not being indexed into
if !expr_uses_argument(object, params) {
// arguments are not used as index
!expr_uses_argument(index, params)
} else {
false
}
},
// Reading fields can be simplified if the object is not an argument of the closure
hir::ExprKind::Field(ref object, _) => !expr_uses_argument(object, params),

View file

@ -3,15 +3,15 @@
#![allow(clippy::redundant_closure)]
#![allow(clippy::bind_instead_of_map)]
struct Deep(Option<u32>);
struct Deep(Option<usize>);
#[derive(Copy, Clone)]
struct SomeStruct {
some_field: u32,
some_field: usize,
}
impl SomeStruct {
fn return_some_field(&self) -> u32 {
fn return_some_field(&self) -> usize {
self.some_field
}
}
@ -22,6 +22,7 @@ fn some_call<T: Default>() -> T {
fn main() {
let astronomers_pi = 10;
let ext_arr: [usize; 1] = [2];
let ext_str = SomeStruct { some_field: 10 };
// Should lint - Option
@ -30,19 +31,21 @@ fn main() {
let _ = opt.unwrap_or(2);
let _ = opt.unwrap_or(astronomers_pi);
let _ = opt.unwrap_or(ext_str.some_field);
let _ = opt.unwrap_or(ext_arr[0]);
let _ = opt.and(ext_opt);
let _ = opt.or(ext_opt);
let _ = opt.or(None);
let _ = opt.get_or_insert(2);
let _ = opt.ok_or(2);
let _ = opt.ok_or(ext_arr[0]);
// Cases when unwrap is not called on a simple variable
let _ = Some(10).unwrap_or(2);
let _ = Some(10).and(ext_opt);
let _: Option<u32> = None.or(ext_opt);
let _: Option<usize> = None.or(ext_opt);
let _ = None.get_or_insert(2);
let _: Result<u32, u32> = None.ok_or(2);
let _: Option<u32> = None.or(None);
let _: Result<usize, usize> = None.ok_or(2);
let _: Option<usize> = None.or(None);
let mut deep = Deep(Some(42));
let _ = deep.0.unwrap_or(2);
@ -55,20 +58,22 @@ fn main() {
let _ = opt.unwrap_or_else(|| ext_str.return_some_field());
let _ = opt.or_else(some_call);
let _ = opt.or_else(|| some_call());
let _: Result<u32, u32> = opt.ok_or_else(|| some_call());
let _: Result<u32, u32> = opt.ok_or_else(some_call);
let _: Result<usize, usize> = opt.ok_or_else(|| some_call());
let _: Result<usize, usize> = opt.ok_or_else(some_call);
let _ = deep.0.get_or_insert_with(|| some_call());
let _ = deep.0.or_else(some_call);
let _ = deep.0.or_else(|| some_call());
// These are handled by bind_instead_of_map
let _: Option<u32> = None.or_else(|| Some(3));
let _ = Some(10).and_then(|idx| Some(ext_arr[idx]));
let _ = Some(10).and_then(|idx| Some(idx));
let _: Option<usize> = None.or_else(|| Some(3));
let _ = deep.0.or_else(|| Some(3));
let _ = opt.or_else(|| Some(3));
// Should lint - Result
let res: Result<u32, u32> = Err(5);
let res2: Result<u32, SomeStruct> = Err(SomeStruct { some_field: 5 });
let res: Result<usize, usize> = Err(5);
let res2: Result<usize, SomeStruct> = Err(SomeStruct { some_field: 5 });
let _ = res2.unwrap_or(2);
let _ = res2.unwrap_or(astronomers_pi);
@ -76,30 +81,31 @@ fn main() {
// Should not lint - Result
let _ = res.unwrap_or_else(|err| err);
let _ = res.unwrap_or_else(|err| ext_arr[err]);
let _ = res2.unwrap_or_else(|err| err.some_field);
let _ = res2.unwrap_or_else(|err| err.return_some_field());
let _ = res2.unwrap_or_else(|_| ext_str.return_some_field());
let _: Result<u32, u32> = res.and_then(|x| Ok(x));
let _: Result<u32, u32> = res.and_then(|x| Err(x));
let _: Result<usize, usize> = res.and_then(|x| Ok(x));
let _: Result<usize, usize> = res.and_then(|x| Err(x));
let _: Result<u32, u32> = res.or_else(|err| Ok(err));
let _: Result<u32, u32> = res.or_else(|err| Err(err));
let _: Result<usize, usize> = res.or_else(|err| Ok(err));
let _: Result<usize, usize> = res.or_else(|err| Err(err));
// These are handled by bind_instead_of_map
let _: Result<u32, u32> = res.and_then(|_| Ok(2));
let _: Result<u32, u32> = res.and_then(|_| Ok(astronomers_pi));
let _: Result<u32, u32> = res.and_then(|_| Ok(ext_str.some_field));
let _: Result<usize, usize> = res.and_then(|_| Ok(2));
let _: Result<usize, usize> = res.and_then(|_| Ok(astronomers_pi));
let _: Result<usize, usize> = res.and_then(|_| Ok(ext_str.some_field));
let _: Result<u32, u32> = res.and_then(|_| Err(2));
let _: Result<u32, u32> = res.and_then(|_| Err(astronomers_pi));
let _: Result<u32, u32> = res.and_then(|_| Err(ext_str.some_field));
let _: Result<usize, usize> = res.and_then(|_| Err(2));
let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field));
let _: Result<u32, u32> = res.or_else(|_| Ok(2));
let _: Result<u32, u32> = res.or_else(|_| Ok(astronomers_pi));
let _: Result<u32, u32> = res.or_else(|_| Ok(ext_str.some_field));
let _: Result<usize, usize> = res.or_else(|_| Ok(2));
let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
let _: Result<u32, u32> = res.or_else(|_| Err(2));
let _: Result<u32, u32> = res.or_else(|_| Err(astronomers_pi));
let _: Result<u32, u32> = res.or_else(|_| Err(ext_str.some_field));
let _: Result<usize, usize> = res.or_else(|_| Err(2));
let _: Result<usize, usize> = res.or_else(|_| Err(astronomers_pi));
let _: Result<usize, usize> = res.or_else(|_| Err(ext_str.some_field));
}

View file

@ -3,15 +3,15 @@
#![allow(clippy::redundant_closure)]
#![allow(clippy::bind_instead_of_map)]
struct Deep(Option<u32>);
struct Deep(Option<usize>);
#[derive(Copy, Clone)]
struct SomeStruct {
some_field: u32,
some_field: usize,
}
impl SomeStruct {
fn return_some_field(&self) -> u32 {
fn return_some_field(&self) -> usize {
self.some_field
}
}
@ -22,6 +22,7 @@ fn some_call<T: Default>() -> T {
fn main() {
let astronomers_pi = 10;
let ext_arr: [usize; 1] = [2];
let ext_str = SomeStruct { some_field: 10 };
// Should lint - Option
@ -30,19 +31,21 @@ fn main() {
let _ = opt.unwrap_or_else(|| 2);
let _ = opt.unwrap_or_else(|| astronomers_pi);
let _ = opt.unwrap_or_else(|| ext_str.some_field);
let _ = opt.unwrap_or_else(|| ext_arr[0]);
let _ = opt.and_then(|_| ext_opt);
let _ = opt.or_else(|| ext_opt);
let _ = opt.or_else(|| None);
let _ = opt.get_or_insert_with(|| 2);
let _ = opt.ok_or_else(|| 2);
let _ = opt.ok_or_else(|| ext_arr[0]);
// Cases when unwrap is not called on a simple variable
let _ = Some(10).unwrap_or_else(|| 2);
let _ = Some(10).and_then(|_| ext_opt);
let _: Option<u32> = None.or_else(|| ext_opt);
let _: Option<usize> = None.or_else(|| ext_opt);
let _ = None.get_or_insert_with(|| 2);
let _: Result<u32, u32> = None.ok_or_else(|| 2);
let _: Option<u32> = None.or_else(|| None);
let _: Result<usize, usize> = None.ok_or_else(|| 2);
let _: Option<usize> = None.or_else(|| None);
let mut deep = Deep(Some(42));
let _ = deep.0.unwrap_or_else(|| 2);
@ -55,20 +58,22 @@ fn main() {
let _ = opt.unwrap_or_else(|| ext_str.return_some_field());
let _ = opt.or_else(some_call);
let _ = opt.or_else(|| some_call());
let _: Result<u32, u32> = opt.ok_or_else(|| some_call());
let _: Result<u32, u32> = opt.ok_or_else(some_call);
let _: Result<usize, usize> = opt.ok_or_else(|| some_call());
let _: Result<usize, usize> = opt.ok_or_else(some_call);
let _ = deep.0.get_or_insert_with(|| some_call());
let _ = deep.0.or_else(some_call);
let _ = deep.0.or_else(|| some_call());
// These are handled by bind_instead_of_map
let _: Option<u32> = None.or_else(|| Some(3));
let _ = Some(10).and_then(|idx| Some(ext_arr[idx]));
let _ = Some(10).and_then(|idx| Some(idx));
let _: Option<usize> = None.or_else(|| Some(3));
let _ = deep.0.or_else(|| Some(3));
let _ = opt.or_else(|| Some(3));
// Should lint - Result
let res: Result<u32, u32> = Err(5);
let res2: Result<u32, SomeStruct> = Err(SomeStruct { some_field: 5 });
let res: Result<usize, usize> = Err(5);
let res2: Result<usize, SomeStruct> = Err(SomeStruct { some_field: 5 });
let _ = res2.unwrap_or_else(|_| 2);
let _ = res2.unwrap_or_else(|_| astronomers_pi);
@ -76,30 +81,31 @@ fn main() {
// Should not lint - Result
let _ = res.unwrap_or_else(|err| err);
let _ = res.unwrap_or_else(|err| ext_arr[err]);
let _ = res2.unwrap_or_else(|err| err.some_field);
let _ = res2.unwrap_or_else(|err| err.return_some_field());
let _ = res2.unwrap_or_else(|_| ext_str.return_some_field());
let _: Result<u32, u32> = res.and_then(|x| Ok(x));
let _: Result<u32, u32> = res.and_then(|x| Err(x));
let _: Result<usize, usize> = res.and_then(|x| Ok(x));
let _: Result<usize, usize> = res.and_then(|x| Err(x));
let _: Result<u32, u32> = res.or_else(|err| Ok(err));
let _: Result<u32, u32> = res.or_else(|err| Err(err));
let _: Result<usize, usize> = res.or_else(|err| Ok(err));
let _: Result<usize, usize> = res.or_else(|err| Err(err));
// These are handled by bind_instead_of_map
let _: Result<u32, u32> = res.and_then(|_| Ok(2));
let _: Result<u32, u32> = res.and_then(|_| Ok(astronomers_pi));
let _: Result<u32, u32> = res.and_then(|_| Ok(ext_str.some_field));
let _: Result<usize, usize> = res.and_then(|_| Ok(2));
let _: Result<usize, usize> = res.and_then(|_| Ok(astronomers_pi));
let _: Result<usize, usize> = res.and_then(|_| Ok(ext_str.some_field));
let _: Result<u32, u32> = res.and_then(|_| Err(2));
let _: Result<u32, u32> = res.and_then(|_| Err(astronomers_pi));
let _: Result<u32, u32> = res.and_then(|_| Err(ext_str.some_field));
let _: Result<usize, usize> = res.and_then(|_| Err(2));
let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field));
let _: Result<u32, u32> = res.or_else(|_| Ok(2));
let _: Result<u32, u32> = res.or_else(|_| Ok(astronomers_pi));
let _: Result<u32, u32> = res.or_else(|_| Ok(ext_str.some_field));
let _: Result<usize, usize> = res.or_else(|_| Ok(2));
let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
let _: Result<u32, u32> = res.or_else(|_| Err(2));
let _: Result<u32, u32> = res.or_else(|_| Err(astronomers_pi));
let _: Result<u32, u32> = res.or_else(|_| Err(ext_str.some_field));
let _: Result<usize, usize> = res.or_else(|_| Err(2));
let _: Result<usize, usize> = res.or_else(|_| Err(astronomers_pi));
let _: Result<usize, usize> = res.or_else(|_| Err(ext_str.some_field));
}

View file

@ -1,5 +1,5 @@
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:30:13
--> $DIR/unnecessary_lazy_eval.rs:31:13
|
LL | let _ = opt.unwrap_or_else(|| 2);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(2)`
@ -7,43 +7,49 @@ LL | let _ = opt.unwrap_or_else(|| 2);
= note: `-D clippy::unnecessary-lazy-evaluation` implied by `-D warnings`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:31:13
--> $DIR/unnecessary_lazy_eval.rs:32:13
|
LL | let _ = opt.unwrap_or_else(|| astronomers_pi);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(astronomers_pi)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:32:13
--> $DIR/unnecessary_lazy_eval.rs:33:13
|
LL | let _ = opt.unwrap_or_else(|| ext_str.some_field);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(ext_str.some_field)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:33:13
--> $DIR/unnecessary_lazy_eval.rs:34:13
|
LL | let _ = opt.unwrap_or_else(|| ext_arr[0]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `opt.unwrap_or(ext_arr[0])`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:35:13
|
LL | let _ = opt.and_then(|_| ext_opt);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `and` instead: `opt.and(ext_opt)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:34:13
--> $DIR/unnecessary_lazy_eval.rs:36:13
|
LL | let _ = opt.or_else(|| ext_opt);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `opt.or(ext_opt)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:35:13
--> $DIR/unnecessary_lazy_eval.rs:37:13
|
LL | let _ = opt.or_else(|| None);
| ^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `opt.or(None)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:36:13
--> $DIR/unnecessary_lazy_eval.rs:38:13
|
LL | let _ = opt.get_or_insert_with(|| 2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `get_or_insert` instead: `opt.get_or_insert(2)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:37:13
--> $DIR/unnecessary_lazy_eval.rs:39:13
|
LL | let _ = opt.ok_or_else(|| 2);
| ^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `opt.ok_or(2)`
@ -51,83 +57,89 @@ LL | let _ = opt.ok_or_else(|| 2);
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:40:13
|
LL | let _ = opt.ok_or_else(|| ext_arr[0]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `opt.ok_or(ext_arr[0])`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:43:13
|
LL | let _ = Some(10).unwrap_or_else(|| 2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `Some(10).unwrap_or(2)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:41:13
--> $DIR/unnecessary_lazy_eval.rs:44:13
|
LL | let _ = Some(10).and_then(|_| ext_opt);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `and` instead: `Some(10).and(ext_opt)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:42:26
--> $DIR/unnecessary_lazy_eval.rs:45:28
|
LL | let _: Option<u32> = None.or_else(|| ext_opt);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `None.or(ext_opt)`
LL | let _: Option<usize> = None.or_else(|| ext_opt);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `None.or(ext_opt)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:43:13
--> $DIR/unnecessary_lazy_eval.rs:46:13
|
LL | let _ = None.get_or_insert_with(|| 2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `get_or_insert` instead: `None.get_or_insert(2)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:44:31
--> $DIR/unnecessary_lazy_eval.rs:47:35
|
LL | let _: Result<u32, u32> = None.ok_or_else(|| 2);
| ^^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `None.ok_or(2)`
LL | let _: Result<usize, usize> = None.ok_or_else(|| 2);
| ^^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `None.ok_or(2)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:45:26
--> $DIR/unnecessary_lazy_eval.rs:48:28
|
LL | let _: Option<u32> = None.or_else(|| None);
| ^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `None.or(None)`
LL | let _: Option<usize> = None.or_else(|| None);
| ^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `None.or(None)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:48:13
--> $DIR/unnecessary_lazy_eval.rs:51:13
|
LL | let _ = deep.0.unwrap_or_else(|| 2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `deep.0.unwrap_or(2)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:49:13
--> $DIR/unnecessary_lazy_eval.rs:52:13
|
LL | let _ = deep.0.and_then(|_| ext_opt);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `and` instead: `deep.0.and(ext_opt)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:50:13
--> $DIR/unnecessary_lazy_eval.rs:53:13
|
LL | let _ = deep.0.or_else(|| None);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: Use `or` instead: `deep.0.or(None)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:51:13
--> $DIR/unnecessary_lazy_eval.rs:54:13
|
LL | let _ = deep.0.get_or_insert_with(|| 2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `get_or_insert` instead: `deep.0.get_or_insert(2)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:52:13
--> $DIR/unnecessary_lazy_eval.rs:55:13
|
LL | let _ = deep.0.ok_or_else(|| 2);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: Use `ok_or` instead: `deep.0.ok_or(2)`
error: unnecessary closure used to substitute value for `Result::Err`
--> $DIR/unnecessary_lazy_eval.rs:73:13
--> $DIR/unnecessary_lazy_eval.rs:78:13
|
LL | let _ = res2.unwrap_or_else(|_| 2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `res2.unwrap_or(2)`
error: unnecessary closure used to substitute value for `Result::Err`
--> $DIR/unnecessary_lazy_eval.rs:74:13
--> $DIR/unnecessary_lazy_eval.rs:79:13
|
LL | let _ = res2.unwrap_or_else(|_| astronomers_pi);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `res2.unwrap_or(astronomers_pi)`
error: unnecessary closure used to substitute value for `Result::Err`
--> $DIR/unnecessary_lazy_eval.rs:75:13
--> $DIR/unnecessary_lazy_eval.rs:80:13
|
LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Use `unwrap_or` instead: `res2.unwrap_or(ext_str.some_field)`
@ -140,5 +152,5 @@ LL | #![warn(clippy::unnecessary_lazy_eval)]
|
= note: `-D clippy::unknown-clippy-lints` implied by `-D warnings`
error: aborting due to 23 previous errors
error: aborting due to 25 previous errors