@@ -59,8 +59,6 @@ declare_clippy_lint! {
59
59
pub struct UseSelf {
60
60
msrv : Option < RustcVersion > ,
61
61
stack : Vec < StackItem > ,
62
- types_to_skip : Vec < HirId > ,
63
- types_to_lint : Vec < HirId > ,
64
62
}
65
63
66
64
const USE_SELF_MSRV : RustcVersion = RustcVersion :: new ( 1 , 37 , 0 ) ;
@@ -75,11 +73,13 @@ impl UseSelf {
75
73
}
76
74
}
77
75
78
- #[ derive( Debug , PartialEq , Eq , Copy , Clone ) ]
76
+ #[ derive( Debug ) ]
79
77
enum StackItem {
80
78
Check {
81
79
hir_id : HirId ,
82
80
impl_trait_ref_def_id : Option < LocalDefId > ,
81
+ types_to_skip : Vec < HirId > ,
82
+ types_to_lint : Vec < HirId > ,
83
83
} ,
84
84
NoCheck ,
85
85
}
@@ -116,6 +116,8 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
116
116
self . stack . push ( StackItem :: Check {
117
117
hir_id : hir_self_ty. hir_id ,
118
118
impl_trait_ref_def_id,
119
+ types_to_lint : Vec :: new ( ) ,
120
+ types_to_skip : Vec :: new ( ) ,
119
121
} ) ;
120
122
} else {
121
123
self . stack . push ( StackItem :: NoCheck ) ;
@@ -149,7 +151,11 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
149
151
// declaration. The collection of those types is all this method implementation does.
150
152
if_chain ! {
151
153
if let ImplItemKind :: Fn ( FnSig { decl, .. } , ..) = impl_item. kind;
152
- if let Some ( StackItem :: Check { impl_trait_ref_def_id: Some ( def_id) , .. } ) = self . stack. last( ) . copied( ) ;
154
+ if let Some ( & mut StackItem :: Check {
155
+ impl_trait_ref_def_id: Some ( def_id) ,
156
+ ref mut types_to_skip,
157
+ ..
158
+ } ) = self . stack. last_mut( ) ;
153
159
if let Some ( impl_trait_ref) = cx. tcx. impl_trait_ref( def_id) ;
154
160
then {
155
161
// `self_ty` is the semantic self type of `impl <trait> for <type>`. This cannot be
@@ -191,17 +197,13 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
191
197
if trait_sem_ty. walk( ) . any( |inner| inner == self_ty. into( ) ) {
192
198
let mut visitor = SkipTyCollector :: default ( ) ;
193
199
visitor. visit_ty( & impl_hir_ty) ;
194
- self . types_to_skip. extend( visitor. types_to_skip) ;
200
+ types_to_skip. extend( visitor. types_to_skip) ;
195
201
}
196
202
}
197
203
}
198
204
}
199
205
}
200
206
201
- fn check_impl_item_post ( & mut self , _: & LateContext < ' _ > , _: & hir:: ImplItem < ' _ > ) {
202
- self . types_to_skip . clear ( ) ;
203
- }
204
-
205
207
fn check_body ( & mut self , cx : & LateContext < ' tcx > , body : & ' tcx hir:: Body < ' _ > ) {
206
208
// `hir_ty_to_ty` cannot be called in `Body`s or it will panic (sometimes). But in bodies
207
209
// we can use `cx.typeck_results.node_type(..)` to get the `ty::Ty` from a `hir::Ty`.
@@ -211,7 +213,13 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
211
213
// which shouldn't, with a visitor. We could directly lint in the visitor, but then we
212
214
// could only allow this lint on item scope. And we would have to check if those types are
213
215
// already dealt with in `check_ty` anyway.
214
- if let Some ( StackItem :: Check { hir_id, .. } ) = self . stack . last ( ) {
216
+ if let Some ( StackItem :: Check {
217
+ hir_id,
218
+ types_to_lint,
219
+ types_to_skip,
220
+ ..
221
+ } ) = self . stack . last_mut ( )
222
+ {
215
223
let self_ty = ty_from_hir_id ( cx, * hir_id) ;
216
224
217
225
let mut visitor = LintTyCollector {
@@ -221,25 +229,36 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
221
229
types_to_skip : vec ! [ ] ,
222
230
} ;
223
231
visitor. visit_expr ( & body. value ) ;
224
- self . types_to_lint . extend ( visitor. types_to_lint ) ;
225
- self . types_to_skip . extend ( visitor. types_to_skip ) ;
232
+ types_to_lint. extend ( visitor. types_to_lint ) ;
233
+ types_to_skip. extend ( visitor. types_to_skip ) ;
226
234
}
227
235
}
228
236
229
- fn check_body_post ( & mut self , _: & LateContext < ' _ > , _: & hir:: Body < ' _ > ) {
230
- self . types_to_lint . clear ( ) ;
231
- }
232
-
233
237
fn check_ty ( & mut self , cx : & LateContext < ' _ > , hir_ty : & hir:: Ty < ' _ > ) {
234
- if in_macro ( hir_ty. span )
235
- | in_impl ( cx, hir_ty)
236
- | self . types_to_skip . contains ( & hir_ty. hir_id )
237
- | !meets_msrv ( self . msrv . as_ref ( ) , & USE_SELF_MSRV )
238
- {
238
+ if in_macro ( hir_ty. span ) | in_impl ( cx, hir_ty) | !meets_msrv ( self . msrv . as_ref ( ) , & USE_SELF_MSRV ) {
239
239
return ;
240
240
}
241
241
242
- let lint_dependend_on_expr_kind = || {
242
+ let lint_dependend_on_expr_kind = if let Some ( StackItem :: Check {
243
+ hir_id,
244
+ types_to_lint,
245
+ types_to_skip,
246
+ ..
247
+ } ) = self . stack . last ( )
248
+ {
249
+ if types_to_skip. contains ( & hir_ty. hir_id ) {
250
+ false
251
+ } else if types_to_lint. contains ( & hir_ty. hir_id ) {
252
+ true
253
+ } else {
254
+ let self_ty = ty_from_hir_id ( cx, * hir_id) ;
255
+ should_lint_ty ( hir_ty, hir_ty_to_ty ( cx. tcx , hir_ty) , self_ty)
256
+ }
257
+ } else {
258
+ false
259
+ } ;
260
+
261
+ if lint_dependend_on_expr_kind {
243
262
// FIXME: this span manipulation should not be necessary
244
263
// @flip1995 found an ast lowering issue in
245
264
// https://github.com/rust-lang/rust/blob/master/src/librustc_ast_lowering/path.rs#l142-l162
@@ -250,16 +269,6 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
250
269
} ) ) => span_lint_until_last_segment ( cx, hir_ty. span , segment) ,
251
270
_ => span_lint ( cx, hir_ty. span ) ,
252
271
}
253
- } ;
254
-
255
- if self . types_to_lint . contains ( & hir_ty. hir_id ) {
256
- lint_dependend_on_expr_kind ( ) ;
257
- } else if let Some ( StackItem :: Check { hir_id, .. } ) = self . stack . last ( ) {
258
- let self_ty = ty_from_hir_id ( cx, * hir_id) ;
259
-
260
- if should_lint_ty ( hir_ty, hir_ty_to_ty ( cx. tcx , hir_ty) , self_ty) {
261
- lint_dependend_on_expr_kind ( ) ;
262
- }
263
272
}
264
273
}
265
274
0 commit comments