Skip to content

Commit 51580d3

Browse files
committed
Refine never_loop iterator reduction check
1 parent fefd58b commit 51580d3

File tree

2 files changed

+20
-17
lines changed

2 files changed

+20
-17
lines changed

clippy_lints/src/loops/mod.rs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ mod while_let_on_iterator;
2626

2727
use clippy_config::Conf;
2828
use clippy_utils::msrvs::Msrv;
29-
use clippy_utils::{higher, sym, ty};
29+
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
30+
use clippy_utils::{higher, sym};
3031
use rustc_ast::Label;
3132
use rustc_hir::{Expr, ExprKind, LoopSource, Pat};
3233
use rustc_lint::{LateContext, LateLintPass};
@@ -881,23 +882,25 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
881882
manual_while_let_some::check(cx, condition, body, span);
882883
}
883884

884-
if let ExprKind::MethodCall(path, recv, [arg], _) = expr.kind
885-
&& matches!(
885+
if let ExprKind::MethodCall(path, recv, args, _) = expr.kind {
886+
if matches!(
886887
path.ident.name,
887888
sym::all | sym::any | sym::filter_map | sym::find_map | sym::flat_map | sym::for_each | sym::map
888-
)
889-
{
890-
unused_enumerate_index::check_method(cx, expr, recv, arg);
891-
}
889+
) && let [arg] = args
890+
{
891+
unused_enumerate_index::check_method(cx, expr, recv, arg);
892+
}
892893

893-
if let ExprKind::MethodCall(path, recv, args, _) = expr.kind
894-
&& matches!(
894+
if matches!(
895895
path.ident.name,
896-
sym::for_each | sym::try_for_each | sym::fold | sym::try_fold | sym::reduce | sym::all | sym::any
897-
)
898-
&& ty::get_iterator_item_ty(cx, cx.typeck_results().expr_ty(recv)).is_some()
899-
{
900-
never_loop::check_iterator_reduction(cx, expr, recv, args);
896+
sym::all | sym::any | sym::for_each | sym::try_for_each | sym::fold | sym::try_fold | sym::reduce
897+
) && cx
898+
.ty_based_def(expr)
899+
.assoc_fn_parent(cx)
900+
.is_diag_item(cx, sym::Iterator)
901+
{
902+
never_loop::check_iterator_reduction(cx, expr, recv, args);
903+
}
901904
}
902905
}
903906
}

clippy_lints/src/loops/never_loop.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use super::utils::make_iterator_snippet;
33
use clippy_utils::diagnostics::span_lint_and_then;
44
use clippy_utils::higher::ForLoop;
55
use clippy_utils::macros::root_macro_call_first_node;
6-
use clippy_utils::source::snippet;
6+
use clippy_utils::source::{snippet, snippet_with_context};
77
use clippy_utils::sym;
88
use clippy_utils::visitors::{Descend, for_each_expr_without_closures};
99
use rustc_errors::Applicability;
@@ -111,8 +111,8 @@ pub(super) fn check_iterator_reduction<'tcx>(
111111
expr.span,
112112
"this iterator reduction never loops (closure always diverges)",
113113
|diag| {
114-
let mut app = Applicability::Unspecified;
115-
let recv_snip = make_iterator_snippet(cx, recv, &mut app);
114+
let mut app = Applicability::HasPlaceholders;
115+
let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "<iter>", &mut app).0;
116116
diag.note("if you only need one element, `if let Some(x) = iter.next()` is clearer");
117117
let sugg = format!("if let Some(x) = {recv_snip}.next() {{ ... }}");
118118
diag.span_suggestion_verbose(expr.span, "consider this pattern", sugg, app);

0 commit comments

Comments
 (0)