diff --git a/tests/ui/iter_nth.rs b/tests/ui/iter_nth.rs new file mode 100644 index 000000000000..9c21dd82ee45 --- /dev/null +++ b/tests/ui/iter_nth.rs @@ -0,0 +1,56 @@ +// aux-build:option_helpers.rs + +#![warn(clippy::iter_nth)] + +#[macro_use] +extern crate option_helpers; + +use option_helpers::IteratorFalsePositives; +use std::collections::VecDeque; + +/// Struct to generate false positives for things with `.iter()`. +#[derive(Copy, Clone)] +struct HasIter; + +impl HasIter { + fn iter(self) -> IteratorFalsePositives { + IteratorFalsePositives { foo: 0 } + } + + fn iter_mut(self) -> IteratorFalsePositives { + IteratorFalsePositives { foo: 0 } + } +} + +/// Checks implementation of `ITER_NTH` lint. +fn iter_nth() { + let mut some_vec = vec![0, 1, 2, 3]; + let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]); + let mut some_vec_deque: VecDeque<_> = some_vec.iter().cloned().collect(); + + { + // Make sure we lint `.iter()` for relevant types. + let bad_vec = some_vec.iter().nth(3); + let bad_slice = &some_vec[..].iter().nth(3); + let bad_boxed_slice = boxed_slice.iter().nth(3); + let bad_vec_deque = some_vec_deque.iter().nth(3); + } + + { + // Make sure we lint `.iter_mut()` for relevant types. + let bad_vec = some_vec.iter_mut().nth(3); + } + { + let bad_slice = &some_vec[..].iter_mut().nth(3); + } + { + let bad_vec_deque = some_vec_deque.iter_mut().nth(3); + } + + // Make sure we don't lint for non-relevant types. + let false_positive = HasIter; + let ok = false_positive.iter().nth(3); + let ok_mut = false_positive.iter_mut().nth(3); +} + +fn main() {} diff --git a/tests/ui/iter_nth.stderr b/tests/ui/iter_nth.stderr new file mode 100644 index 000000000000..70412f784040 --- /dev/null +++ b/tests/ui/iter_nth.stderr @@ -0,0 +1,46 @@ +error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable + --> $DIR/iter_nth.rs:33:23 + | +LL | let bad_vec = some_vec.iter().nth(3); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::iter-nth` implied by `-D warnings` + +error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable + --> $DIR/iter_nth.rs:34:26 + | +LL | let bad_slice = &some_vec[..].iter().nth(3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable + --> $DIR/iter_nth.rs:35:31 + | +LL | let bad_boxed_slice = boxed_slice.iter().nth(3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable + --> $DIR/iter_nth.rs:36:29 + | +LL | let bad_vec_deque = some_vec_deque.iter().nth(3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable + --> $DIR/iter_nth.rs:41:23 + | +LL | let bad_vec = some_vec.iter_mut().nth(3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable + --> $DIR/iter_nth.rs:44:26 + | +LL | let bad_slice = &some_vec[..].iter_mut().nth(3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable + --> $DIR/iter_nth.rs:47:29 + | +LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 46a16f75c7bc..673176911a9a 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -215,20 +215,6 @@ fn option_methods() { ); } -/// Struct to generate false positives for things with `.iter()`. -#[derive(Copy, Clone)] -struct HasIter; - -impl HasIter { - fn iter(self) -> IteratorFalsePositives { - IteratorFalsePositives { foo: 0 } - } - - fn iter_mut(self) -> IteratorFalsePositives { - IteratorFalsePositives { foo: 0 } - } -} - /// Checks implementation of `FILTER_NEXT` lint. #[rustfmt::skip] fn filter_next() { @@ -287,100 +273,6 @@ fn search_is_some() { let _ = foo.rposition().is_some(); } -/// Checks implementation of the `OR_FUN_CALL` lint. -fn or_fun_call() { - struct Foo; - - impl Foo { - fn new() -> Foo { - Foo - } - } - - enum Enum { - A(i32), - } - - fn make() -> T { - unimplemented!(); - } - - let with_enum = Some(Enum::A(1)); - with_enum.unwrap_or(Enum::A(5)); - - let with_const_fn = Some(::std::time::Duration::from_secs(1)); - with_const_fn.unwrap_or(::std::time::Duration::from_secs(5)); - - let with_constructor = Some(vec![1]); - with_constructor.unwrap_or(make()); - - let with_new = Some(vec![1]); - with_new.unwrap_or(Vec::new()); - - let with_const_args = Some(vec![1]); - with_const_args.unwrap_or(Vec::with_capacity(12)); - - let with_err: Result<_, ()> = Ok(vec![1]); - with_err.unwrap_or(make()); - - let with_err_args: Result<_, ()> = Ok(vec![1]); - with_err_args.unwrap_or(Vec::with_capacity(12)); - - let with_default_trait = Some(1); - with_default_trait.unwrap_or(Default::default()); - - let with_default_type = Some(1); - with_default_type.unwrap_or(u64::default()); - - let with_vec = Some(vec![1]); - with_vec.unwrap_or(vec![]); - - // FIXME #944: ~|SUGGESTION with_vec.unwrap_or_else(|| vec![]); - - let without_default = Some(Foo); - without_default.unwrap_or(Foo::new()); - - let mut map = HashMap::::new(); - map.entry(42).or_insert(String::new()); - - let mut btree = BTreeMap::::new(); - btree.entry(42).or_insert(String::new()); - - let stringy = Some(String::from("")); - let _ = stringy.unwrap_or("".to_owned()); -} - -/// Checks implementation of `ITER_NTH` lint. -fn iter_nth() { - let mut some_vec = vec![0, 1, 2, 3]; - let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]); - let mut some_vec_deque: VecDeque<_> = some_vec.iter().cloned().collect(); - - { - // Make sure we lint `.iter()` for relevant types. - let bad_vec = some_vec.iter().nth(3); - let bad_slice = &some_vec[..].iter().nth(3); - let bad_boxed_slice = boxed_slice.iter().nth(3); - let bad_vec_deque = some_vec_deque.iter().nth(3); - } - - { - // Make sure we lint `.iter_mut()` for relevant types. - let bad_vec = some_vec.iter_mut().nth(3); - } - { - let bad_slice = &some_vec[..].iter_mut().nth(3); - } - { - let bad_vec_deque = some_vec_deque.iter_mut().nth(3); - } - - // Make sure we don't lint for non-relevant types. - let false_positive = HasIter; - let ok = false_positive.iter().nth(3); - let ok_mut = false_positive.iter_mut().nth(3); -} - #[allow(clippy::similar_names)] fn main() { let opt = Some(0); diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index cfbb0152eebd..b86220f5dc26 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -154,7 +154,7 @@ LL | }); | error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:238:13 + --> $DIR/methods.rs:224:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -163,7 +163,7 @@ LL | let _ = v.iter().filter(|&x| *x < 0).next(); = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:241:13 + --> $DIR/methods.rs:227:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ @@ -173,7 +173,7 @@ LL | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:257:13 + --> $DIR/methods.rs:243:13 | LL | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -182,7 +182,7 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some(); = note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:260:13 + --> $DIR/methods.rs:246:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -192,7 +192,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:266:13 + --> $DIR/methods.rs:252:13 | LL | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -200,7 +200,7 @@ LL | let _ = v.iter().position(|&x| x < 0).is_some(); = note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:269:13 + --> $DIR/methods.rs:255:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -210,7 +210,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:275:13 + --> $DIR/methods.rs:261:13 | LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -218,7 +218,7 @@ LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); = note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:278:13 + --> $DIR/methods.rs:264:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -227,131 +227,13 @@ LL | | } LL | | ).is_some(); | |______________________________^ -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:315:22 - | -LL | with_constructor.unwrap_or(make()); - | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` - | - = note: `-D clippy::or-fun-call` implied by `-D warnings` - -error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:318:5 - | -LL | with_new.unwrap_or(Vec::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:321:21 - | -LL | with_const_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:324:14 - | -LL | with_err.unwrap_or(make()); - | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:327:19 - | -LL | with_err_args.unwrap_or(Vec::with_capacity(12)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` - -error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:330:5 - | -LL | with_default_trait.unwrap_or(Default::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` - -error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:333:5 - | -LL | with_default_type.unwrap_or(u64::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:336:14 - | -LL | with_vec.unwrap_or(vec![]); - | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| vec![])` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:341:21 - | -LL | without_default.unwrap_or(Foo::new()); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` - -error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:344:19 - | -LL | map.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` - -error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:347:21 - | -LL | btree.entry(42).or_insert(String::new()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` - -error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:350:21 - | -LL | let _ = stringy.unwrap_or("".to_owned()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` - -error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:361:23 - | -LL | let bad_vec = some_vec.iter().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::iter-nth` implied by `-D warnings` - -error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:362:26 - | -LL | let bad_slice = &some_vec[..].iter().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:363:31 - | -LL | let bad_boxed_slice = boxed_slice.iter().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:364:29 - | -LL | let bad_vec_deque = some_vec_deque.iter().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:369:23 - | -LL | let bad_vec = some_vec.iter_mut().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:372:26 - | -LL | let bad_slice = &some_vec[..].iter_mut().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:375:29 - | -LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:387:13 + --> $DIR/methods.rs:279:13 | LL | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D clippy::option-unwrap-used` implied by `-D warnings` -error: aborting due to 44 previous errors +error: aborting due to 25 previous errors diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs new file mode 100644 index 000000000000..562120c3ea0f --- /dev/null +++ b/tests/ui/or_fun_call.rs @@ -0,0 +1,69 @@ +#![warn(clippy::or_fun_call)] + +use std::collections::BTreeMap; +use std::collections::HashMap; + +/// Checks implementation of the `OR_FUN_CALL` lint. +fn or_fun_call() { + struct Foo; + + impl Foo { + fn new() -> Foo { + Foo + } + } + + enum Enum { + A(i32), + } + + fn make() -> T { + unimplemented!(); + } + + let with_enum = Some(Enum::A(1)); + with_enum.unwrap_or(Enum::A(5)); + + let with_const_fn = Some(::std::time::Duration::from_secs(1)); + with_const_fn.unwrap_or(::std::time::Duration::from_secs(5)); + + let with_constructor = Some(vec![1]); + with_constructor.unwrap_or(make()); + + let with_new = Some(vec![1]); + with_new.unwrap_or(Vec::new()); + + let with_const_args = Some(vec![1]); + with_const_args.unwrap_or(Vec::with_capacity(12)); + + let with_err: Result<_, ()> = Ok(vec![1]); + with_err.unwrap_or(make()); + + let with_err_args: Result<_, ()> = Ok(vec![1]); + with_err_args.unwrap_or(Vec::with_capacity(12)); + + let with_default_trait = Some(1); + with_default_trait.unwrap_or(Default::default()); + + let with_default_type = Some(1); + with_default_type.unwrap_or(u64::default()); + + let with_vec = Some(vec![1]); + with_vec.unwrap_or(vec![]); + + // FIXME #944: ~|SUGGESTION with_vec.unwrap_or_else(|| vec![]); + + let without_default = Some(Foo); + without_default.unwrap_or(Foo::new()); + + let mut map = HashMap::::new(); + map.entry(42).or_insert(String::new()); + + let mut btree = BTreeMap::::new(); + btree.entry(42).or_insert(String::new()); + + let stringy = Some(String::from("")); + let _ = stringy.unwrap_or("".to_owned()); +} + +fn main() {} diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr new file mode 100644 index 000000000000..40ae09cc20e7 --- /dev/null +++ b/tests/ui/or_fun_call.stderr @@ -0,0 +1,76 @@ +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:31:22 + | +LL | with_constructor.unwrap_or(make()); + | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` + | + = note: `-D clippy::or-fun-call` implied by `-D warnings` + +error: use of `unwrap_or` followed by a call to `new` + --> $DIR/or_fun_call.rs:34:5 + | +LL | with_new.unwrap_or(Vec::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` + +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:37:21 + | +LL | with_const_args.unwrap_or(Vec::with_capacity(12)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` + +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:40:14 + | +LL | with_err.unwrap_or(make()); + | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` + +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:43:19 + | +LL | with_err_args.unwrap_or(Vec::with_capacity(12)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` + +error: use of `unwrap_or` followed by a call to `default` + --> $DIR/or_fun_call.rs:46:5 + | +LL | with_default_trait.unwrap_or(Default::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` + +error: use of `unwrap_or` followed by a call to `default` + --> $DIR/or_fun_call.rs:49:5 + | +LL | with_default_type.unwrap_or(u64::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` + +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:52:14 + | +LL | with_vec.unwrap_or(vec![]); + | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| vec![])` + +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:57:21 + | +LL | without_default.unwrap_or(Foo::new()); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` + +error: use of `or_insert` followed by a function call + --> $DIR/or_fun_call.rs:60:19 + | +LL | map.entry(42).or_insert(String::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` + +error: use of `or_insert` followed by a function call + --> $DIR/or_fun_call.rs:63:21 + | +LL | btree.entry(42).or_insert(String::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` + +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:66:21 + | +LL | let _ = stringy.unwrap_or("".to_owned()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` + +error: aborting due to 12 previous errors +