@@ -713,6 +713,13 @@ impl ty::EarlyBoundRegion {
713
713
714
714
/// Information about the formal type/lifetime parameters associated
715
715
/// with an item or method. Analogous to hir::Generics.
716
+ ///
717
+ /// Note that in the presence of a `Self` parameter, the ordering here
718
+ /// is different from the ordering in a Substs. Substs are ordered as
719
+ /// Self, *Regions, *Other Type Params, (...child generics)
720
+ /// while this struct is ordered as
721
+ /// regions = Regions
722
+ /// types = [Self, *Other Type Params]
716
723
#[ derive( Clone , Debug , RustcEncodable , RustcDecodable ) ]
717
724
pub struct Generics {
718
725
pub parent : Option < DefId > ,
@@ -729,7 +736,7 @@ pub struct Generics {
729
736
pub has_late_bound_regions : Option < Span > ,
730
737
}
731
738
732
- impl Generics {
739
+ impl < ' a , ' gcx , ' tcx > Generics {
733
740
pub fn parent_count ( & self ) -> usize {
734
741
self . parent_regions as usize + self . parent_types as usize
735
742
}
@@ -742,14 +749,52 @@ impl Generics {
742
749
self . parent_count ( ) + self . own_count ( )
743
750
}
744
751
745
- pub fn region_param ( & self , param : & EarlyBoundRegion ) -> & RegionParameterDef {
746
- assert_eq ! ( self . parent_count( ) , 0 ) ;
747
- & self . regions [ param. index as usize - self . has_self as usize ]
748
- }
749
-
750
- pub fn type_param ( & self , param : & ParamTy ) -> & TypeParameterDef {
751
- assert_eq ! ( self . parent_count( ) , 0 ) ;
752
- & self . types [ param. idx as usize - self . has_self as usize - self . regions . len ( ) ]
752
+ pub fn region_param ( & ' tcx self ,
753
+ param : & EarlyBoundRegion ,
754
+ tcx : TyCtxt < ' a , ' gcx , ' tcx > )
755
+ -> & ' tcx RegionParameterDef
756
+ {
757
+ if let Some ( index) = param. index . checked_sub ( self . parent_count ( ) as u32 ) {
758
+ & self . regions [ index as usize - self . has_self as usize ]
759
+ } else {
760
+ tcx. generics_of ( self . parent . expect ( "parent_count>0 but no parent?" ) )
761
+ . region_param ( param, tcx)
762
+ }
763
+ }
764
+
765
+ /// Returns the `TypeParameterDef` associated with this `ParamTy`.
766
+ pub fn type_param ( & ' tcx self ,
767
+ param : & ParamTy ,
768
+ tcx : TyCtxt < ' a , ' gcx , ' tcx > )
769
+ -> & TypeParameterDef {
770
+ if let Some ( idx) = param. idx . checked_sub ( self . parent_count ( ) as u32 ) {
771
+ // non-Self type parameters are always offset by exactly
772
+ // `self.regions.len()`. In the absence of a Self, this is obvious,
773
+ // but even in the absence of a `Self` we just have to "compensate"
774
+ // for the regions:
775
+ //
776
+ // For example, for `trait Foo<'a, 'b, T1, T2>`, the
777
+ // situation is:
778
+ // Substs:
779
+ // 0 1 2 3 4
780
+ // Self 'a 'b T1 T2
781
+ // generics.types:
782
+ // 0 1 2
783
+ // Self T1 T2
784
+ // And it can be seen that to move from a substs offset to a
785
+ // generics offset you just have to offset by the number of regions.
786
+ let type_param_offset = self . regions . len ( ) ;
787
+ if let Some ( idx) = ( idx as usize ) . checked_sub ( type_param_offset) {
788
+ assert ! ( !( self . has_self && idx == 0 ) ) ;
789
+ & self . types [ idx]
790
+ } else {
791
+ assert ! ( self . has_self && idx == 0 ) ;
792
+ & self . types [ 0 ]
793
+ }
794
+ } else {
795
+ tcx. generics_of ( self . parent . expect ( "parent_count>0 but no parent?" ) )
796
+ . type_param ( param, tcx)
797
+ }
753
798
}
754
799
}
755
800
0 commit comments