@@ -625,122 +625,131 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
625625 } ;
626626 self . with ( scope, |_, this| this. visit_ty ( & mt. ty ) ) ;
627627 }
628- hir:: TyImplTraitExistential ( item_id, _, ref lifetimes) => {
629- // Resolve the lifetimes that are applied to the existential type.
630- // These are resolved in the current scope.
631- // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
632- // `fn foo<'a>() -> MyAnonTy<'a> { ... }`
633- // ^ ^this gets resolved in the current scope
634- for lifetime in lifetimes {
635- self . visit_lifetime ( lifetime) ;
636-
637- // Check for predicates like `impl for<'a> SomeTrait<impl OtherTrait<'a>>`
638- // and ban them. Type variables instantiated inside binders aren't
639- // well-supported at the moment, so this doesn't work.
640- // In the future, this should be fixed and this error should be removed.
641- let def = self . map . defs . get ( & lifetime. id ) . cloned ( ) ;
642- if let Some ( Region :: LateBound ( _, def_id, _) ) = def {
643- if let Some ( node_id) = self . tcx . hir . as_local_node_id ( def_id) {
644- // Ensure that the parent of the def is an item, not HRTB
645- let parent_id = self . tcx . hir . get_parent_node ( node_id) ;
646- let parent_impl_id = hir:: ImplItemId { node_id : parent_id } ;
647- let parent_trait_id = hir:: TraitItemId { node_id : parent_id } ;
648- let krate = self . tcx . hir . forest . krate ( ) ;
649- if !( krate. items . contains_key ( & parent_id)
650- || krate. impl_items . contains_key ( & parent_impl_id)
651- || krate. trait_items . contains_key ( & parent_trait_id) )
652- {
653- span_err ! (
654- self . tcx. sess,
655- lifetime. span,
656- E0657 ,
657- "`impl Trait` can only capture lifetimes \
658- bound at the fn or impl level"
659- ) ;
660- self . uninsert_lifetime_on_error ( lifetime, def. unwrap ( ) ) ;
628+ hir:: TyPath ( hir:: QPath :: Resolved ( None , ref path) ) => {
629+ if let Def :: Existential ( exist_ty_did) = path. def {
630+ assert ! ( exist_ty_did. is_local( ) ) ;
631+ // Resolve the lifetimes that are applied to the existential type.
632+ // These are resolved in the current scope.
633+ // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
634+ // `fn foo<'a>() -> MyAnonTy<'a> { ... }`
635+ // ^ ^this gets resolved in the current scope
636+ for lifetime in & path. segments [ 0 ] . args . as_ref ( ) . unwrap ( ) . args {
637+ if let hir:: GenericArg :: Lifetime ( lifetime) = lifetime {
638+ self . visit_lifetime ( lifetime) ;
639+
640+ // Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
641+ // and ban them. Type variables instantiated inside binders aren't
642+ // well-supported at the moment, so this doesn't work.
643+ // In the future, this should be fixed and this error should be removed.
644+ let def = self . map . defs . get ( & lifetime. id ) . cloned ( ) ;
645+ if let Some ( Region :: LateBound ( _, def_id, _) ) = def {
646+ if let Some ( node_id) = self . tcx . hir . as_local_node_id ( def_id) {
647+ // Ensure that the parent of the def is an item, not HRTB
648+ let parent_id = self . tcx . hir . get_parent_node ( node_id) ;
649+ let parent_impl_id = hir:: ImplItemId { node_id : parent_id } ;
650+ let parent_trait_id = hir:: TraitItemId { node_id : parent_id } ;
651+ let krate = self . tcx . hir . forest . krate ( ) ;
652+ if !( krate. items . contains_key ( & parent_id)
653+ || krate. impl_items . contains_key ( & parent_impl_id)
654+ || krate. trait_items . contains_key ( & parent_trait_id) )
655+ {
656+ span_err ! (
657+ self . tcx. sess,
658+ lifetime. span,
659+ E0657 ,
660+ "`impl Trait` can only capture lifetimes \
661+ bound at the fn or impl level"
662+ ) ;
663+ self . uninsert_lifetime_on_error ( lifetime, def. unwrap ( ) ) ;
664+ }
665+ }
661666 }
662667 }
663668 }
664- }
665669
666- // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
667- // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
668- // `abstract type MyAnonTy<'b>: MyTrait<'b>;`
669- // ^ ^ this gets resolved in the scope of
670- // the exist_ty generics
671- let ( generics, bounds) = match self . tcx . hir . expect_item ( item_id. id ) . node {
672- hir:: ItemExistential ( hir:: ExistTy { ref generics, ref bounds, .. } ) => (
673- generics,
674- bounds,
675- ) ,
676- ref i => bug ! ( "impl Trait pointed to non-existential type?? {:#?}" , i) ,
677- } ;
670+ let id = self . tcx . hir . as_local_node_id ( exist_ty_did) . unwrap ( ) ;
671+
672+ // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
673+ // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
674+ // `abstract type MyAnonTy<'b>: MyTrait<'b>;`
675+ // ^ ^ this gets resolved in the scope of
676+ // the exist_ty generics
677+ let ( generics, bounds) = match self . tcx . hir . expect_item ( id) . node {
678+ hir:: ItemExistential ( hir:: ExistTy { ref generics, ref bounds, .. } ) => (
679+ generics,
680+ bounds,
681+ ) ,
682+ ref i => bug ! ( "impl Trait pointed to non-existential type?? {:#?}" , i) ,
683+ } ;
678684
679- // We want to start our early-bound indices at the end of the parent scope,
680- // not including any parent `impl Trait`s.
681- let mut index = self . next_early_index_for_abstract_type ( ) ;
682- debug ! ( "visit_ty: index = {}" , index) ;
685+ // We want to start our early-bound indices at the end of the parent scope,
686+ // not including any parent `impl Trait`s.
687+ let mut index = self . next_early_index_for_abstract_type ( ) ;
688+ debug ! ( "visit_ty: index = {}" , index) ;
683689
684- let mut elision = None ;
685- let mut lifetimes = FxHashMap ( ) ;
686- let mut type_count = 0 ;
687- for param in & generics. params {
688- match param. kind {
689- GenericParamKind :: Lifetime { .. } => {
690- let ( name, reg) = Region :: early ( & self . tcx . hir , & mut index, & param) ;
691- if let hir:: ParamName :: Plain ( param_name) = name {
692- if param_name. name == keywords:: UnderscoreLifetime . name ( ) {
693- // Pick the elided lifetime "definition" if one exists
694- // and use it to make an elision scope.
695- elision = Some ( reg) ;
690+ let mut elision = None ;
691+ let mut lifetimes = FxHashMap ( ) ;
692+ let mut type_count = 0 ;
693+ for param in & generics. params {
694+ match param. kind {
695+ GenericParamKind :: Lifetime { .. } => {
696+ let ( name, reg) = Region :: early ( & self . tcx . hir , & mut index, & param) ;
697+ if let hir:: ParamName :: Plain ( param_name) = name {
698+ if param_name. name == keywords:: UnderscoreLifetime . name ( ) {
699+ // Pick the elided lifetime "definition" if one exists
700+ // and use it to make an elision scope.
701+ elision = Some ( reg) ;
702+ } else {
703+ lifetimes. insert ( name, reg) ;
704+ }
696705 } else {
697706 lifetimes. insert ( name, reg) ;
698707 }
699- } else {
700- lifetimes. insert ( name, reg) ;
701708 }
702- }
703- GenericParamKind :: Type { .. } => {
704- type_count += 1 ;
709+ GenericParamKind :: Type { .. } => {
710+ type_count += 1 ;
711+ }
705712 }
706713 }
707- }
708- let next_early_index = index + type_count;
714+ let next_early_index = index + type_count;
709715
710- if let Some ( elision_region) = elision {
711- let scope = Scope :: Elision {
712- elide : Elide :: Exact ( elision_region) ,
713- s : self . scope ,
714- } ;
715- self . with ( scope, |_old_scope, this| {
716+ if let Some ( elision_region) = elision {
717+ let scope = Scope :: Elision {
718+ elide : Elide :: Exact ( elision_region) ,
719+ s : self . scope ,
720+ } ;
721+ self . with ( scope, |_old_scope, this| {
722+ let scope = Scope :: Binder {
723+ lifetimes,
724+ next_early_index,
725+ s : this. scope ,
726+ track_lifetime_uses : true ,
727+ abstract_type_parent : false ,
728+ } ;
729+ this. with ( scope, |_old_scope, this| {
730+ this. visit_generics ( generics) ;
731+ for bound in bounds {
732+ this. visit_param_bound ( bound) ;
733+ }
734+ } ) ;
735+ } ) ;
736+ } else {
716737 let scope = Scope :: Binder {
717738 lifetimes,
718739 next_early_index,
719- s : this . scope ,
740+ s : self . scope ,
720741 track_lifetime_uses : true ,
721742 abstract_type_parent : false ,
722743 } ;
723- this . with ( scope, |_old_scope, this| {
744+ self . with ( scope, |_old_scope, this| {
724745 this. visit_generics ( generics) ;
725746 for bound in bounds {
726747 this. visit_param_bound ( bound) ;
727748 }
728749 } ) ;
729- } ) ;
750+ }
730751 } else {
731- let scope = Scope :: Binder {
732- lifetimes,
733- next_early_index,
734- s : self . scope ,
735- track_lifetime_uses : true ,
736- abstract_type_parent : false ,
737- } ;
738- self . with ( scope, |_old_scope, this| {
739- this. visit_generics ( generics) ;
740- for bound in bounds {
741- this. visit_param_bound ( bound) ;
742- }
743- } ) ;
752+ intravisit:: walk_ty ( self , ty)
744753 }
745754 }
746755 _ => intravisit:: walk_ty ( self , ty) ,
0 commit comments