@@ -51,9 +51,11 @@ declare_lint_pass!(UseSelf => [USE_SELF]);
5151
5252const SEGMENTS_MSG : & str = "segments should be composed of at least 1 element" ;
5353
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+
5557 // 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 ;
5759 // Only take path up to the end of last_path_span.
5860 let span = path. span . with_hi ( last_path_span. hi ( ) ) ;
5961
@@ -80,22 +82,18 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> {
8082 let trait_ty = self . trait_type_walker . next ( ) ;
8183 let impl_ty = self . impl_type_walker . next ( ) ;
8284
83- if let TyKind :: Path ( QPath :: Resolved ( _, path) ) = & t. node {
85+ if_chain ! {
86+ if let TyKind :: Path ( QPath :: Resolved ( _, path) ) = & t. node;
87+
8488 // The implementation and trait types don't match which means that
8589 // 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 )
9997 }
10098 }
10199 }
@@ -220,15 +218,35 @@ struct UseSelfVisitor<'a, 'tcx> {
220218
221219impl < ' a , ' tcx > Visitor < ' tcx > for UseSelfVisitor < ' a , ' tcx > {
222220 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+
223240 if path. segments . last ( ) . expect ( SEGMENTS_MSG ) . ident . name != kw:: SelfUpper {
224241 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 ) ;
229246 }
230247 }
231248 }
249+
232250 walk_path ( self , path) ;
233251 }
234252
0 commit comments