Skip to content

Conversation

@cuongleqq
Copy link

@cuongleqq cuongleqq commented Dec 12, 2025

Fixes #16061.

Extend never_loop to also lint iterator reduction methods (e.g. for_each, try_for_each, fold, try_fold, reduce, all, any) when the closure’s body diverges (return type !). Add a UI test never_loop_iterator_reduction to cover these cases.

Testing:

  • TESTNAME=never_loop_iterator_reduction cargo uitest

changelog: [never_loop]: lint diverging iterator reduction closures like for_each and fold

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Dec 12, 2025
@rustbot
Copy link
Collaborator

rustbot commented Dec 12, 2025

r? @Jarcho

rustbot has assigned @Jarcho.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Comment on lines 893 to 901
if let ExprKind::MethodCall(path, recv, args, _) = expr.kind
&& matches!(
path.ident.name,
sym::for_each | sym::try_for_each | sym::fold | sym::try_fold | sym::reduce | sym::all | sym::any
)
&& ty::get_iterator_item_ty(cx, cx.typeck_results().expr_ty(recv)).is_some()
{
never_loop::check_iterator_reduction(cx, expr, recv, args);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be combined with the previous method check as something like

if let ExprKind::MethodCall(path, recv, args, _) = expr.kind {
  match (path.ident.name, args) {
    // methods here
  }
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used a single MethodCall destructure as suggested, but I kept 2 if branches instead of a single match because some methods like for_each, all, any are handled by both lints. Match will short-circuit to only the first matching arm.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still make it a single match. A match arm can do multiple things.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok! I switched it to a single match as suggested. For the overlapping methods, the match arm now calls both unused_enumerate_index and never_loop. Other arms handle the single-lint cases.

expr.span,
"this iterator reduction never loops (closure always diverges)",
|diag| {
let mut app = Applicability::Unspecified;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be WithPlaceholders

"this iterator reduction never loops (closure always diverges)",
|diag| {
let mut app = Applicability::Unspecified;
let recv_snip = make_iterator_snippet(cx, recv, &mut app);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be snippet_with_context. We already know the receiver is an iterator.

path.ident.name,
sym::for_each | sym::try_for_each | sym::fold | sym::try_fold | sym::reduce | sym::all | sym::any
)
&& ty::get_iterator_item_ty(cx, cx.typeck_results().expr_ty(recv)).is_some()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be recv.ty_based_def(cx).assoc_fn_parent(cx).is_diag_item(cx, sym::Iterator).

@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Dec 13, 2025
@rustbot
Copy link
Collaborator

rustbot commented Dec 13, 2025

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@rustbot rustbot added the S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) label Dec 13, 2025
@cuongleqq
Copy link
Author

I pushed an update to address all 4 comments

  • Combined the method check for both unused_enumerate_index and never_loop
  • Use a more direct check for Iterator trait
  • Use HasPlaceholders for the applicability
  • Use snippet_with_context instead of make_iterator_snippet

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties and removed S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) labels Dec 13, 2025
@cuongleqq
Copy link
Author

Addressed the requested changes:

  • Switched to a single match for the MethodCall handling

@rustbot ready

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties

Projects

None yet

Development

Successfully merging this pull request may close these issues.

never_loop: Also check all known iterator reductions.

3 participants