@@ -5,6 +5,7 @@ use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts};
55use clippy_utils:: { get_parent_expr, is_trait_method, is_ty_alias, match_def_path, path_to_local, paths} ;
66use if_chain:: if_chain;
77use rustc_errors:: Applicability ;
8+ use rustc_hir:: def:: DefKind ;
89use rustc_hir:: def_id:: DefId ;
910use rustc_hir:: { BindingAnnotation , Expr , ExprKind , HirId , MatchSource , Node , PatKind } ;
1011use rustc_lint:: { LateContext , LateLintPass } ;
@@ -101,6 +102,17 @@ fn into_iter_deep_call<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -
101102 ( expr, depth)
102103}
103104
105+ /// Checks if the given `expr` is an argument of a macro invocation.
106+ /// This is a slow-ish operation, so consider calling this late
107+ /// to avoid slowing down the lint in the happy path when not emitting a warning
108+ fn is_macro_argument ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> bool {
109+ if let Some ( parent) = get_parent_expr ( cx, expr) {
110+ parent. span . from_expansion ( ) || is_macro_argument ( cx, parent)
111+ } else {
112+ false
113+ }
114+ }
115+
104116#[ expect( clippy:: too_many_lines) ]
105117impl < ' tcx > LateLintPass < ' tcx > for UselessConversion {
106118 fn check_expr ( & mut self , cx : & LateContext < ' tcx > , e : & ' tcx Expr < ' _ > ) {
@@ -155,7 +167,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
155167 && let Some ( did) = cx. qpath_res ( qpath, recv. hir_id ) . opt_def_id ( )
156168 // make sure that the path indeed points to a fn-like item, so that
157169 // `fn_sig` does not ICE. (see #11065)
158- && cx. tcx . opt_def_kind ( did) . is_some_and ( |k| k . is_fn_like ( ) ) =>
170+ && cx. tcx . opt_def_kind ( did) . is_some_and ( DefKind :: is_fn_like) =>
159171 {
160172 Some ( ( did, args, MethodOrFunction :: Function ) )
161173 }
@@ -173,6 +185,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
173185 && let Some ( & into_iter_param) = sig. inputs ( ) . get ( kind. param_pos ( arg_pos) )
174186 && let ty:: Param ( param) = into_iter_param. kind ( )
175187 && let Some ( span) = into_iter_bound ( cx, parent_fn_did, into_iter_did, param. index )
188+ && !is_macro_argument ( cx, e)
176189 {
177190 // Get the "innermost" `.into_iter()` call, e.g. given this expression:
178191 // `foo.into_iter().into_iter()`
0 commit comments