@@ -7,124 +7,149 @@ use rustc_hir::{
7
7
} ;
8
8
use rustc_lint:: LateContext ;
9
9
use rustc_middle:: lint:: in_external_macro;
10
- use rustc_span:: Span ;
10
+ use rustc_span:: { symbol :: Ident , Span } ;
11
11
12
12
use super :: HIDDEN_STATIC_LIFETIME ;
13
13
14
- // As a summary:
15
- //
16
- // A lifetime can only be changed if:
17
- // * Used in immutable references.
18
- // * Not behind a mutable reference.
19
- // * Not used in function types
20
- //
21
- // NOTE: Struct's fields follow the same rules as types
22
-
23
- pub ( super ) fn check_fn < ' tcx > ( cx : & LateContext < ' _ > , kind : FnKind < ' tcx > , decl : & ' tcx FnDecl < ' _ > , span : Span ) {
24
- if !in_external_macro ( cx. sess ( ) , span) &&
25
- let FnKind :: ItemFn ( _, generics, _) = kind {
26
-
27
- let mut v = FuncVisitor {
28
- ret_ty : & decl. output ,
29
- inputs : decl. inputs ,
30
- predicates : & generics. predicates ,
31
- lifetime_is_used : false
32
- } ;
33
-
34
- for param in generics. params {
35
- if let GenericParamKind :: Lifetime { kind } = param. kind && kind != LifetimeParamKind :: Elided {
36
- v. visit_generic_param ( param) ;
37
- if !v. lifetime_is_used {
38
- span_lint ( cx, HIDDEN_STATIC_LIFETIME , param. span , "hi" ) ;
39
- } ;
40
- }
41
- } ;
42
- }
14
+ struct V < ' a > {
15
+ // (Lifetime, Bounded typ)
16
+ lifetimes : Vec < & ' a GenericParam < ' a > > ,
43
17
}
44
18
45
- struct FuncVisitor < ' a > {
46
- ret_ty : & ' a FnRetTy < ' a > ,
47
- inputs : & ' a [ Ty < ' a > ] ,
48
- predicates : & ' a [ WherePredicate < ' a > ] ,
49
- lifetime_is_used : bool ,
50
- }
19
+ impl < ' a > Visitor < ' _ > for V < ' a > {
20
+ /// Remove all mutable lifetimes that aren't for T: 'static
21
+ fn visit_where_predicate ( & mut self , predicate : & WherePredicate < ' _ > ) {
22
+ if let WherePredicate :: BoundPredicate ( pred) = predicate {
23
+ for bound in pred. bounds {
24
+ // Check (for each lifetime) that the type they're associated with is 'static.
25
+ continue ;
26
+ }
27
+ }
28
+ }
51
29
52
- impl < ' v > Visitor < ' _ > for FuncVisitor < ' v > {
53
- fn visit_generic_param ( & mut self , param : & GenericParam < ' _ > ) {
54
- // Check inputs
55
- for input in self . inputs {
56
- if ref_uses_lifetime ( input, param) || check_path ( input, param) {
57
- dbg ! ( "@@@@@@@@@@@@@@@@@@@@@@@@" ) ;
58
- self . lifetime_is_used = true ;
59
- return ;
60
- } ;
61
- }
30
+ fn visit_ty ( & mut self , ty : & Ty < ' _ > ) {
31
+ let mut outer_continue: bool ;
32
+ let mut outer_break = false ;
33
+ let mut i = 0 ;
34
+ while i < self . lifetimes . len ( ) {
35
+ outer_continue = false ;
36
+ let lifetime = self . lifetimes [ i] ;
37
+
38
+ // Check references
39
+
40
+ let mut final_ty = ty;
41
+ let mut behind_mut_ref = false ;
42
+ while let TyKind :: Ref ( lt, mut_ty) = & final_ty. kind {
43
+ if mut_ty. mutbl . is_mut ( ) {
44
+ behind_mut_ref = true ;
45
+ } ;
62
46
63
- // Check return
64
- if let FnRetTy :: Return ( ret_ty) = self . ret_ty {
65
- if ref_uses_lifetime ( ret_ty, param) || check_path ( ret_ty, param) {
66
- dbg ! ( "============================" ) ;
67
- self . lifetime_is_used = true ;
68
- return ;
69
- } ;
70
- } ;
47
+ if lt. ident . name == lifetime. name . ident ( ) . name || behind_mut_ref {
48
+ if self . lifetimes . is_empty ( ) {
49
+ outer_continue = true ;
50
+ continue ;
51
+ }
52
+
53
+ self . lifetimes . remove ( i) ;
54
+ outer_continue = true ;
55
+
56
+ }
57
+ final_ty = mut_ty. ty ;
58
+ }
71
59
72
- // Check predicates
60
+ if outer_continue {
61
+ continue ;
62
+ } else if outer_break {
63
+ break ;
64
+ }
73
65
74
- for predicate in self . predicates {
75
- for bound in predicate. bounds ( ) {
76
- if let GenericBound :: Outlives ( lifetime) = bound &&
77
- lifetime. ident . name == param. name . ident ( ) . name {
78
- self . lifetime_is_used = true ;
79
- return ;
66
+ // Now final_ty is equal to ty.peel_refs()
67
+ // Check Paths:
68
+
69
+ if let TyKind :: Path ( QPath :: Resolved ( _, path) ) = final_ty. kind {
70
+ for segment in path. segments {
71
+ for argument in segment. args ( ) . args {
72
+ if let GenericArg :: Lifetime ( lt) = argument && lt. ident . name == lifetime. name . ident ( ) . name {
73
+ self . lifetimes . remove ( i) ;
74
+ outer_continue = true ;
75
+ continue ;
76
+ } ;
77
+ }
78
+ if outer_continue {
79
+ break ;
80
+ }
80
81
}
82
+ } ;
83
+
84
+ if outer_continue {
85
+ continue ;
81
86
}
87
+ i += 1 ;
82
88
}
83
89
}
84
- }
85
90
86
- fn ref_uses_lifetime ( mut ty : & Ty < ' _ > , lifetime : & GenericParam < ' _ > ) -> bool {
87
- while let TyKind :: Ref ( lt_ref, mut_ty) = & ty. kind {
88
- if lt_ref. ident . name == lifetime. name . ident ( ) . name && mut_ty. mutbl . is_not ( ) {
89
- return true ;
90
- } else {
91
- ty = mut_ty. ty ;
91
+ fn visit_fn_ret_ty < ' v > ( & mut self , ret_ty : & ' v FnRetTy < ' v > ) {
92
+ if let FnRetTy :: Return ( ty) = ret_ty {
93
+ let mut i = 0 ;
94
+ while i < self . lifetimes . len ( ) {
95
+ dbg ! ( self . lifetimes[ i] . name. ident( ) . as_str( ) ) ;
96
+ if ty_uses_lifetime ( ty, & self . lifetimes [ i] , & self ) {
97
+ self . lifetimes . remove ( i) ;
98
+ }
99
+ i += 1 ;
100
+ }
92
101
}
93
102
}
94
- false
95
103
}
96
104
97
- fn check_path ( ty : & Ty < ' _ > , lifetime : & GenericParam < ' _ > ) -> bool {
98
- if let TyKind :: Path ( QPath :: Resolved ( _, path) ) = ty. peel_refs ( ) . kind {
99
- for segment in path. segments {
100
- for arg in segment. args ( ) . args {
101
- if let GenericArg :: Lifetime ( lt_arg) = arg {
102
- if lt_arg. ident . name == lifetime. name . ident ( ) . name {
103
- return true ;
104
- } ;
105
- } else if let & GenericArg :: Type ( ty) = arg {
106
- dbg ! ( "!!!!!!!!!!!!!!!!!!!!!!!!!" ) ;
107
- return check_all_types ( ty, lifetime) ;
108
- } ;
109
- }
110
- }
111
- } ;
112
- false
105
+ pub ( super ) fn check_fn < ' tcx > ( cx : & LateContext < ' _ > , kind : FnKind < ' tcx > , decl : & ' tcx FnDecl < ' _ > , span : Span ) {
106
+ if !in_external_macro ( cx. sess ( ) , span) &&
107
+ let FnKind :: ItemFn ( _, generics, _) = kind {
108
+ let mut visitor = V {
109
+ lifetimes : Vec :: new ( )
110
+ } ;
111
+
112
+ // Fill visitor.lifetimes with function's lifetimes
113
+
114
+ for generic in generics. params {
115
+ if let GenericParamKind :: Lifetime { .. } = generic. kind {
116
+ visitor. lifetimes . push ( generic) ;
117
+ } ;
118
+ } ;
119
+
120
+ for input in decl. inputs {
121
+ visitor. visit_ty ( input) ;
122
+ }
123
+
124
+ for predicate in generics. predicates {
125
+ visitor. visit_where_predicate ( predicate) ;
126
+ }
127
+ visitor. visit_fn_ret_ty ( & decl. output ) ;
128
+
129
+ for generic in visitor. lifetimes {
130
+ span_lint_and_help ( cx,
131
+ HIDDEN_STATIC_LIFETIME ,
132
+ generic. span ,
133
+ "this lifetime can be changed to `'static`" ,
134
+ None ,
135
+ & format ! ( "try removing the lifetime parameter `{}` and changing references to `'static`" , generic. name. ident( ) . as_str( ) ) ) ;
136
+ }
137
+ } ;
113
138
}
114
139
115
- fn check_all_types ( ty : & Ty < ' _ > , lifetime : & GenericParam < ' _ > ) -> bool {
116
- fn ty_uses_lifetime ( ty : & Ty < ' _ > , generic : & GenericParam < ' _ > ) -> bool {
117
- if let TyKind :: Path ( QPath :: Resolved ( _, path) ) = ty. kind {
140
+ fn ty_uses_lifetime ( ty : & Ty < ' _ > , generic : & GenericParam , v : & V < ' _ > ) -> bool {
141
+ fn check_ty ( ty : & Ty < ' _ > , generic : & GenericParam , v : & V < ' _ > ) -> bool {
142
+ if let TyKind :: Path ( QPath :: Resolved ( _, path) ) = ty. kind {
118
143
for segment in path. segments {
119
144
if let Some ( GenericArgs { args, .. } ) = segment. args {
120
145
for arg in args. iter ( ) {
121
146
if let GenericArg :: Lifetime ( lifetime) = arg {
122
- if lifetime. ident . name == generic. name . ident ( ) . name {
147
+ if lifetime. ident . name == generic. name . ident ( ) . name {
123
148
// generic is used
124
149
return true ;
125
150
}
126
151
} else if let GenericArg :: Type ( ty) = arg {
127
- return classify_ty ( ty, generic) ;
152
+ return classify_ty ( ty, generic, v ) ;
128
153
}
129
154
}
130
155
}
@@ -134,37 +159,34 @@ fn check_all_types(ty: &Ty<'_>, lifetime: &GenericParam<'_>) -> bool {
134
159
}
135
160
136
161
#[ inline]
137
- fn barefn_uses_lifetime ( barefn : & BareFnTy < ' _ > , generic : & GenericParam < ' _ > ) -> bool {
138
- // Check inputs
139
- for input in barefn. decl . inputs {
140
- if ref_uses_lifetime ( input, generic) || check_path ( input, generic) {
141
- return false ;
142
- } ;
143
- }
144
-
145
- // Check return
146
- if let FnRetTy :: Return ( ret_ty) = barefn. decl . output {
147
- if check_path ( ret_ty, generic) {
148
- return false ;
149
- } ;
150
- } ;
151
- true
152
- }
162
+ fn barefn_uses_lifetime ( barefn : & BareFnTy < ' _ > , generic : & GenericParam , v : & V < ' _ > ) -> bool {
163
+ // let mut visitor = V {
164
+ // lifetimes: v.lifetimes.clone(),
165
+ // };
166
+
167
+ // for input in barefn.decl.inputs {
168
+ // visitor.visit_ty(input);
169
+ // }
170
+
171
+ // visitor.visit_fn_ret_ty(&barefn.decl.output);
172
+ // !visitor.lifetimes.contains(&generic)
173
+ true
174
+ }
153
175
154
176
#[ inline]
155
- fn tuple_uses_lifetime ( tuple : & [ Ty < ' _ > ] , generic : & GenericParam < ' _ > ) -> bool {
156
- tuple. iter ( ) . any ( |ty| classify_ty ( ty, generic) )
177
+ fn tuple_uses_lifetime ( tuple : & [ Ty < ' _ > ] , generic : & GenericParam , v : & V < ' _ > ) -> bool {
178
+ tuple. iter ( ) . any ( |ty| classify_ty ( ty, generic, v ) )
157
179
}
158
180
159
- fn opaquedef_uses_lifetime ( args : & [ GenericArg < ' _ > ] , generic : & GenericParam < ' _ > ) -> bool {
181
+ fn opaquedef_uses_lifetime ( args : & [ GenericArg < ' _ > ] , generic : & GenericParam , v : & V < ' _ > ) -> bool {
160
182
for arg in args. iter ( ) {
161
183
if let GenericArg :: Lifetime ( lifetime) = arg {
162
184
if lifetime. ident . name == generic. name . ident ( ) . name {
163
185
// generic is used
164
186
return true ;
165
187
}
166
188
} else if let GenericArg :: Type ( ty) = arg {
167
- return classify_ty ( ty, generic) ;
189
+ return classify_ty ( ty, generic, v ) ;
168
190
}
169
191
}
170
192
false
@@ -173,40 +195,41 @@ fn check_all_types(ty: &Ty<'_>, lifetime: &GenericParam<'_>) -> bool {
173
195
#[ inline]
174
196
fn traitobject_uses_lifetime ( lifetime : & Lifetime , traits : & [ PolyTraitRef < ' _ > ] , generic : & GenericParam < ' _ > ) -> bool {
175
197
if lifetime. ident . name == generic. name . ident ( ) . name {
176
- return true ;
198
+ return false ;
177
199
}
178
200
for PolyTraitRef {
179
201
bound_generic_params, ..
180
202
} in traits
181
203
{
182
- if bound_generic_params. iter ( ) . any ( |param| param. def_id == generic. def_id ) {
204
+ if bound_generic_params
205
+ . iter ( )
206
+ . any ( |param| param. name . ident ( ) . name == generic. name . ident ( ) . name )
207
+ {
183
208
return true ;
184
209
} ;
185
210
}
186
211
false
187
212
}
188
213
189
214
#[ inline]
190
- fn classify_ty ( ty : & Ty < ' _ > , generic : & GenericParam < ' _ > ) -> bool {
215
+ fn classify_ty ( ty : & Ty < ' _ > , generic : & GenericParam , v : & V < ' _ > ) -> bool {
191
216
match & ty. kind {
192
- TyKind :: Slice ( ty) | TyKind :: Array ( ty, _) => ty_uses_lifetime ( ty, generic) ,
193
- TyKind :: Ptr ( mut_ty) => ty_uses_lifetime ( mut_ty. ty , generic) ,
194
- TyKind :: BareFn ( barefnty) => barefn_uses_lifetime ( barefnty, generic) ,
195
- TyKind :: Tup ( tuple) => tuple_uses_lifetime ( tuple, generic) ,
196
- TyKind :: Path ( _) => ty_uses_lifetime ( ty, generic) ,
197
- TyKind :: OpaqueDef ( _, genericargs, _) => opaquedef_uses_lifetime ( genericargs, generic) ,
217
+ TyKind :: Slice ( ty) | TyKind :: Array ( ty, _) => check_ty ( ty, generic, v) ,
218
+ TyKind :: Ptr ( mut_ty) => check_ty ( mut_ty. ty , generic, v) ,
219
+ TyKind :: BareFn ( barefnty) => {
220
+ barefn_uses_lifetime ( barefnty, generic, v) } ,
221
+ TyKind :: Tup ( tuple) => tuple_uses_lifetime ( tuple, generic, v) ,
222
+ TyKind :: Path ( _) => check_ty ( ty, generic, v) ,
223
+ TyKind :: OpaqueDef ( _, genericargs, _) => opaquedef_uses_lifetime ( genericargs, generic, v) ,
198
224
TyKind :: TraitObject ( poly_trait_ref, lifetime, _) =>
199
225
traitobject_uses_lifetime ( lifetime, poly_trait_ref, generic) ,
200
226
TyKind :: Typeof ( _) // This is unused for now, this needs revising when Typeof is used.
201
227
| TyKind :: Err
202
- | TyKind :: Never => false ,
203
- TyKind :: Ref ( _, MutTy { ty , .. } ) => ref_uses_lifetime ( ty , generic ) ,
204
- TyKind :: Infer => true ,
228
+ | TyKind :: Never
229
+ | TyKind :: Ref ( _, _ )
230
+ | TyKind :: Infer => true ,
205
231
}
206
232
}
207
233
208
- // Separate refs from ty.
209
-
210
- // Now final_ty is equivalent to ty.peel_refs
211
- return classify_ty ( ty. peel_refs ( ) , lifetime) ;
234
+ return classify_ty ( ty. peel_refs ( ) , & generic, v) ;
212
235
}
0 commit comments