@@ -10,17 +10,64 @@ use rustc_span::{sym, Span};
1010
1111use  super :: UNNECESSARY_FALLIBLE_CONVERSIONS ; 
1212
13+ #[ derive( Copy ,  Clone ) ]  
14+ enum  SpansKind  { 
15+  TraitFn  {  trait_span :  Span ,  fn_span :  Span  } , 
16+  Fn  {  fn_span :  Span  } , 
17+ } 
18+ 
1319/// What function is being called and whether that call is written as a method call or a function 
1420/// call 
15- #[ derive( Clone ) ]  
21+ #[ derive( Copy ,   Clone ) ]  
1622#[ expect( clippy:: enum_variant_names) ]  
1723enum  FunctionKind  { 
1824 /// `T::try_from(U)` 
19- TryFromFunction ( Option < Vec < Span > > ) , 
25+ TryFromFunction ( Option < SpansKind > ) , 
2026 /// `t.try_into()` 
2127TryIntoMethod , 
2228 /// `U::try_into(t)` 
23- TryIntoFunction ( Option < Vec < Span > > ) , 
29+ TryIntoFunction ( Option < SpansKind > ) , 
30+ } 
31+ 
32+ impl  FunctionKind  { 
33+  fn  applicability ( & self ,  parent_unwrap_call :  & Option < Span > )  -> Applicability  { 
34+  if  parent_unwrap_call. is_none ( )  { 
35+  return  Applicability :: Unspecified ; 
36+  } 
37+  match  & self  { 
38+  FunctionKind :: TryFromFunction ( None )  | FunctionKind :: TryIntoFunction ( None )  => Applicability :: Unspecified , 
39+  _ => Applicability :: MachineApplicable , 
40+  } 
41+  } 
42+ 
43+  fn  default_sugg ( & self ,  primary_span :  Span )  -> Vec < ( Span ,  String ) >  { 
44+  match  * self  { 
45+  FunctionKind :: TryFromFunction ( _)  => vec ! [ ( primary_span,  String :: from( "From::from" ) ) ] , 
46+  FunctionKind :: TryIntoFunction ( _)  => vec ! [ ( primary_span,  String :: from( "Into::into" ) ) ] , 
47+  FunctionKind :: TryIntoMethod  => vec ! [ ( primary_span,  String :: from( "into" ) ) ] , 
48+  } 
49+  } 
50+ 
51+  fn  machine_applicable_sugg ( & self ,  primary_span :  Span ,  unwrap_span :  Span )  -> Vec < ( Span ,  String ) >  { 
52+  let  mut  sugg = match  * self  { 
53+  FunctionKind :: TryFromFunction ( Some ( spans) )  => match  spans { 
54+  SpansKind :: TraitFn  {  trait_span,  fn_span }  => { 
55+  vec ! [ ( trait_span,  String :: from( "From" ) ) ,  ( fn_span,  String :: from( "from" ) ) ] 
56+  } , 
57+  SpansKind :: Fn  {  fn_span }  => vec ! [ ( fn_span,  String :: from( "from" ) ) ] , 
58+  } , 
59+  FunctionKind :: TryIntoFunction ( Some ( spans) )  => match  spans { 
60+  SpansKind :: TraitFn  {  trait_span,  fn_span }  => { 
61+  vec ! [ ( trait_span,  String :: from( "Into" ) ) ,  ( fn_span,  String :: from( "into" ) ) ] 
62+  } , 
63+  SpansKind :: Fn  {  fn_span }  => vec ! [ ( fn_span,  String :: from( "into" ) ) ] , 
64+  } , 
65+  FunctionKind :: TryIntoMethod  => vec ! [ ( primary_span,  String :: from( "into" ) ) ] , 
66+  _ => unreachable ! ( ) , 
67+  } ; 
68+  sugg. push ( ( unwrap_span,  String :: new ( ) ) ) ; 
69+  sugg
70+  } 
2471} 
2572
2673fn  check < ' tcx > ( 
@@ -69,47 +116,17 @@ fn check<'tcx>(
69116 primary_span
70117 } ; 
71118
72-  let  ( source_ty,  target_ty,  sugg,  applicability)  = match  ( kind,  parent_unwrap_call)  { 
73-  ( FunctionKind :: TryIntoMethod ,  Some ( unwrap_span) )  => { 
74-  let  sugg = vec ! [ ( primary_span,  String :: from( "into" ) ) ,  ( unwrap_span,  String :: new( ) ) ] ; 
75-  ( self_ty,  other_ty,  sugg,  Applicability :: MachineApplicable ) 
76-  } , 
77-  ( FunctionKind :: TryFromFunction ( Some ( spans) ) ,  Some ( unwrap_span) )  => { 
78-  let  sugg = match  spans. len ( )  { 
79-  1  => vec ! [ ( spans[ 0 ] ,  String :: from( "from" ) ) ,  ( unwrap_span,  String :: new( ) ) ] , 
80-  2  => vec ! [ 
81-  ( spans[ 0 ] ,  String :: from( "From" ) ) , 
82-  ( spans[ 1 ] ,  String :: from( "from" ) ) , 
83-  ( unwrap_span,  String :: new( ) ) , 
84-  ] , 
85-  _ => unreachable ! ( ) , 
86-  } ; 
87-  ( other_ty,  self_ty,  sugg,  Applicability :: MachineApplicable ) 
88-  } , 
89-  ( FunctionKind :: TryIntoFunction ( Some ( spans) ) ,  Some ( unwrap_span) )  => { 
90-  let  sugg = match  spans. len ( )  { 
91-  1  => vec ! [ ( spans[ 0 ] ,  String :: from( "into" ) ) ,  ( unwrap_span,  String :: new( ) ) ] , 
92-  2  => vec ! [ 
93-  ( spans[ 0 ] ,  String :: from( "Into" ) ) , 
94-  ( spans[ 1 ] ,  String :: from( "into" ) ) , 
95-  ( unwrap_span,  String :: new( ) ) , 
96-  ] , 
97-  _ => unreachable ! ( ) , 
98-  } ; 
99-  ( self_ty,  other_ty,  sugg,  Applicability :: MachineApplicable ) 
100-  } , 
101-  ( FunctionKind :: TryFromFunction ( _) ,  _)  => { 
102-  let  sugg = vec ! [ ( primary_span,  String :: from( "From::from" ) ) ] ; 
103-  ( other_ty,  self_ty,  sugg,  Applicability :: Unspecified ) 
104-  } , 
105-  ( FunctionKind :: TryIntoFunction ( _) ,  _)  => { 
106-  let  sugg = vec ! [ ( primary_span,  String :: from( "Into::into" ) ) ] ; 
107-  ( self_ty,  other_ty,  sugg,  Applicability :: Unspecified ) 
108-  } , 
109-  ( FunctionKind :: TryIntoMethod ,  _)  => { 
110-  let  sugg = vec ! [ ( primary_span,  String :: from( "into" ) ) ] ; 
111-  ( self_ty,  other_ty,  sugg,  Applicability :: Unspecified ) 
112-  } , 
119+  let  ( source_ty,  target_ty)  = match  kind { 
120+  FunctionKind :: TryIntoMethod  | FunctionKind :: TryIntoFunction ( _)  => ( self_ty,  other_ty) , 
121+  FunctionKind :: TryFromFunction ( _)  => ( other_ty,  self_ty) , 
122+  } ; 
123+ 
124+  let  applicability = kind. applicability ( & parent_unwrap_call) ; 
125+ 
126+  let  sugg = if  applicability == Applicability :: MachineApplicable  { 
127+  kind. machine_applicable_sugg ( primary_span,  parent_unwrap_call. unwrap ( ) ) 
128+  }  else  { 
129+  kind. default_sugg ( primary_span) 
113130 } ; 
114131
115132 span_lint_and_then ( 
@@ -151,10 +168,18 @@ pub(super) fn check_function(cx: &LateContext<'_>, expr: &Expr<'_>, callee: &Exp
151168 { 
152169 let  qpath_spans = match  qpath { 
153170 QPath :: Resolved ( _,  path)  => { 
154-  let  segments = path. segments . iter ( ) . map ( |seg| seg. ident ) . collect :: < Vec < _ > > ( ) ; 
155-  ( segments. len ( )  == 2 ) . then ( || vec ! [ segments[ 0 ] . span,  segments[ 1 ] . span] ) 
171+  if  let  [ trait_seg,  fn_seg]  = path. segments  { 
172+  Some ( SpansKind :: TraitFn  { 
173+  trait_span :  trait_seg. ident . span , 
174+  fn_span :  fn_seg. ident . span , 
175+  } ) 
176+  }  else  { 
177+  None 
178+  } 
156179 } , 
157-  QPath :: TypeRelative ( _,  seg)  => Some ( vec ! [ seg. ident. span] ) , 
180+  QPath :: TypeRelative ( _,  seg)  => Some ( SpansKind :: Fn  { 
181+  fn_span :  seg. ident . span , 
182+  } ) , 
158183 QPath :: LangItem ( _,  _)  => unreachable ! ( "`TryFrom` and `TryInto` are not lang items" ) , 
159184 } ; 
160185
0 commit comments