@@ -65,7 +65,7 @@ use rustc::ty::{ToPredicate, ReprOptions};
65
65
use rustc:: ty:: { self , AdtKind , ToPolyTraitRef , Ty , TyCtxt } ;
66
66
use rustc:: ty:: maps:: Providers ;
67
67
use rustc:: ty:: util:: IntTypeExt ;
68
- use util:: nodemap:: FxHashMap ;
68
+ use util:: nodemap:: { DefIdSet , FxHashMap } ;
69
69
70
70
use rustc_const_math:: ConstInt ;
71
71
@@ -76,7 +76,7 @@ use syntax::codemap::Spanned;
76
76
use syntax:: symbol:: { Symbol , keywords} ;
77
77
use syntax_pos:: { Span , DUMMY_SP } ;
78
78
79
- use rustc:: hir:: { self , map as hir_map} ;
79
+ use rustc:: hir:: { self , map as hir_map, Lifetime } ;
80
80
use rustc:: hir:: intravisit:: { self , Visitor , NestedVisitorMap } ;
81
81
use rustc:: hir:: def:: { Def , CtorKind } ;
82
82
use rustc:: hir:: def_id:: DefId ;
@@ -863,6 +863,35 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
863
863
}
864
864
}
865
865
866
+ struct ImplTraitRegionBoundsCollector < ' a , ' tcx : ' a , ' b > {
867
+ tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
868
+ region_bounds : & ' b mut DefIdSet ,
869
+ }
870
+
871
+ impl < ' a , ' tcx : ' a , ' b > Visitor < ' tcx > for ImplTraitRegionBoundsCollector < ' a , ' tcx , ' b > {
872
+ fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
873
+ NestedVisitorMap :: None
874
+ }
875
+
876
+ fn visit_lifetime ( & mut self , lifetime : & ' tcx Lifetime ) {
877
+ if !lifetime. is_static ( ) { // no need to look up the lifetime if we already know it's static
878
+ match self . tcx . named_region_map . defs . get ( & lifetime. id ) {
879
+ Some ( & rl:: Region :: EarlyBound ( _, id) ) => {
880
+ self . region_bounds . insert ( self . tcx . hir . local_def_id ( id) ) ;
881
+ }
882
+ Some ( & rl:: Region :: LateBound ( _, _) ) |
883
+ Some ( & rl:: Region :: LateBoundAnon ( _, _) ) => {
884
+ span_bug ! ( lifetime. span,
885
+ "Late-bound lifetimes not yet handed properly in `impl Trait`" ) ;
886
+ }
887
+ Some ( & rl:: Region :: Static ) |
888
+ Some ( & rl:: Region :: Free ( _, _) ) |
889
+ None => { }
890
+ }
891
+ }
892
+ }
893
+ }
894
+
866
895
fn generics_of < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
867
896
def_id : DefId )
868
897
-> & ' tcx ty:: Generics {
@@ -884,18 +913,6 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
884
913
NodeExpr ( & hir:: Expr { node : hir:: ExprClosure ( ..) , .. } ) => {
885
914
Some ( tcx. closure_base_def_id ( def_id) )
886
915
}
887
- NodeTy ( & hir:: Ty { node : hir:: TyImplTrait ( ..) , .. } ) => {
888
- let mut parent_id = node_id;
889
- loop {
890
- match tcx. hir . get ( parent_id) {
891
- NodeItem ( _) | NodeImplItem ( _) | NodeTraitItem ( _) => break ,
892
- _ => {
893
- parent_id = tcx. hir . get_parent_node ( parent_id) ;
894
- }
895
- }
896
- }
897
- Some ( tcx. hir . local_def_id ( parent_id) )
898
- }
899
916
_ => None
900
917
} ;
901
918
@@ -962,6 +979,67 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
962
979
}
963
980
}
964
981
982
+ NodeTy ( & hir:: Ty { node : hir:: TyImplTrait ( ref impl_trait_bounds) , .. } ) => {
983
+ // Traverse impl_trait_bounds to identify all of the region bounds that appear
984
+ // so that we can copy them from the environment
985
+ let mut region_bounds = DefIdSet ( ) ;
986
+ {
987
+ let mut bounds_collector = ImplTraitRegionBoundsCollector {
988
+ tcx : tcx,
989
+ region_bounds : & mut region_bounds,
990
+ } ;
991
+ for bound in impl_trait_bounds {
992
+ bounds_collector. visit_ty_param_bound ( bound) ;
993
+ }
994
+ }
995
+
996
+ let mut regions = vec ! [ ] ;
997
+ let mut types = vec ! [ ] ;
998
+ let mut region_param_to_index = BTreeMap :: new ( ) ;
999
+ let mut type_param_to_index = BTreeMap :: new ( ) ;
1000
+ let mut has_self = false ;
1001
+
1002
+ // Copy generics from parents, filtering out unused region parameters
1003
+ let mut parent_id = Some ( tcx. hir . local_def_id ( tcx. hir . get_parent ( node_id) ) ) ;
1004
+ while let Some ( cur_gen_id) = parent_id {
1005
+ let cur_generics = tcx. generics_of ( cur_gen_id) ;
1006
+
1007
+ has_self |= cur_generics. has_self ;
1008
+
1009
+ for region in & cur_generics. regions {
1010
+ if region_bounds. contains ( & region. def_id ) {
1011
+ regions. push ( * region) ;
1012
+ }
1013
+ }
1014
+
1015
+ types. extend_from_slice ( & cur_generics. types ) ;
1016
+
1017
+ parent_id = cur_generics. parent ;
1018
+ }
1019
+
1020
+ // Fixup indices
1021
+ for ( i, ref mut region) in regions. iter_mut ( ) . enumerate ( ) {
1022
+ region. index = i as u32 ;
1023
+ region_param_to_index. insert ( region. def_id . index , region. index ) ;
1024
+ }
1025
+ for ( i, ref mut type_) in types. iter_mut ( ) . enumerate ( ) {
1026
+ type_. index = ( regions. len ( ) + i) as u32 ;
1027
+ type_param_to_index. insert ( type_. def_id . index , type_. index ) ;
1028
+ }
1029
+
1030
+ return tcx. alloc_generics ( ty:: Generics {
1031
+ parent : None ,
1032
+ parent_regions : 0 ,
1033
+ parent_types : 0 ,
1034
+ regions : regions,
1035
+ types : types,
1036
+ region_param_to_index : Some ( region_param_to_index) ,
1037
+ type_param_to_index : type_param_to_index,
1038
+ has_self : has_self,
1039
+ has_late_bound_regions : None ,
1040
+ } ) ;
1041
+ }
1042
+
965
1043
_ => & no_generics
966
1044
} ;
967
1045
@@ -1048,6 +1126,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1048
1126
regions : regions,
1049
1127
types : types,
1050
1128
type_param_to_index : type_param_to_index,
1129
+ region_param_to_index : None ,
1051
1130
has_self : has_self || parent_has_self,
1052
1131
has_late_bound_regions : has_late_bound_regions ( tcx, node) ,
1053
1132
} )
0 commit comments