@@ -89,9 +89,12 @@ struct LifetimeContext<'a, 'tcx: 'a> {
8989
9090#[ derive( PartialEq , Debug ) ]
9191enum ScopeChain < ' a > {
92- /// EarlyScope(['a, 'b, ...], s) extends s with early-bound
93- /// lifetimes.
94- EarlyScope ( & ' a [ hir:: LifetimeDef ] , Scope < ' a > ) ,
92+ /// EarlyScope(['a, 'b, ...], start, s) extends s with early-bound
93+ /// lifetimes, with consecutive parameter indices from `start`.
94+ /// That is, 'a has index `start`, 'b has index `start + 1`, etc.
95+ /// Indices before `start` correspond to other generic parameters
96+ /// of a parent item (trait/impl of a method), or `Self` in traits.
97+ EarlyScope ( & ' a [ hir:: LifetimeDef ] , u32 , Scope < ' a > ) ,
9598 /// LateScope(['a, 'b, ...], s) extends s with late-bound
9699 /// lifetimes introduced by the declaration binder_id.
97100 LateScope ( & ' a [ hir:: LifetimeDef ] , Scope < ' a > ) ,
@@ -157,7 +160,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for LifetimeContext<'a, 'tcx> {
157160 hir:: ItemImpl ( _, _, ref generics, _, _, _) => {
158161 // These kinds of items have only early bound lifetime parameters.
159162 let lifetimes = & generics. lifetimes ;
160- this. with ( EarlyScope ( lifetimes, & ROOT_SCOPE ) , |old_scope, this| {
163+ let start = if let hir:: ItemTrait ( ..) = item. node {
164+ 1 // Self comes before lifetimes
165+ } else {
166+ 0
167+ } ;
168+ this. with ( EarlyScope ( lifetimes, start, & ROOT_SCOPE ) , |old_scope, this| {
161169 this. check_lifetime_defs ( old_scope, lifetimes) ;
162170 intravisit:: walk_item ( this, item) ;
163171 } ) ;
@@ -461,7 +469,7 @@ fn extract_labels(ctxt: &mut LifetimeContext, b: &hir::Block) {
461469 FnScope { s, .. } => { scope = s; }
462470 RootScope => { return ; }
463471
464- EarlyScope ( lifetimes, s) |
472+ EarlyScope ( lifetimes, _ , s) |
465473 LateScope ( lifetimes, s) => {
466474 for lifetime_def in lifetimes {
467475 // FIXME (#24278): non-hygienic comparison
@@ -566,8 +574,24 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
566574 . cloned ( )
567575 . partition ( |l| self . map . late_bound . contains_key ( & l. lifetime . id ) ) ;
568576
577+ // Find the start of nested early scopes, e.g. in methods.
578+ let mut start = 0 ;
579+ if let EarlyScope ( ..) = * self . scope {
580+ let parent = self . hir_map . expect_item ( self . hir_map . get_parent ( fn_id) ) ;
581+ if let hir:: ItemTrait ( ..) = parent. node {
582+ start += 1 ; // Self comes first.
583+ }
584+ match parent. node {
585+ hir:: ItemTrait ( _, ref generics, _, _) |
586+ hir:: ItemImpl ( _, _, ref generics, _, _, _) => {
587+ start += generics. lifetimes . len ( ) + generics. ty_params . len ( ) ;
588+ }
589+ _ => { }
590+ }
591+ }
592+
569593 let this = self ;
570- this. with ( EarlyScope ( & early, this. scope ) , move |old_scope, this| {
594+ this. with ( EarlyScope ( & early, start as u32 , this. scope ) , move |old_scope, this| {
571595 this. with ( LateScope ( & late, this. scope ) , move |_, this| {
572596 this. check_lifetime_defs ( old_scope, & generics. lifetimes ) ;
573597 walk ( this) ;
@@ -597,19 +621,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
597621 break ;
598622 }
599623
600- EarlyScope ( lifetimes, s) => {
624+ EarlyScope ( lifetimes, start , s) => {
601625 match search_lifetimes ( lifetimes, lifetime_ref) {
602- Some ( ( mut index, lifetime_def) ) => {
603- // Adjust for nested early scopes, e.g. in methods.
604- let mut parent = s;
605- while let EarlyScope ( lifetimes, s) = * parent {
606- index += lifetimes. len ( ) as u32 ;
607- parent = s;
608- }
609- assert_eq ! ( * parent, RootScope ) ;
610-
626+ Some ( ( index, lifetime_def) ) => {
611627 let decl_id = lifetime_def. id ;
612- let def = DefEarlyBoundRegion ( index, decl_id) ;
628+ let def = DefEarlyBoundRegion ( start + index, decl_id) ;
613629 self . insert_lifetime ( lifetime_ref, def) ;
614630 return ;
615631 }
@@ -671,7 +687,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
671687 break ;
672688 }
673689
674- EarlyScope ( lifetimes, s) |
690+ EarlyScope ( lifetimes, _ , s) |
675691 LateScope ( lifetimes, s) => {
676692 search_result = search_lifetimes ( lifetimes, lifetime_ref) ;
677693 if search_result. is_some ( ) {
@@ -767,7 +783,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
767783 return ;
768784 }
769785
770- EarlyScope ( lifetimes, s) |
786+ EarlyScope ( lifetimes, _ , s) |
771787 LateScope ( lifetimes, s) => {
772788 if let Some ( ( _, lifetime_def) ) = search_lifetimes ( lifetimes, lifetime) {
773789 signal_shadowing_problem (
0 commit comments