Skip to content

Commit 5857a01

Browse files
committed
Auto merge of #8744 - Jarcho:needless_collect_fp, r=llogiq
Extend `needless_collect` Extends when `is_empty` and `contains` are linted. `is_empty` will be linted when `<IterTy as Iterator>::Item` is the same as `<CollectTy as IntoIterator>::Item`. This can be a false positive if the `FromIterator` implementation filters out items, but I don't know of any which do that also implement `IntoIterator` with a matching `Item` type. `contains` will be linted when the argument type is `&<IterTy as Iterator>::Item`. It has the same false positives as `is_empty` with the same note that I know of nothing that actually causes that in practice. changelog: Lint `needless_collect` when `is_empty` or `contains` is called on some non-std types
2 parents 213003b + 8bfc8bc commit 5857a01

File tree

11 files changed

+433
-176
lines changed

11 files changed

+433
-176
lines changed

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
237237
crate::loops::MANUAL_MEMCPY_INFO,
238238
crate::loops::MISSING_SPIN_LOOP_INFO,
239239
crate::loops::MUT_RANGE_BOUND_INFO,
240-
crate::loops::NEEDLESS_COLLECT_INFO,
241240
crate::loops::NEEDLESS_RANGE_LOOP_INFO,
242241
crate::loops::NEVER_LOOP_INFO,
243242
crate::loops::SAME_ITEM_PUSH_INFO,
@@ -346,6 +345,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
346345
crate::methods::MAP_UNWRAP_OR_INFO,
347346
crate::methods::MUT_MUTEX_LOCK_INFO,
348347
crate::methods::NAIVE_BYTECOUNT_INFO,
348+
crate::methods::NEEDLESS_COLLECT_INFO,
349349
crate::methods::NEEDLESS_OPTION_AS_DEREF_INFO,
350350
crate::methods::NEEDLESS_OPTION_TAKE_INFO,
351351
crate::methods::NEEDLESS_SPLITN_INFO,

clippy_lints/src/loops/mod.rs

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ mod manual_flatten;
99
mod manual_memcpy;
1010
mod missing_spin_loop;
1111
mod mut_range_bound;
12-
mod needless_collect;
1312
mod needless_range_loop;
1413
mod never_loop;
1514
mod same_item_push;
@@ -205,28 +204,6 @@ declare_clippy_lint! {
205204
"`loop { if let { ... } else break }`, which can be written as a `while let` loop"
206205
}
207206

208-
declare_clippy_lint! {
209-
/// ### What it does
210-
/// Checks for functions collecting an iterator when collect
211-
/// is not needed.
212-
///
213-
/// ### Why is this bad?
214-
/// `collect` causes the allocation of a new data structure,
215-
/// when this allocation may not be needed.
216-
///
217-
/// ### Example
218-
/// ```rust
219-
/// # let iterator = vec![1].into_iter();
220-
/// let len = iterator.clone().collect::<Vec<_>>().len();
221-
/// // should be
222-
/// let len = iterator.count();
223-
/// ```
224-
#[clippy::version = "1.30.0"]
225-
pub NEEDLESS_COLLECT,
226-
nursery,
227-
"collecting an iterator when collect is not needed"
228-
}
229-
230207
declare_clippy_lint! {
231208
/// ### What it does
232209
/// Checks `for` loops over slices with an explicit counter
@@ -605,7 +582,6 @@ declare_lint_pass!(Loops => [
605582
EXPLICIT_INTO_ITER_LOOP,
606583
ITER_NEXT_LOOP,
607584
WHILE_LET_LOOP,
608-
NEEDLESS_COLLECT,
609585
EXPLICIT_COUNTER_LOOP,
610586
EMPTY_LOOP,
611587
WHILE_LET_ON_ITERATOR,
@@ -667,8 +643,6 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
667643
while_immutable_condition::check(cx, condition, body);
668644
missing_spin_loop::check(cx, condition, body);
669645
}
670-
671-
needless_collect::check(expr, cx);
672646
}
673647
}
674648

