@@ -51,9 +51,11 @@ declare_lint_pass!(UseSelf => [USE_SELF]);
51
51
52
52
const SEGMENTS_MSG : & str = "segments should be composed of at least 1 element" ;
53
53
54
- fn span_use_self_lint ( cx : & LateContext < ' _ , ' _ > , path : & Path ) {
54
+ fn span_use_self_lint ( cx : & LateContext < ' _ , ' _ > , path : & Path , last_segment : Option < & PathSegment > ) {
55
+ let last_segment = last_segment. unwrap_or_else ( || path. segments . last ( ) . expect ( SEGMENTS_MSG ) ) ;
56
+
55
57
// Path segments only include actual path, no methods or fields.
56
- let last_path_span = path . segments . last ( ) . expect ( SEGMENTS_MSG ) . ident . span ;
58
+ let last_path_span = last_segment . ident . span ;
57
59
// Only take path up to the end of last_path_span.
58
60
let span = path. span . with_hi ( last_path_span. hi ( ) ) ;
59
61
@@ -80,22 +82,18 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> {
80
82
let trait_ty = self . trait_type_walker . next ( ) ;
81
83
let impl_ty = self . impl_type_walker . next ( ) ;
82
84
83
- if let TyKind :: Path ( QPath :: Resolved ( _, path) ) = & t. node {
85
+ if_chain ! {
86
+ if let TyKind :: Path ( QPath :: Resolved ( _, path) ) = & t. node;
87
+
84
88
// The implementation and trait types don't match which means that
85
89
// the concrete type was specified by the implementation
86
- if impl_ty != trait_ty {
87
- if let Some ( impl_ty) = impl_ty {
88
- if self . item_type == impl_ty {
89
- let is_self_ty = if let def:: Res :: SelfTy ( ..) = path. res {
90
- true
91
- } else {
92
- false
93
- } ;
94
-
95
- if !is_self_ty {
96
- span_use_self_lint ( self . cx , path) ;
97
- }
98
- }
90
+ if impl_ty != trait_ty;
91
+ if let Some ( impl_ty) = impl_ty;
92
+ if self . item_type == impl_ty;
93
+ then {
94
+ match path. res {
95
+ def:: Res :: SelfTy ( ..) => { } ,
96
+ _ => span_use_self_lint( self . cx, path, None )
99
97
}
100
98
}
101
99
}
@@ -220,15 +218,35 @@ struct UseSelfVisitor<'a, 'tcx> {
220
218
221
219
impl < ' a , ' tcx > Visitor < ' tcx > for UseSelfVisitor < ' a , ' tcx > {
222
220
fn visit_path ( & mut self , path : & ' tcx Path , _id : HirId ) {
221
+ if path. segments . len ( ) >= 2 {
222
+ let last_but_one = & path. segments [ path. segments . len ( ) - 2 ] ;
223
+ if last_but_one. ident . name != kw:: SelfUpper {
224
+ let enum_def_id = match path. res {
225
+ Res :: Def ( DefKind :: Variant , variant_def_id) =>
226
+ self . cx . tcx . parent ( variant_def_id) ,
227
+ Res :: Def ( DefKind :: Ctor ( def:: CtorOf :: Variant , _) , ctor_def_id) => {
228
+ let variant_def_id = self . cx . tcx . parent ( ctor_def_id) ;
229
+ variant_def_id. and_then ( |def_id| self . cx . tcx . parent ( def_id) )
230
+ }
231
+ _ => None
232
+ } ;
233
+
234
+ if self . item_path . res . opt_def_id ( ) == enum_def_id {
235
+ span_use_self_lint ( self . cx , path, Some ( last_but_one) ) ;
236
+ }
237
+ }
238
+ }
239
+
223
240
if path. segments . last ( ) . expect ( SEGMENTS_MSG ) . ident . name != kw:: SelfUpper {
224
241
if self . item_path . res == path. res {
225
- span_use_self_lint ( self . cx , path) ;
226
- } else if let Res :: Def ( DefKind :: Ctor ( def:: CtorOf :: Struct , CtorKind :: Fn ) , ctor_did ) = path. res {
227
- if self . item_path . res . opt_def_id ( ) == self . cx . tcx . parent ( ctor_did ) {
228
- span_use_self_lint ( self . cx , path) ;
242
+ span_use_self_lint ( self . cx , path, None ) ;
243
+ } else if let Res :: Def ( DefKind :: Ctor ( def:: CtorOf :: Struct , CtorKind :: Fn ) , ctor_def_id ) = path. res {
244
+ if self . item_path . res . opt_def_id ( ) == self . cx . tcx . parent ( ctor_def_id ) {
245
+ span_use_self_lint ( self . cx , path, None ) ;
229
246
}
230
247
}
231
248
}
249
+
232
250
walk_path ( self , path) ;
233
251
}
234
252
0 commit comments