@@ -10,17 +10,64 @@ use rustc_span::{sym, Span};
10
10
11
11
use super :: UNNECESSARY_FALLIBLE_CONVERSIONS ;
12
12
13
+ #[ derive( Copy , Clone ) ]
14
+ enum SpansKind {
15
+ TraitFn { trait_span : Span , fn_span : Span } ,
16
+ Fn { fn_span : Span } ,
17
+ }
18
+
13
19
/// What function is being called and whether that call is written as a method call or a function
14
20
/// call
15
- #[ derive( Clone ) ]
21
+ #[ derive( Copy , Clone ) ]
16
22
#[ expect( clippy:: enum_variant_names) ]
17
23
enum FunctionKind {
18
24
/// `T::try_from(U)`
19
- TryFromFunction ( Option < Vec < Span > > ) ,
25
+ TryFromFunction ( Option < SpansKind > ) ,
20
26
/// `t.try_into()`
21
27
TryIntoMethod ,
22
28
/// `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
+ }
24
71
}
25
72
26
73
fn check < ' tcx > (
@@ -69,47 +116,17 @@ fn check<'tcx>(
69
116
primary_span
70
117
} ;
71
118
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)
113
130
} ;
114
131
115
132
span_lint_and_then (
@@ -151,10 +168,18 @@ pub(super) fn check_function(cx: &LateContext<'_>, expr: &Expr<'_>, callee: &Exp
151
168
{
152
169
let qpath_spans = match qpath {
153
170
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
+ }
156
179
} ,
157
- QPath :: TypeRelative ( _, seg) => Some ( vec ! [ seg. ident. span] ) ,
180
+ QPath :: TypeRelative ( _, seg) => Some ( SpansKind :: Fn {
181
+ fn_span : seg. ident . span ,
182
+ } ) ,
158
183
QPath :: LangItem ( _, _) => unreachable ! ( "`TryFrom` and `TryInto` are not lang items" ) ,
159
184
} ;
160
185
0 commit comments