@@ -2117,48 +2117,77 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
21172117 // First (determined here), if `self` is by-reference, then the
21182118 // implied output region is the region of the self parameter.
21192119 if has_self {
2120- // Look for `self: &'a Self` - also desugared from `&'a self`,
2121- // and if that matches, use it for elision and return early.
2122- let is_self_ty = |res : Res | {
2123- if let Res :: SelfTy ( ..) = res {
2124- return true ;
2125- }
2126-
2127- // Can't always rely on literal (or implied) `Self` due
2128- // to the way elision rules were originally specified.
2129- let impl_self = impl_self. map ( |ty| & ty. node ) ;
2130- if let Some ( & hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , ref path) ) ) = impl_self {
2131- match path. res {
2132- // Whitelist the types that unambiguously always
2133- // result in the same type constructor being used
2134- // (it can't differ between `Self` and `self`).
2135- Res :: Def ( DefKind :: Struct , _)
2136- | Res :: Def ( DefKind :: Union , _)
2137- | Res :: Def ( DefKind :: Enum , _)
2138- | Res :: PrimTy ( _) => {
2139- return res == path. res
2120+ struct SelfVisitor < ' a > {
2121+ map : & ' a NamedRegionMap ,
2122+ impl_self : Option < & ' a hir:: TyKind > ,
2123+ lifetime : Set1 < Region > ,
2124+ }
2125+
2126+ impl SelfVisitor < ' _ > {
2127+ // Look for `self: &'a Self` - also desugared from `&'a self`,
2128+ // and if that matches, use it for elision and return early.
2129+ fn is_self_ty ( & self , res : Res ) -> bool {
2130+ if let Res :: SelfTy ( ..) = res {
2131+ return true ;
2132+ }
2133+
2134+ // Can't always rely on literal (or implied) `Self` due
2135+ // to the way elision rules were originally specified.
2136+ if let Some ( & hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , ref path) ) ) =
2137+ self . impl_self
2138+ {
2139+ match path. res {
2140+ // Whitelist the types that unambiguously always
2141+ // result in the same type constructor being used
2142+ // (it can't differ between `Self` and `self`).
2143+ Res :: Def ( DefKind :: Struct , _)
2144+ | Res :: Def ( DefKind :: Union , _)
2145+ | Res :: Def ( DefKind :: Enum , _)
2146+ | Res :: PrimTy ( _) => {
2147+ return res == path. res
2148+ }
2149+ _ => { }
21402150 }
2141- _ => { }
21422151 }
2152+
2153+ false
21432154 }
2155+ }
21442156
2145- false
2146- } ;
2157+ impl < ' a > Visitor < ' a > for SelfVisitor < ' a > {
2158+ fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' a > {
2159+ NestedVisitorMap :: None
2160+ }
21472161
2148- if let hir:: TyKind :: Rptr ( lifetime_ref, ref mt) = inputs[ 0 ] . node {
2149- if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , ref path) ) = mt. ty . node {
2150- if is_self_ty ( path. res ) {
2151- if let Some ( & lifetime) = self . map . defs . get ( & lifetime_ref. hir_id ) {
2152- let scope = Scope :: Elision {
2153- elide : Elide :: Exact ( lifetime) ,
2154- s : self . scope ,
2155- } ;
2156- self . with ( scope, |_, this| this. visit_ty ( output) ) ;
2157- return ;
2162+ fn visit_ty ( & mut self , ty : & ' a hir:: Ty ) {
2163+ if let hir:: TyKind :: Rptr ( lifetime_ref, ref mt) = ty. node {
2164+ if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , ref path) ) = mt. ty . node
2165+ {
2166+ if self . is_self_ty ( path. res ) {
2167+ if let Some ( lifetime) = self . map . defs . get ( & lifetime_ref. hir_id ) {
2168+ self . lifetime . insert ( * lifetime) ;
2169+ }
2170+ }
21582171 }
21592172 }
2173+ intravisit:: walk_ty ( self , ty)
21602174 }
21612175 }
2176+
2177+ let mut visitor = SelfVisitor {
2178+ map : self . map ,
2179+ impl_self : impl_self. map ( |ty| & ty. node ) ,
2180+ lifetime : Set1 :: Empty ,
2181+ } ;
2182+ visitor. visit_ty ( & inputs[ 0 ] ) ;
2183+ if let Set1 :: One ( lifetime) = visitor. lifetime {
2184+ let scope = Scope :: Elision {
2185+ elide : Elide :: Exact ( lifetime) ,
2186+ s : self . scope ,
2187+ } ;
2188+ self . with ( scope, |_, this| this. visit_ty ( output) ) ;
2189+ return ;
2190+ }
21622191 }
21632192
21642193 // Second, if there was exactly one lifetime (either a substitution or a
0 commit comments