Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5995,6 +5995,7 @@ Released 2018-09-13
[`unsound_collection_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsound_collection_transmute
[`unstable_as_mut_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_mut_slice
[`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice
[`unused_any_all`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_any_all
[`unused_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_async
[`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect
[`unused_enumerate_index`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_enumerate_index
Expand Down
1 change: 1 addition & 0 deletions clippy_lints/src/declared_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::unnecessary_wraps::UNNECESSARY_WRAPS_INFO,
crate::unnested_or_patterns::UNNESTED_OR_PATTERNS_INFO,
crate::unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME_INFO,
crate::unused_any_all::UNUSED_ANY_ALL_INFO,
crate::unused_async::UNUSED_ASYNC_INFO,
crate::unused_io_amount::UNUSED_IO_AMOUNT_INFO,
crate::unused_peekable::UNUSED_PEEKABLE_INFO,
Expand Down
2 changes: 2 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ mod unnecessary_struct_initialization;
mod unnecessary_wraps;
mod unnested_or_patterns;
mod unsafe_removed_from_name;
mod unused_any_all;
mod unused_async;
mod unused_io_amount;
mod unused_peekable;
Expand Down Expand Up @@ -799,6 +800,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_late_pass(move |_| Box::new(if_then_some_else_none::IfThenSomeElseNone::new(conf)));
store.register_late_pass(|_| Box::new(bool_assert_comparison::BoolAssertComparison));
store.register_early_pass(move || Box::new(module_style::ModStyle));
store.register_late_pass(|_| Box::<unused_any_all::UnusedAnyAll>::default());
store.register_late_pass(|_| Box::<unused_async::UnusedAsync>::default());
store.register_late_pass(move |tcx| Box::new(disallowed_types::DisallowedTypes::new(tcx, conf)));
store.register_late_pass(move |tcx| Box::new(missing_enforced_import_rename::ImportRename::new(tcx, conf)));
Expand Down
95 changes: 95 additions & 0 deletions clippy_lints/src/unused_any_all.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::macros::HirNode;
use rustc_hir::{Expr, ExprKind, QPath, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
use rustc_span::sym;

declare_clippy_lint! {
/// ### What it does
/// Checks for calls to `any` or `all` where the return values are ignored.
///
/// Ignoring the return value of `any` or `all` is suspicious and may indicate a mistake.
/// The returned value is usually intended to be used as a condition.
/// If `any` or `all` is called solely for their side effects on the iterator or their `FnMut` argument,
/// it's generally better to consume the iterator using a plain `for` loop.
///
/// ### Example
/// ```no_run
/// let mut days_without_accident = 0;
/// (0..).all(|day| {
/// if day % 5 == 0 {
/// return false
/// }
///
/// days_without_accident += 1;
/// true
/// });
/// ```

#[clippy::version = "1.82.0"]
pub UNUSED_ANY_ALL,
suspicious,
"unused result of `Iterator::any` or `Iterator::all`"
}

#[derive(Default)]
pub struct UnusedAnyAll;

impl_lint_pass!(UnusedAnyAll => [UNUSED_ANY_ALL]);

impl<'tcx> LateLintPass<'tcx> for UnusedAnyAll {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
let sym_any = sym::any;
let sym_all = sym::all;
let sym_iter = sym::Iterator;

let ExprKind::Block(block, _label) = &expr.kind else {
return;
};

for statement in block.stmts {
let StmtKind::Semi(semi) = statement.kind else { continue };

let method_name = match &semi.kind {
ExprKind::MethodCall(path, expr, _args, _span)
if path.ident.name == sym_any
|| path.ident.name == sym_all && clippy_utils::is_trait_method(cx, expr, sym::Iterator) =>
{
path.ident.name
},
ExprKind::Call(path, _args) => match path.kind {
ExprKind::Path(QPath::Resolved(_, path))
if path
.segments
.first()
.map(|s| s.ident.name)
.zip(path.segments.last().map(|s| s.ident.name))
== Some((sym_iter, sym_all)) =>
{
sym_all
},
ExprKind::Path(QPath::Resolved(_, path))
if path
.segments
.first()
.map(|s| s.ident.name)
.zip(path.segments.last().map(|s| s.ident.name))
== Some((sym_iter, sym_any)) =>
{
sym_any
},
_ => continue,
},
_ => continue,
};

span_lint(
cx,
UNUSED_ANY_ALL,
semi.span(),
format!("unused result of `Iterator::{method_name}`"),
);
}
}
}
2 changes: 1 addition & 1 deletion tests/ui/infinite_iter.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![allow(clippy::uninlined_format_args)]
#![allow(clippy::uninlined_format_args, clippy::unused_any_all)]

use std::iter::repeat;
fn square_is_lower_64(x: &u32) -> bool {
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/needless_character_iteration.fixed
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![warn(clippy::needless_character_iteration)]
#![allow(clippy::map_identity, clippy::unnecessary_operation)]
#![allow(clippy::map_identity, clippy::unnecessary_operation, clippy::unused_any_all)]

#[derive(Default)]
struct S {
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/needless_character_iteration.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![warn(clippy::needless_character_iteration)]
#![allow(clippy::map_identity, clippy::unnecessary_operation)]
#![allow(clippy::map_identity, clippy::unnecessary_operation, clippy::unused_any_all)]

#[derive(Default)]
struct S {
Expand Down
8 changes: 7 additions & 1 deletion tests/ui/needless_collect.fixed
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
#![allow(unused, clippy::needless_if, clippy::suspicious_map, clippy::iter_count)]
#![allow(
unused,
clippy::needless_if,
clippy::suspicious_map,
clippy::iter_count,
clippy::unused_any_all
)]

use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList};

Expand Down
8 changes: 7 additions & 1 deletion tests/ui/needless_collect.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
#![allow(unused, clippy::needless_if, clippy::suspicious_map, clippy::iter_count)]
#![allow(
unused,
clippy::needless_if,
clippy::suspicious_map,
clippy::iter_count,
clippy::unused_any_all
)]

