@@ -2,7 +2,9 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lin
22use  clippy_utils:: source:: { snippet,  snippet_with_applicability,  snippet_with_context} ; 
33use  clippy_utils:: sugg:: { DiagExt  as  _,  Sugg } ; 
44use  clippy_utils:: ty:: { is_copy,  is_type_diagnostic_item,  same_type_and_consts} ; 
5- use  clippy_utils:: { get_parent_expr,  is_trait_item,  is_trait_method,  is_ty_alias,  path_to_local} ; 
5+ use  clippy_utils:: { 
6+     get_parent_expr,  is_inherent_method_call,  is_trait_item,  is_trait_method,  is_ty_alias,  path_to_local, 
7+ } ; 
68use  rustc_errors:: Applicability ; 
79use  rustc_hir:: def_id:: DefId ; 
810use  rustc_hir:: { BindingMode ,  Expr ,  ExprKind ,  HirId ,  MatchSource ,  Node ,  PatKind } ; 
@@ -12,7 +14,7 @@ use rustc_lint::{LateContext, LateLintPass};
1214use  rustc_middle:: traits:: ObligationCause ; 
1315use  rustc_middle:: ty:: { self ,  AdtDef ,  EarlyBinder ,  GenericArg ,  GenericArgsRef ,  Ty ,  TypeVisitableExt } ; 
1416use  rustc_session:: impl_lint_pass; 
15- use  rustc_span:: { Span ,  sym} ; 
17+ use  rustc_span:: { Span ,  Symbol ,   sym} ; 
1618use  rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt ; 
1719
1820declare_clippy_lint !  { 
@@ -386,11 +388,8 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
386388/// Check if `arg` is a `Into::into` or `From::from` applied to `receiver` to give `expr`, through a 
387389/// higher-order mapping function. 
388390pub  fn  check_function_application ( cx :  & LateContext < ' _ > ,  expr :  & Expr < ' _ > ,  recv :  & Expr < ' _ > ,  arg :  & Expr < ' _ > )  { 
389-     let  recv_ty = cx. typeck_results ( ) . expr_ty ( recv) ; 
390-     let  expr_ty = cx. typeck_results ( ) . expr_ty_adjusted ( expr) ; 
391-     if  let  Some ( recv_ty_defid)  = recv_ty. ty_adt_def ( ) . map ( AdtDef :: did) 
392-         && let  Some ( diag_name)  = cx. tcx . get_diagnostic_name ( recv_ty_defid) 
393-         && matches ! ( diag_name,  sym:: Option  | sym:: Result ) 
391+     if  has_eligible_receiver ( cx,  recv,  expr) 
392+         && let  expr_ty = cx. typeck_results ( ) . expr_ty_adjusted ( expr) 
394393        && same_type_and_consts ( expr_ty,  cx. typeck_results ( ) . expr_ty_adjusted ( recv) ) 
395394        && ( is_trait_item ( cx,  arg,  sym:: Into )  || is_trait_item ( cx,  arg,  sym:: From ) ) 
396395    { 
@@ -410,3 +409,29 @@ pub fn check_function_application(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &
410409        ) ; 
411410    } 
412411} 
412+ 
413+ fn  has_eligible_receiver ( cx :  & LateContext < ' _ > ,  recv :  & Expr < ' _ > ,  expr :  & Expr < ' _ > )  -> bool  { 
414+     let  recv_ty = cx. typeck_results ( ) . expr_ty ( recv) ; 
415+     if  is_inherent_method_call ( cx,  expr) 
416+         && let  Some ( recv_ty_defid)  = recv_ty. ty_adt_def ( ) . map ( AdtDef :: did) 
417+     { 
418+         if  let  Some ( diag_name)  = cx. tcx . get_diagnostic_name ( recv_ty_defid) 
419+             && matches ! ( diag_name,  sym:: Option  | sym:: Result ) 
420+         { 
421+             return  true ; 
422+         } 
423+ 
424+         // Necessary for `core::ops::control_flow::ControlFlow` until a diagnostic item 
425+         // has been added. 
426+         let  def_path = cx. get_def_path ( recv_ty_defid) ; 
427+         if  def_path
428+             . iter ( ) 
429+             . map ( Symbol :: as_str) 
430+             . zip ( [ "core" ,  "ops" ,  "control_flow" ,  "ControlFlow" ] ) 
431+             . all ( |( sym,  s) | sym == s) 
432+         { 
433+             return  true ; 
434+         } 
435+     } 
436+     false 
437+ } 
0 commit comments