Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

needless_collect: avoid warning if non-iterator methods are used #14147

Merged
merged 2 commits into from
Mar 2, 2025

Conversation

notriddle
Copy link
Contributor

changelog: [needless_collect]: avoid warning if non-Iterator methods are called on the result of into_iter

Fixes #13430

It can make sense to `collect()` an iterator and then immediately
iterate over it if the iterator has special methods that you need.
For example, the Map iterator doesn't implement Clone, but the
collection iterator might. Or the collection iterator might
support slicing.
@rustbot
Copy link
Collaborator

rustbot commented Feb 4, 2025

r? @blyxyas

rustbot has assigned @blyxyas.
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

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Feb 4, 2025
Comment on lines 538 to 568
impl<'tcx> Visitor<'tcx> for IteratorMethodCheckVisitor<'_, 'tcx> {
type Result = ControlFlow<()>;
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> ControlFlow<()> {
if let ExprKind::MethodCall(_method_name, recv, _args, _) = &expr.kind
&& (recv.hir_id == self.hir_id_of_expr
|| self
.hir_id_of_let_binding
.is_some_and(|hid| path_to_local_id(recv, hid)))
&& !is_trait_method(self.cx, expr, sym::Iterator)
{
return ControlFlow::Break(());
}
walk_expr(self, expr)
}
fn visit_stmt(&mut self, stmt: &'tcx Stmt<'tcx>) -> ControlFlow<()> {
if let StmtKind::Let(LetStmt {
init: Some(expr),
pat:
Pat {
kind: PatKind::Binding(BindingMode::NONE | BindingMode::MUT, id, _, None),
..
},
..
}) = &stmt.kind
&& expr.hir_id == self.hir_id_of_expr
{
self.hir_id_of_let_binding = Some(*id);
}
walk_stmt(self, stmt)
}
}
Copy link
Member

Choose a reason for hiding this comment

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

I've been checking for already-computed alternatives to this visitor. Seeing it
gives you a "this has to be already computed somewhere", and there are liveness
checks throughout Rust that are near what we need, but it seems that there isn't
anywhere that we can check to traverse through all uses of a local.

Quite sad.

}
}

fn check_iter_expr_used_only_as_iterator<'tcx>(
Copy link
Member

Choose a reason for hiding this comment

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

What would happen if we were to do something like this:

let x;
{
    x = xxx.into_iter();
    for i in x.clone();
}

If I'm not wrong, the code that comes before this, only looks at the current
scope, first looking for the initializing local, and then assigning that to
some iterable.

Testing that, it seems that the x = part is a Path with a Def of Local, could
you also take that into acccount?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're correct. The code will also check assignment to a local now.

Copy link
Member

@blyxyas blyxyas left a comment

Choose a reason for hiding this comment

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

LGTM, thanks! ❤️

@blyxyas blyxyas added this pull request to the merge queue Mar 2, 2025
Merged via the queue into rust-lang:master with commit a9c61ec Mar 2, 2025
11 checks passed
@notriddle notriddle deleted the notriddle/needless-collect-fix branch March 2, 2025 23:03
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.

False positive for "clippy::needless_collect"
3 participants