@@ -2146,48 +2146,77 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
21462146 // First (determined here), if `self` is by-reference, then the
21472147 // implied output region is the region of the self parameter.
21482148 if has_self {
2149- // Look for `self: &'a Self` - also desugared from `&'a self`,
2150- // and if that matches, use it for elision and return early.
2151- let is_self_ty = |res : Res | {
2152- if let Res :: SelfTy ( ..) = res {
2153- return true ;
2154- }
2155-
2156- // Can't always rely on literal (or implied) `Self` due
2157- // to the way elision rules were originally specified.
2158- let impl_self = impl_self. map ( |ty| & ty. node ) ;
2159- if let Some ( & hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , ref path) ) ) = impl_self {
2160- match path. res {
2161- // Whitelist the types that unambiguously always
2162- // result in the same type constructor being used
2163- // (it can't differ between `Self` and `self`).
2164- Res :: Def ( DefKind :: Struct , _)
2165- | Res :: Def ( DefKind :: Union , _)
2166- | Res :: Def ( DefKind :: Enum , _)
2167- | Res :: PrimTy ( _) => {
2168- return res == path. res
2149+ struct SelfVisitor < ' a > {
2150+ map : & ' a NamedRegionMap ,
2151+ impl_self : Option < & ' a hir:: TyKind > ,
2152+ lifetime : Set1 < Region > ,
2153+ }
2154+
2155+ impl SelfVisitor < ' _ > {
2156+ // Look for `self: &'a Self` - also desugared from `&'a self`,
2157+ // and if that matches, use it for elision and return early.
2158+ fn is_self_ty ( & self , res : Res ) -> bool {
2159+ if let Res :: SelfTy ( ..) = res {
2160+ return true ;
2161+ }
2162+
2163+ // Can't always rely on literal (or implied) `Self` due
2164+ // to the way elision rules were originally specified.
2165+ if let Some ( & hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , ref path) ) ) =
2166+ self . impl_self
2167+ {
2168+ match path. res {
2169+ // Whitelist the types that unambiguously always
2170+ // result in the same type constructor being used
2171+ // (it can't differ between `Self` and `self`).
2172+ Res :: Def ( DefKind :: Struct , _)
2173+ | Res :: Def ( DefKind :: Union , _)
2174+ | Res :: Def ( DefKind :: Enum , _)
2175+ | Res :: PrimTy ( _) => {
2176+ return res == path. res
2177+ }
2178+ _ => { }
21692179 }
2170- _ => { }
21712180 }
2181+
2182+ false
21722183 }
2184+ }
21732185
2174- false
2175- } ;
2186+ impl < ' a > Visitor < ' a > for SelfVisitor < ' a > {
2187+ fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' a > {
2188+ NestedVisitorMap :: None
2189+ }
21762190
2177- if let hir:: TyKind :: Rptr ( lifetime_ref, ref mt) = inputs[ 0 ] . node {
2178- if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , ref path) ) = mt. ty . node {
2179- if is_self_ty ( path. res ) {
2180- if let Some ( & lifetime) = self . map . defs . get ( & lifetime_ref. hir_id ) {
2181- let scope = Scope :: Elision {
2182- elide : Elide :: Exact ( lifetime) ,
2183- s : self . scope ,
2184- } ;
2185- self . with ( scope, |_, this| this. visit_ty ( output) ) ;
2186- return ;
2191+ fn visit_ty ( & mut self , ty : & ' a hir:: Ty ) {
2192+ if let hir:: TyKind :: Rptr ( lifetime_ref, ref mt) = ty. node {
2193+ if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , ref path) ) = mt. ty . node
2194+ {
2195+ if self . is_self_ty ( path. res ) {
2196+ if let Some ( lifetime) = self . map . defs . get ( & lifetime_ref. hir_id ) {
2197+ self . lifetime . insert ( * lifetime) ;
2198+ }
2199+ }
21872200 }
21882201 }
2202+ intravisit:: walk_ty ( self , ty)
21892203 }
21902204 }
2205+
2206+ let mut visitor = SelfVisitor {
2207+ map : self . map ,
2208+ impl_self : impl_self. map ( |ty| & ty. node ) ,
2209+ lifetime : Set1 :: Empty ,
2210+ } ;
2211+ visitor. visit_ty ( & inputs[ 0 ] ) ;
2212+ if let Set1 :: One ( lifetime) = visitor. lifetime {
2213+ let scope = Scope :: Elision {
2214+ elide : Elide :: Exact ( lifetime) ,
2215+ s : self . scope ,
2216+ } ;
2217+ self . with ( scope, |_, this| this. visit_ty ( output) ) ;
2218+ return ;
2219+ }
21912220 }
21922221
21932222 // Second, if there was exactly one lifetime (either a substitution or a
0 commit comments