clippy_lints/src/methods/collapsible_str_replace.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(
2323
// If the parent node's `to` argument is the same as the `to` argument
2424
// of the last replace call in the current chain, don't lint as it was already linted
2525
if let Some(parent) = get_parent_expr(cx, expr)
26-
&& let Some(("replace", _, [current_from, current_to], _)) = method_call(parent)
26+
&& let Some(("replace", _, [current_from, current_to], _, _)) = method_call(parent)
2727
&& eq_expr_value(cx, to, current_to)
2828
&& from_kind == cx.typeck_results().expr_ty(current_from).peel_refs().kind()
2929
{
@@ -48,7 +48,7 @@ fn collect_replace_calls<'tcx>(
4848
let mut from_args = VecDeque::new();
4949

5050
let _: Option<()> = for_each_expr(expr, |e| {
51-
if let Some(("replace", _, [from, to], _)) = method_call(e) {
51+
if let Some(("replace", _, [from, to], _, _)) = method_call(e) {
5252
if eq_expr_value(cx, to_arg, to) && cx.typeck_results().expr_ty(from).peel_refs().is_char() {
5353
methods.push_front(e);
5454
from_args.push_front(from);
@@ -78,7 +78,7 @@ fn check_consecutive_replace_calls<'tcx>(
7878
.collect();
7979
let app = Applicability::MachineApplicable;
8080
let earliest_replace_call = replace_methods.methods.front().unwrap();
81-
if let Some((_, _, [..], span_lo)) = method_call(earliest_replace_call) {
81+
if let Some((_, _, [..], span_lo, _)) = method_call(earliest_replace_call) {
8282
span_lint_and_sugg(
8383
cx,
8484
COLLAPSIBLE_STR_REPLACE,

clippy_lints/src/methods/manual_str_repeat.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,8 @@ pub(super) fn check(
5959
if let ExprKind::Call(repeat_fn, [repeat_arg]) = take_self_arg.kind;
6060
if is_path_diagnostic_item(cx, repeat_fn, sym::iter_repeat);
6161
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(collect_expr), sym::String);
62-
if let Some(collect_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id);
6362
if let Some(take_id) = cx.typeck_results().type_dependent_def_id(take_expr.hir_id);
6463
if let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
65-
if cx.tcx.trait_of_item(collect_id) == Some(iter_trait_id);
6664
if cx.tcx.trait_of_item(take_id) == Some(iter_trait_id);
6765
if let Some(repeat_kind) = parse_repeat_arg(cx, repeat_arg);
6866
let ctxt = collect_expr.span.ctxt();

clippy_lints/src/methods/map_collect_result_unit.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::is_trait_method;
32
use clippy_utils::source::snippet;
43
use clippy_utils::ty::is_type_diagnostic_item;
54
use if_chain::if_chain;
@@ -11,18 +10,10 @@ use rustc_span::symbol::sym;
1110

1211
use super::MAP_COLLECT_RESULT_UNIT;
1312

14-
pub(super) fn check(
15-
cx: &LateContext<'_>,
16-
expr: &hir::Expr<'_>,
17-
iter: &hir::Expr<'_>,
18-
map_fn: &hir::Expr<'_>,
19-
collect_recv: &hir::Expr<'_>,
20-
) {
13+
pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, iter: &hir::Expr<'_>, map_fn: &hir::Expr<'_>) {
14+
// return of collect `Result<(),_>`
15+
let collect_ret_ty = cx.typeck_results().expr_ty(expr);
2116
if_chain! {
22-
// called on Iterator
23-
if is_trait_method(cx, collect_recv, sym::Iterator);
24-
// return of collect `Result<(),_>`
25-
let collect_ret_ty = cx.typeck_results().expr_ty(expr);
2617
if is_type_diagnostic_item(cx, collect_ret_ty, sym::Result);
2718
if let ty::Adt(_, substs) = collect_ret_ty.kind();
2819
if let Some(result_t) = substs.types().next();

0 commit comments

Comments
 (0)