Skip to content

Commit c59da4f

Browse files
committed
loops: reuse iterator checks for unused_enumerate_index
1 parent 9dca2a8 commit c59da4f

File tree

3 files changed

+32
-43
lines changed

3 files changed

+32
-43
lines changed

clippy_lints/src/loops/mod.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -884,25 +884,38 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
884884

885885
if let ExprKind::MethodCall(path, recv, args, _) = expr.kind {
886886
let name = path.ident.name;
887-
let is_iterator_method = cx
888-
.ty_based_def(expr)
889-
.assoc_fn_parent(cx)
890-
.is_diag_item(cx, sym::Iterator);
891887

888+
let is_iterator_method = || {
889+
cx.ty_based_def(expr)
890+
.assoc_fn_parent(cx)
891+
.is_diag_item(cx, sym::Iterator)
892+
};
893+
894+
// is_iterator_method is a bit expensive, so we call it last in each match arm
892895
match (name, args) {
893896
(sym::for_each | sym::all | sym::any, [arg]) => {
894-
unused_enumerate_index::check_method(cx, expr, recv, arg);
895-
if is_iterator_method {
896-
never_loop::check_iterator_reduction(cx, expr, recv, args);
897+
if let ExprKind::Closure(closure) = arg.kind
898+
&& is_iterator_method()
899+
{
900+
unused_enumerate_index::check_method(cx, recv, arg, closure);
901+
never_loop::check_iterator_reduction(cx, expr, recv, closure);
897902
}
898903
},
899904

900905
(sym::filter_map | sym::find_map | sym::flat_map | sym::map, [arg]) => {
901-
unused_enumerate_index::check_method(cx, expr, recv, arg);
906+
if let ExprKind::Closure(closure) = arg.kind
907+
&& is_iterator_method()
908+
{
909+
unused_enumerate_index::check_method(cx, recv, arg, closure);
910+
}
902911
},
903912

904-
(sym::try_for_each | sym::reduce | sym::fold | sym::try_fold, args) if is_iterator_method => {
905-
never_loop::check_iterator_reduction(cx, expr, recv, args);
913+
(sym::try_for_each | sym::reduce, [arg]) | (sym::fold | sym::try_fold, [_, arg]) => {
914+
if let ExprKind::Closure(closure) = arg.kind
915+
&& is_iterator_method()
916+
{
917+
never_loop::check_iterator_reduction(cx, expr, recv, closure);
918+
}
906919
},
907920

908921
_ => {},

clippy_lints/src/loops/never_loop.rs

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ use clippy_utils::sym;
88
use clippy_utils::visitors::{Descend, for_each_expr_without_closures};
99
use rustc_errors::Applicability;
1010
use rustc_hir::{
11-
Block, Destination, Expr, ExprKind, HirId, InlineAsm, InlineAsmOperand, Node, Pat, Stmt, StmtKind, StructTailExpr,
11+
Block, Closure, Destination, Expr, ExprKind, HirId, InlineAsm, InlineAsmOperand, Node, Pat, Stmt, StmtKind,
12+
StructTailExpr,
1213
};
1314
use rustc_lint::LateContext;
1415
use rustc_span::{BytePos, Span};
@@ -77,32 +78,9 @@ pub(super) fn check_iterator_reduction<'tcx>(
7778
cx: &LateContext<'tcx>,
7879
expr: &'tcx Expr<'tcx>,
7980
recv: &'tcx Expr<'tcx>,
80-
args: &'tcx [Expr<'tcx>],
81+
closure: &'tcx Closure<'tcx>,
8182
) {
82-
// identify which argument is the closure based on the method kind
83-
let Some(method_name) = (match expr.kind {
84-
ExprKind::MethodCall(path, ..) => Some(path.ident.name),
85-
_ => None,
86-
}) else {
87-
return;
88-
};
89-
90-
let closure_arg = match method_name {
91-
sym::for_each | sym::try_for_each | sym::reduce | sym::all | sym::any => args.first(),
92-
sym::fold | sym::try_fold => args.get(1),
93-
_ => None,
94-
};
95-
96-
let Some(closure_arg) = closure_arg else {
97-
return;
98-
};
99-
100-
// extract the closure body
101-
let closure_body = match closure_arg.kind {
102-
ExprKind::Closure(closure) => cx.tcx.hir_body(closure.body).value,
103-
_ => return,
104-
};
105-
83+
let closure_body = cx.tcx.hir_body(closure.body).value;
10684
let body_ty = cx.typeck_results().expr_ty(closure_body);
10785
if body_ty.is_never() {
10886
span_lint_and_then(

clippy_lints/src/loops/unused_enumerate_index.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use super::UNUSED_ENUMERATE_INDEX;
22
use clippy_utils::diagnostics::span_lint_hir_and_then;
3-
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
3+
use clippy_utils::res::MaybeDef;
44
use clippy_utils::source::{SpanRangeExt, walk_span_to_context};
55
use clippy_utils::{expr_or_init, pat_is_wild};
66
use rustc_errors::Applicability;
7-
use rustc_hir::{Expr, ExprKind, Pat, PatKind, TyKind};
7+
use rustc_hir::{Closure, Expr, ExprKind, Pat, PatKind, TyKind};
88
use rustc_lint::LateContext;
99
use rustc_span::{Span, SyntaxContext, sym};
1010

@@ -60,14 +60,12 @@ pub(super) fn check<'tcx>(
6060

6161
pub(super) fn check_method<'tcx>(
6262
cx: &LateContext<'tcx>,
63-
e: &'tcx Expr<'tcx>,
6463
recv: &'tcx Expr<'tcx>,
6564
arg: &'tcx Expr<'tcx>,
65+
closure: &'tcx Closure<'tcx>,
6666
) {
67-
if let ExprKind::Closure(closure) = arg.kind
68-
&& let body = cx.tcx.hir_body(closure.body)
69-
&& let [param] = body.params
70-
&& cx.ty_based_def(e).opt_parent(cx).is_diag_item(cx, sym::Iterator)
67+
let body = cx.tcx.hir_body(closure.body);
68+
if let [param] = body.params
7169
&& let [input] = closure.fn_decl.inputs
7270
&& !arg.span.from_expansion()
7371
&& !input.span.from_expansion()

0 commit comments

Comments
 (0)