use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList};

Expand Down
38 changes: 19 additions & 19 deletions tests/ui/needless_collect.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:9:29
--> tests/ui/needless_collect.rs:15:29
|
LL | let len = sample.iter().collect::<Vec<_>>().len();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `count()`
Expand All @@ -8,109 +8,109 @@ LL | let len = sample.iter().collect::<Vec<_>>().len();
= help: to override `-D warnings` add `#[allow(clippy::needless_collect)]`

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:10:22
--> tests/ui/needless_collect.rs:16:22
|
LL | if sample.iter().collect::<Vec<_>>().is_empty() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()`

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:13:28
--> tests/ui/needless_collect.rs:19:28
|
LL | sample.iter().cloned().collect::<Vec<_>>().contains(&1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == 1)`

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:18:35
--> tests/ui/needless_collect.rs:24:35
|
LL | sample.iter().map(|x| (x, x)).collect::<HashMap<_, _>>().is_empty();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()`

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:19:35
--> tests/ui/needless_collect.rs:25:35
|
LL | sample.iter().map(|x| (x, x)).collect::<BTreeMap<_, _>>().is_empty();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()`

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:26:19
--> tests/ui/needless_collect.rs:32:19
|
LL | sample.iter().collect::<LinkedList<_>>().len();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `count()`

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:27:19
--> tests/ui/needless_collect.rs:33:19
|
LL | sample.iter().collect::<LinkedList<_>>().is_empty();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()`

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:28:28
--> tests/ui/needless_collect.rs:34:28
|
LL | sample.iter().cloned().collect::<LinkedList<_>>().contains(&1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == 1)`

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:29:19
--> tests/ui/needless_collect.rs:35:19
|
LL | sample.iter().collect::<LinkedList<_>>().contains(&&1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &1)`

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:32:19
--> tests/ui/needless_collect.rs:38:19
|
LL | sample.iter().collect::<BinaryHeap<_>>().len();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `count()`

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:33:19
--> tests/ui/needless_collect.rs:39:19
|
LL | sample.iter().collect::<BinaryHeap<_>>().is_empty();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()`

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:38:27
--> tests/ui/needless_collect.rs:44:27
|
LL | let _ = sample.iter().collect::<HashSet<_>>().is_empty();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()`

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:39:27
--> tests/ui/needless_collect.rs:45:27
|
LL | let _ = sample.iter().collect::<HashSet<_>>().contains(&&0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &0)`

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:61:27
--> tests/ui/needless_collect.rs:67:27
|
LL | let _ = sample.iter().collect::<VecWrapper<_>>().is_empty();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()`

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:62:27
--> tests/ui/needless_collect.rs:68:27
|
LL | let _ = sample.iter().collect::<VecWrapper<_>>().contains(&&0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &0)`

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:66:40
--> tests/ui/needless_collect.rs:72:40
|
LL | Vec::<u8>::new().extend((0..10).collect::<Vec<_>>());
| ^^^^^^^^^^^^^^^^^^^^ help: remove this call

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:67:20
--> tests/ui/needless_collect.rs:73:20
|
LL | foo((0..10).collect::<Vec<_>>());
| ^^^^^^^^^^^^^^^^^^^^ help: remove this call

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:68:49
--> tests/ui/needless_collect.rs:74:49
|
LL | bar((0..10).collect::<Vec<_>>(), (0..10).collect::<Vec<_>>());
| ^^^^^^^^^^^^^^^^^^^^ help: remove this call

