Fix false positive of useless_conversion when using .into_iter().any() (#14800)

Fixes: rust-lang/rust-clippy#14656

changelog: Fix [`useless_conversion`] false positive when using
`.into_iter().any()`.
This commit is contained in:
llogiq 2025-05-16 06:49:42 +00:00 committed by GitHub
commit ff5e626837
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 71 additions and 2 deletions

View file

@ -7,7 +7,7 @@ use clippy_utils::{
};
use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_hir::{BindingMode, Expr, ExprKind, HirId, MatchSource, Node, PatKind};
use rustc_hir::{BindingMode, Expr, ExprKind, HirId, MatchSource, Mutability, Node, PatKind};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::Obligation;
use rustc_lint::{LateContext, LateLintPass};
@ -298,6 +298,33 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
// implements Copy, in which case .into_iter() returns a copy of the receiver and
// cannot be safely omitted.
if same_type_and_consts(a, b) && !is_copy(cx, b) {
// Below we check if the parent method call meets the following conditions:
// 1. First parameter is `&mut self` (requires mutable reference)
// 2. Second parameter implements the `FnMut` trait (e.g., Iterator::any)
// For methods satisfying these conditions (like any), .into_iter() must be preserved.
if let Some(parent) = get_parent_expr(cx, e)
&& let ExprKind::MethodCall(_, recv, _, _) = parent.kind
&& recv.hir_id == e.hir_id
&& let Some(def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id)
&& let sig = cx.tcx.fn_sig(def_id).skip_binder().skip_binder()
&& let inputs = sig.inputs()
&& inputs.len() >= 2
&& let Some(self_ty) = inputs.first()
&& let ty::Ref(_, _, Mutability::Mut) = self_ty.kind()
&& let Some(second_ty) = inputs.get(1)
&& let predicates = cx.tcx.param_env(def_id).caller_bounds()
&& predicates.iter().any(|pred| {
if let ty::ClauseKind::Trait(trait_pred) = pred.kind().skip_binder() {
trait_pred.self_ty() == *second_ty
&& cx.tcx.lang_items().fn_mut_trait() == Some(trait_pred.def_id())
} else {
false
}
})
{
return;
}
let sugg = snippet(cx, recv.span, "<expr>").into_owned();
span_lint_and_sugg(
cx,