diff --git a/CHANGELOG.md b/CHANGELOG.md index a2d9e0d3c235..e271a655859e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6116,7 +6116,6 @@ Released 2018-09-13 [`unnecessary_first_then_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_first_then_check [`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold [`unnecessary_get_then_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_get_then_check -[`unnecessary_iter_any`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_iter_any [`unnecessary_join`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_join [`unnecessary_lazy_evaluations`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations [`unnecessary_literal_bound`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_literal_bound diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 309249d5dace..6789d9e75006 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -483,7 +483,6 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::methods::UNNECESSARY_FIRST_THEN_CHECK_INFO, crate::methods::UNNECESSARY_FOLD_INFO, crate::methods::UNNECESSARY_GET_THEN_CHECK_INFO, - crate::methods::UNNECESSARY_ITER_ANY_INFO, crate::methods::UNNECESSARY_JOIN_INFO, crate::methods::UNNECESSARY_LAZY_EVALUATIONS_INFO, crate::methods::UNNECESSARY_LITERAL_UNWRAP_INFO, diff --git a/clippy_lints/src/methods/iter_any.rs b/clippy_lints/src/methods/iter_any.rs deleted file mode 100644 index 703b6dfc6ef6..000000000000 --- a/clippy_lints/src/methods/iter_any.rs +++ /dev/null @@ -1,60 +0,0 @@ -use clippy_utils::diagnostics::span_lint; -use rustc_hir::{Expr, ExprKind}; -use rustc_lint::LateContext; -use rustc_middle::ty::{self}; - -use super::{SLICE_ITER_ANY, UNNECESSARY_ITER_ANY, method_call}; - -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { - if !expr.span.from_expansion() - // any() - && let Some((name, recv, args, _, _)) = method_call(expr) - && name == "any" - // check if the inner closure is a equality check - && args.len() == 1 - && let ExprKind::Closure(closure) = args[0].kind - && let body = cx.tcx.hir().body(closure.body) - && let ExprKind::Binary(op, _, _) = body.value.kind - && op.node == rustc_ast::ast::BinOpKind::Eq - // iter() - && let Some((name, recv, _, _, _)) = method_call(recv) - && name == "iter" - { - let ref_type = cx.typeck_results().expr_ty(recv); - - match ref_type.kind() { - ty::Ref(_, inner_type, _) if inner_type.is_slice() => { - // check if the receiver is a u8/i8 slice - if let ty::Slice(slice_type) = inner_type.kind() - && (slice_type.to_string() == "u8" || slice_type.to_string() == "i8") - { - span_lint( - cx, - SLICE_ITER_ANY, - expr.span, - "using `contains()` instead of `iter().any()` on u8/i8 slices is more efficient", - ); - } else if let ty::Slice(slice_type) = inner_type.kind() - && slice_type.is_numeric() - { - span_lint( - cx, - UNNECESSARY_ITER_ANY, - expr.span, - "using `contains()` instead of `iter().any()` is more readable", - ); - } - }, - // if it's an array that uses `iter().any()` and its closure is an equality check, suggest using - // `contains()` (currently only for numeric arrays because of the difficulty in determining whether - // `contains()` can be replaced by `contains()` for arrays of general types) - ty::Array(array_type, _) if array_type.is_numeric() => span_lint( - cx, - UNNECESSARY_ITER_ANY, - expr.span, - "using `contains()` instead of `iter().any()` is more readable", - ), - _ => {}, - } - } -} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 2b096f1bf6b9..392c6fe7576f 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -37,7 +37,6 @@ mod inspect_for_each; mod into_iter_on_ref; mod is_digit_ascii_radix; mod is_empty; -mod iter_any; mod iter_cloned_collect; mod iter_count; mod iter_filter; @@ -101,6 +100,7 @@ mod single_char_add_str; mod single_char_insert_string; mod single_char_push_string; mod skip_while_next; +mod slice_iter_any; mod stable_sort_primitive; mod str_split; mod str_splitn; @@ -4287,10 +4287,10 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usage of `iter().any()` on slices of `u8`/`i8` when it can be replaced with `contains()` and suggests doing so. + /// Checks for usage of `iter().any()` on numeric slices when it can be replaced with `contains()` and suggests doing so. /// /// ### Why is this bad? - /// `contains()` on slices of `u8`/`i8` is faster than `iter().any()` in such cases. + /// `contains()` on numeric slices is faster than `iter().any()`. /// /// ### Example /// ```no_run @@ -4307,30 +4307,7 @@ declare_clippy_lint! { #[clippy::version = "1.85.0"] pub SLICE_ITER_ANY, perf, - "using `contains()` instead of `iter().any()` on `u8`/`i8` slices is more fast" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for usage of `iter().any()` when it can be replaced with `contains()` and suggests doing so. - /// - /// ### Why is this bad? - /// It makes the code less readable. - /// - /// ### Example - /// ```no_run - /// let values = &[1, 2, 3]; - /// let _ = values.iter().any(|&v| v == 2); - /// ``` - /// Use instead: - /// ```no_run - /// let values = &[1, 2, 3]; - /// let _ = values.contains(&2); - /// ``` - #[clippy::version = "1.85.0"] - pub UNNECESSARY_ITER_ANY, - style, - "using `contains()` instead of `iter().any()` is more readable" + "detect use of `iter().any()` on numeric slices and suggest using `contains()`" } pub struct Methods { @@ -4499,7 +4476,6 @@ impl_lint_pass!(Methods => [ MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES, UNNECESSARY_MAP_OR, SLICE_ITER_ANY, - UNNECESSARY_ITER_ANY, ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -4734,7 +4710,7 @@ impl Methods { ("any", [arg]) => { unused_enumerate_index::check(cx, expr, recv, arg); needless_character_iteration::check(cx, expr, recv, arg, false); - iter_any::check(cx, expr); + slice_iter_any::check(cx, expr, &self.msrv); match method_call(recv) { Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check( cx, diff --git a/clippy_lints/src/methods/slice_iter_any.rs b/clippy_lints/src/methods/slice_iter_any.rs new file mode 100644 index 000000000000..df9ef3bda38f --- /dev/null +++ b/clippy_lints/src/methods/slice_iter_any.rs @@ -0,0 +1,66 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::msrvs::Msrv; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_middle::ty::{self}; +use rustc_session::RustcVersion; +use rustc_span::source_map::Spanned; + +use super::{SLICE_ITER_ANY, method_call}; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) { + if !expr.span.from_expansion() + // any() + && let Some((name, recv, args, _, _)) = method_call(expr) + && name == "any" + // check if `iter().any()` can be replaced with `contains()` + && args.len() == 1 + && let ExprKind::Closure(closure) = args[0].kind + && let body = cx.tcx.hir().body(closure.body) + && let ExprKind::Binary(op, lhs, rhs) = body.value.kind + && can_replace_with_contains(op, lhs, rhs) + // iter() + && let Some((name, recv, _, _, _)) = method_call(recv) + && name == "iter" + { + let ref_type = cx.typeck_results().expr_ty_adjusted(recv); + + match ref_type.kind() { + ty::Ref(_, inner_type, _) if inner_type.is_slice() => { + // check if the receiver is a numeric slice + if let ty::Slice(slice_type) = inner_type.kind() + && ((slice_type.to_string() == "u8" || slice_type.to_string() == "i8") + || (slice_type.is_numeric() + && msrv.meets(RustcVersion { + major: 1, + minor: 84, + patch: 0, + }))) + { + span_lint( + cx, + SLICE_ITER_ANY, + expr.span, + "using `contains()` instead of `iter().any()` is more efficient", + ); + } + }, + _ => {}, + } + } +} + +fn can_replace_with_contains(op: Spanned, lhs: &Expr<'_>, rhs: &Expr<'_>) -> bool { + matches!( + (op.node, &lhs.kind, &rhs.kind), + ( + BinOpKind::Eq, + ExprKind::Path(_) | ExprKind::Unary(_, _), + ExprKind::Lit(_) | ExprKind::Path(_) + ) | ( + BinOpKind::Eq, + ExprKind::Lit(_), + ExprKind::Path(_) | ExprKind::Unary(_, _) + ) + ) +} diff --git a/tests/ui/iter_any.rs b/tests/ui/iter_any.rs deleted file mode 100644 index 3fa407b4ec05..000000000000 --- a/tests/ui/iter_any.rs +++ /dev/null @@ -1,36 +0,0 @@ -#![warn(clippy::slice_iter_any)] - -fn main() { - let vec: Vec = vec![1, 2, 3, 4, 5, 6]; - let values = &vec[..]; - let _ = values.iter().any(|&v| v == 4); - //~^ ERROR: using `contains()` instead of `iter().any()` on u8/i8 slices is more efficient - - let vec: Vec = vec![1, 2, 3, 4, 5, 6]; - let values = &vec[..]; - let _ = values.contains(&4); - // no error, because it uses `contains()` - - let vec: Vec = vec![1, 2, 3, 4, 5, 6]; - let values = &vec[..]; - let _ = values.iter().any(|&v| v == 4); - //~^ ERROR: using `contains()` instead of `iter().any()` is more readable - - let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; - let _ = values.iter().any(|&v| v == 10); - //~^ ERROR: using `contains()` instead of `iter().any()` is more readable - - let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; - let _ = values.iter().any(|&v| v > 10); - // no error, because this `any()` is not for equality -} - -fn foo(values: &[u8]) -> bool { - values.iter().any(|&v| v == 10) - //~^ ERROR: using `contains()` instead of `iter().any()` on u8/i8 slices is more efficient -} - -fn bar(values: [u8; 3]) -> bool { - values.iter().any(|&v| v == 10) - //~^ ERROR: using `contains()` instead of `iter().any()` is more readable -} diff --git a/tests/ui/iter_any.stderr b/tests/ui/iter_any.stderr deleted file mode 100644 index 17c425811e08..000000000000 --- a/tests/ui/iter_any.stderr +++ /dev/null @@ -1,38 +0,0 @@ -error: using `contains()` instead of `iter().any()` on u8/i8 slices is more efficient - --> tests/ui/iter_any.rs:6:13 - | -LL | let _ = values.iter().any(|&v| v == 4); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::slice-iter-any` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::slice_iter_any)]` - -error: using `contains()` instead of `iter().any()` is more readable - --> tests/ui/iter_any.rs:16:13 - | -LL | let _ = values.iter().any(|&v| v == 4); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::unnecessary-iter-any` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::unnecessary_iter_any)]` - -error: using `contains()` instead of `iter().any()` is more readable - --> tests/ui/iter_any.rs:20:13 - | -LL | let _ = values.iter().any(|&v| v == 10); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: using `contains()` instead of `iter().any()` on u8/i8 slices is more efficient - --> tests/ui/iter_any.rs:29:5 - | -LL | values.iter().any(|&v| v == 10) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: using `contains()` instead of `iter().any()` is more readable - --> tests/ui/iter_any.rs:34:5 - | -LL | values.iter().any(|&v| v == 10) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 5 previous errors - diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed index af08669da6a4..636dc492a04f 100644 --- a/tests/ui/needless_collect.fixed +++ b/tests/ui/needless_collect.fixed @@ -1,14 +1,15 @@ -#![allow(unused, clippy::needless_if, clippy::suspicious_map, clippy::iter_count)] +#![allow( + unused, + clippy::needless_if, + clippy::suspicious_map, + clippy::iter_count, + clippy::slice_iter_any +)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList}; #[warn(clippy::needless_collect)] -#[allow( - unused_variables, - clippy::unnecessary_iter_any, - clippy::iter_cloned_collect, - clippy::iter_next_slice -)] +#[allow(unused_variables, clippy::iter_cloned_collect, clippy::iter_next_slice)] fn main() { let sample = [1; 5]; let len = sample.iter().count(); diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index d357f4d4d43f..39e241070000 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -1,14 +1,15 @@ -#![allow(unused, clippy::needless_if, clippy::suspicious_map, clippy::iter_count)] +#![allow( + unused, + clippy::needless_if, + clippy::suspicious_map, + clippy::iter_count, + clippy::slice_iter_any +)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList}; #[warn(clippy::needless_collect)] -#[allow( - unused_variables, - clippy::unnecessary_iter_any, - clippy::iter_cloned_collect, - clippy::iter_next_slice -)] +#[allow(unused_variables, clippy::iter_cloned_collect, clippy::iter_next_slice)] fn main() { let sample = [1; 5]; let len = sample.iter().collect::>().len(); diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index 89a4d913b0a2..c22ff1a13d3d 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -1,5 +1,5 @@ error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:14:29 + --> tests/ui/needless_collect.rs:15:29 | LL | let len = sample.iter().collect::>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `count()` @@ -8,109 +8,109 @@ LL | let len = sample.iter().collect::>().len(); = help: to override `-D warnings` add `#[allow(clippy::needless_collect)]` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:15:22 + --> tests/ui/needless_collect.rs:16:22 | LL | if sample.iter().collect::>().is_empty() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:18:28 + --> tests/ui/needless_collect.rs:19:28 | LL | sample.iter().cloned().collect::>().contains(&1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == 1)` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:23:35 + --> tests/ui/needless_collect.rs:24:35 | LL | sample.iter().map(|x| (x, x)).collect::>().is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:24:35 + --> tests/ui/needless_collect.rs:25:35 | LL | sample.iter().map(|x| (x, x)).collect::>().is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:31:19 + --> tests/ui/needless_collect.rs:32:19 | LL | sample.iter().collect::>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `count()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:32:19 + --> tests/ui/needless_collect.rs:33:19 | LL | sample.iter().collect::>().is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:33:28 + --> tests/ui/needless_collect.rs:34:28 | LL | sample.iter().cloned().collect::>().contains(&1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == 1)` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:34:19 + --> tests/ui/needless_collect.rs:35:19 | LL | sample.iter().collect::>().contains(&&1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &1)` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:37:19 + --> tests/ui/needless_collect.rs:38:19 | LL | sample.iter().collect::>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `count()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:38:19 + --> tests/ui/needless_collect.rs:39:19 | LL | sample.iter().collect::>().is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:43:27 + --> tests/ui/needless_collect.rs:44:27 | LL | let _ = sample.iter().collect::>().is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:44:27 + --> tests/ui/needless_collect.rs:45:27 | LL | let _ = sample.iter().collect::>().contains(&&0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &0)` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:66:27 + --> tests/ui/needless_collect.rs:67:27 | LL | let _ = sample.iter().collect::>().is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:67:27 + --> tests/ui/needless_collect.rs:68:27 | LL | let _ = sample.iter().collect::>().contains(&&0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &0)` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:71:40 + --> tests/ui/needless_collect.rs:72:40 | LL | Vec::::new().extend((0..10).collect::>()); | ^^^^^^^^^^^^^^^^^^^^ help: remove this call error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:72:20 + --> tests/ui/needless_collect.rs:73:20 | LL | foo((0..10).collect::>()); | ^^^^^^^^^^^^^^^^^^^^ help: remove this call error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:73:49 + --> tests/ui/needless_collect.rs:74:49 | LL | bar((0..10).collect::>(), (0..10).collect::>()); | ^^^^^^^^^^^^^^^^^^^^ help: remove this call error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:74:37 + --> tests/ui/needless_collect.rs:75:37 | LL | baz((0..10), (), ('a'..='z').collect::>()) | ^^^^^^^^^^^^^^^^^^^^ help: remove this call diff --git a/tests/ui/search_is_some_fixable_none.fixed b/tests/ui/search_is_some_fixable_none.fixed index 86a937b4dae1..31aa072dd479 100644 --- a/tests/ui/search_is_some_fixable_none.fixed +++ b/tests/ui/search_is_some_fixable_none.fixed @@ -1,4 +1,4 @@ -#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec, clippy::slice_iter_any)] #![warn(clippy::search_is_some)] fn main() { diff --git a/tests/ui/search_is_some_fixable_none.rs b/tests/ui/search_is_some_fixable_none.rs index c0103a015097..776e62dcab78 100644 --- a/tests/ui/search_is_some_fixable_none.rs +++ b/tests/ui/search_is_some_fixable_none.rs @@ -1,4 +1,4 @@ -#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec, clippy::slice_iter_any)] #![warn(clippy::search_is_some)] fn main() { diff --git a/tests/ui/search_is_some_fixable_some.fixed b/tests/ui/search_is_some_fixable_some.fixed index ae3cbc3c4da2..484e2cc7f044 100644 --- a/tests/ui/search_is_some_fixable_some.fixed +++ b/tests/ui/search_is_some_fixable_some.fixed @@ -1,4 +1,4 @@ -#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec, clippy::slice_iter_any)] #![warn(clippy::search_is_some)] fn main() { diff --git a/tests/ui/search_is_some_fixable_some.rs b/tests/ui/search_is_some_fixable_some.rs index 19a44803fd54..b2dafbfd5ec7 100644 --- a/tests/ui/search_is_some_fixable_some.rs +++ b/tests/ui/search_is_some_fixable_some.rs @@ -1,4 +1,4 @@ -#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec, clippy::slice_iter_any)] #![warn(clippy::search_is_some)] fn main() { diff --git a/tests/ui/slice_iter_any.rs b/tests/ui/slice_iter_any.rs new file mode 100644 index 000000000000..c69c451f49bb --- /dev/null +++ b/tests/ui/slice_iter_any.rs @@ -0,0 +1,82 @@ +#![warn(clippy::slice_iter_any)] + +fn main() { + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.iter().any(|&v| v == 4); + //~^ ERROR: using `contains()` instead of `iter().any()` is more efficient + + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.contains(&4); + // no error, because it uses `contains()` + + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.iter().any(|&v| v == 4); + //~^ ERROR: using `contains()` instead of `iter().any()` is more efficient + + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.iter().any(|&v| v == 10); + //~^ ERROR: using `contains()` instead of `iter().any()` is more efficient + + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.iter().any(|&v| v > 10); + // no error, because this `any()` is not for equality + + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.iter().any(|&v| v % 2 == 0); + // no error, because this `iter().any()` can't be replaced with `contains()` simply + + let num = 14; + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.iter().any(|&v| v == num); + //~^ ERROR: using `contains()` instead of `iter().any()` is more efficient + + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.iter().any(|v| *v == 4); + //~^ ERROR: using `contains()` instead of `iter().any()` is more efficient +} + +fn foo(values: &[u8]) -> bool { + values.iter().any(|&v| v == 10) + //~^ ERROR: using `contains()` instead of `iter().any()` is more efficient +} + +fn bar(values: [u8; 3]) -> bool { + values.iter().any(|&v| v == 10) + //~^ ERROR: using `contains()` instead of `iter().any()` is more efficient +} + +#[clippy::msrv = "1.83"] +fn u8_slice_and_msrv_is_1_83_0() { + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.iter().any(|&v| v == 4); + //~^ ERROR: using `contains()` instead of `iter().any()` is more efficient +} + +#[clippy::msrv = "1.83"] +fn u32_slice_and_msrv_is_1_83_0() { + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.iter().any(|&v| v == 4); + // Shouldn't trigger the performance lint because the MSRV is 1.83.0 and this is a u32 slice +} + +#[clippy::msrv = "1.84"] +fn u8_slice_and_msrv_is_1_84_0() { + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.iter().any(|&v| v == 4); + //~^ ERROR: using `contains()` instead of `iter().any()` is more efficient +} + +#[clippy::msrv = "1.84"] +fn u32_slice_and_msrv_is_1_84_0() { + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.iter().any(|&v| v == 4); + //~^ ERROR: using `contains()` instead of `iter().any()` is more efficient +} diff --git a/tests/ui/slice_iter_any.stderr b/tests/ui/slice_iter_any.stderr new file mode 100644 index 000000000000..710b801f8996 --- /dev/null +++ b/tests/ui/slice_iter_any.stderr @@ -0,0 +1,65 @@ +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/slice_iter_any.rs:6:13 + | +LL | let _ = values.iter().any(|&v| v == 4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::slice-iter-any` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::slice_iter_any)]` + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/slice_iter_any.rs:16:13 + | +LL | let _ = values.iter().any(|&v| v == 4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/slice_iter_any.rs:20:13 + | +LL | let _ = values.iter().any(|&v| v == 10); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/slice_iter_any.rs:34:13 + | +LL | let _ = values.iter().any(|&v| v == num); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/slice_iter_any.rs:38:13 + | +LL | let _ = values.iter().any(|v| *v == 4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/slice_iter_any.rs:43:5 + | +LL | values.iter().any(|&v| v == 10) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/slice_iter_any.rs:48:5 + | +LL | values.iter().any(|&v| v == 10) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/slice_iter_any.rs:56:13 + | +LL | let _ = values.iter().any(|&v| v == 4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/slice_iter_any.rs:72:13 + | +LL | let _ = values.iter().any(|&v| v == 4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/slice_iter_any.rs:80:13 + | +LL | let _ = values.iter().any(|&v| v == 4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 10 previous errors +