@@ -7,7 +7,7 @@ use clippy_utils::{
7
7
} ;
8
8
use rustc_errors:: Applicability ;
9
9
use rustc_hir:: def_id:: DefId ;
10
- use rustc_hir:: { BindingMode , Expr , ExprKind , HirId , MatchSource , Node , PatKind } ;
10
+ use rustc_hir:: { BindingMode , Expr , ExprKind , HirId , MatchSource , Mutability , Node , PatKind } ;
11
11
use rustc_infer:: infer:: TyCtxtInferExt ;
12
12
use rustc_infer:: traits:: Obligation ;
13
13
use rustc_lint:: { LateContext , LateLintPass } ;
@@ -298,6 +298,33 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
298
298
// implements Copy, in which case .into_iter() returns a copy of the receiver and
299
299
// cannot be safely omitted.
300
300
if same_type_and_consts ( a, b) && !is_copy ( cx, b) {
301
+ // Below we check if the parent method call meets the following conditions:
302
+ // 1. First parameter is `&mut self` (requires mutable reference)
303
+ // 2. Second parameter implements the `FnMut` trait (e.g., Iterator::any)
304
+ // For methods satisfying these conditions (like any), .into_iter() must be preserved.
305
+ if let Some ( parent) = get_parent_expr ( cx, e)
306
+ && let ExprKind :: MethodCall ( _, recv, _, _) = parent. kind
307
+ && recv. hir_id == e. hir_id
308
+ && let Some ( def_id) = cx. typeck_results ( ) . type_dependent_def_id ( parent. hir_id )
309
+ && let sig = cx. tcx . fn_sig ( def_id) . skip_binder ( ) . skip_binder ( )
310
+ && let inputs = sig. inputs ( )
311
+ && inputs. len ( ) >= 2
312
+ && let Some ( self_ty) = inputs. first ( )
313
+ && let ty:: Ref ( _, _, Mutability :: Mut ) = self_ty. kind ( )
314
+ && let Some ( second_ty) = inputs. get ( 1 )
315
+ && let predicates = cx. tcx . param_env ( def_id) . caller_bounds ( )
316
+ && predicates. iter ( ) . any ( |pred| {
317
+ if let ty:: ClauseKind :: Trait ( trait_pred) = pred. kind ( ) . skip_binder ( ) {
318
+ trait_pred. self_ty ( ) == * second_ty
319
+ && cx. tcx . lang_items ( ) . fn_mut_trait ( ) == Some ( trait_pred. def_id ( ) )
320
+ } else {
321
+ false
322
+ }
323
+ } )
324
+ {
325
+ return ;
326
+ }
327
+
301
328
let sugg = snippet ( cx, recv. span , "<expr>" ) . into_owned ( ) ;
302
329
span_lint_and_sugg (
303
330
cx,
0 commit comments