error: avoid using `collect()` when not needed
--> tests/ui/needless_collect.rs:69:37
--> tests/ui/needless_collect.rs:75:37
|
LL | baz((0..10), (), ('a'..='z').collect::<Vec<_>>())
| ^^^^^^^^^^^^^^^^^^^^ help: remove this call
Expand Down
8 changes: 7 additions & 1 deletion tests/ui/string_lit_chars_any.fixed
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
//@aux-build:proc_macros.rs
#![allow(clippy::eq_op, clippy::needless_raw_string_hashes, clippy::no_effect, unused)]
#![allow(
clippy::eq_op,
clippy::needless_raw_string_hashes,
clippy::no_effect,
clippy::unused_any_all,
unused
)]
#![warn(clippy::string_lit_chars_any)]

#[macro_use]
Expand Down
8 changes: 7 additions & 1 deletion tests/ui/string_lit_chars_any.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
//@aux-build:proc_macros.rs
#![allow(clippy::eq_op, clippy::needless_raw_string_hashes, clippy::no_effect, unused)]
#![allow(
clippy::eq_op,
clippy::needless_raw_string_hashes,
clippy::no_effect,
clippy::unused_any_all,
unused
)]
#![warn(clippy::string_lit_chars_any)]

#[macro_use]
Expand Down
10 changes: 5 additions & 5 deletions tests/ui/string_lit_chars_any.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: usage of `.chars().any(...)` to check if a char matches any from a string literal
--> tests/ui/string_lit_chars_any.rs:18:5
--> tests/ui/string_lit_chars_any.rs:24:5
|
LL | "\\.+*?()|[]{}^$#&-~".chars().any(|x| x == c);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -12,7 +12,7 @@ LL | matches!(c, '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | '[' | ']'
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

error: usage of `.chars().any(...)` to check if a char matches any from a string literal
--> tests/ui/string_lit_chars_any.rs:19:5
--> tests/ui/string_lit_chars_any.rs:25:5
|
LL | r#"\.+*?()|[]{}^$#&-~"#.chars().any(|x| x == c);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -23,7 +23,7 @@ LL | matches!(c, '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | '[' | ']'
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

error: usage of `.chars().any(...)` to check if a char matches any from a string literal
--> tests/ui/string_lit_chars_any.rs:20:5
--> tests/ui/string_lit_chars_any.rs:26:5
|
LL | "\\.+*?()|[]{}^$#&-~".chars().any(|x| c == x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -34,7 +34,7 @@ LL | matches!(c, '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | '[' | ']'
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

error: usage of `.chars().any(...)` to check if a char matches any from a string literal
--> tests/ui/string_lit_chars_any.rs:21:5
--> tests/ui/string_lit_chars_any.rs:27:5
|
LL | r#"\.+*?()|[]{}^$#&-~"#.chars().any(|x| c == x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -45,7 +45,7 @@ LL | matches!(c, '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | '[' | ']'
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

error: usage of `.chars().any(...)` to check if a char matches any from a string literal
--> tests/ui/string_lit_chars_any.rs:23:5
--> tests/ui/string_lit_chars_any.rs:29:5
|
LL | "\\.+*?()|[]{}^$#&-~".chars().any(|x| { x == c });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/unused_any_all.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![warn(clippy::unused_any_all)]

fn main() {
(0..1).any(|_| false);
Iterator::any(&mut (0..1), |_| false);
let _ = (0..1).any(|_| false);
let _ = Iterator::any(&mut (0..1), |_| false);
}
Loading
Loading