@@ -17,7 +17,7 @@ use rustc_hir as hir;
1717use rustc_hir:: def_id:: DefId ;
1818use rustc_index:: vec:: Idx ;
1919use rustc_macros:: HashStable ;
20- use rustc_span:: symbol:: { kw, Ident , Symbol } ;
20+ use rustc_span:: symbol:: { kw, Symbol } ;
2121use rustc_target:: abi:: VariantIdx ;
2222use rustc_target:: spec:: abi;
2323use std:: borrow:: Cow ;
@@ -1112,36 +1112,35 @@ pub struct ProjectionTy<'tcx> {
11121112}
11131113
11141114impl < ' tcx > ProjectionTy < ' tcx > {
1115- /// Construct a `ProjectionTy` by searching the trait from `trait_ref` for the
1116- /// associated item named `item_name`.
1117- pub fn from_ref_and_name (
1118- tcx : TyCtxt < ' _ > ,
1119- trait_ref : ty:: TraitRef < ' tcx > ,
1120- item_name : Ident ,
1121- ) -> ProjectionTy < ' tcx > {
1122- let item_def_id = tcx
1123- . associated_items ( trait_ref. def_id )
1124- . find_by_name_and_kind ( tcx, item_name, ty:: AssocKind :: Type , trait_ref. def_id )
1125- . unwrap ( )
1126- . def_id ;
1115+ pub fn trait_def_id ( & self , tcx : TyCtxt < ' tcx > ) -> DefId {
1116+ tcx. associated_item ( self . item_def_id ) . container . id ( )
1117+ }
11271118
1128- ProjectionTy { substs : trait_ref. substs , item_def_id }
1119+ /// Extracts the underlying trait reference and own substs from this projection.
1120+ /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
1121+ /// then this function would return a `T: Iterator` trait reference and `['a]` as the own substs
1122+ pub fn trait_ref_and_own_substs (
1123+ & self ,
1124+ tcx : TyCtxt < ' tcx > ,
1125+ ) -> ( ty:: TraitRef < ' tcx > , & ' tcx [ ty:: GenericArg < ' tcx > ] ) {
1126+ let def_id = tcx. associated_item ( self . item_def_id ) . container . id ( ) ;
1127+ let trait_generics = tcx. generics_of ( def_id) ;
1128+ (
1129+ ty:: TraitRef { def_id, substs : self . substs . truncate_to ( tcx, trait_generics) } ,
1130+ & self . substs [ trait_generics. count ( ) ..] ,
1131+ )
11291132 }
11301133
11311134 /// Extracts the underlying trait reference from this projection.
11321135 /// For example, if this is a projection of `<T as Iterator>::Item`,
11331136 /// then this function would return a `T: Iterator` trait reference.
1137+ ///
1138+ /// WARNING: This will drop the substs for generic associated types
1139+ /// consider calling [Self::trait_ref_and_own_substs] to get those
1140+ /// as well.
11341141 pub fn trait_ref ( & self , tcx : TyCtxt < ' tcx > ) -> ty:: TraitRef < ' tcx > {
1135- // FIXME: This method probably shouldn't exist at all, since it's not
1136- // clear what this method really intends to do. Be careful when
1137- // using this method since the resulting TraitRef additionally
1138- // contains the substs for the assoc_item, which strictly speaking
1139- // is not correct
1140- let def_id = tcx. associated_item ( self . item_def_id ) . container . id ( ) ;
1141- // Include substitutions for generic arguments of associated types
1142- let assoc_item = tcx. associated_item ( self . item_def_id ) ;
1143- let substs_assoc_item = self . substs . truncate_to ( tcx, tcx. generics_of ( assoc_item. def_id ) ) ;
1144- ty:: TraitRef { def_id, substs : substs_assoc_item }
1142+ let def_id = self . trait_def_id ( tcx) ;
1143+ ty:: TraitRef { def_id, substs : self . substs . truncate_to ( tcx, tcx. generics_of ( def_id) ) }
11451144 }
11461145
11471146 pub fn self_ty ( & self ) -> Ty < ' tcx > {
@@ -1493,12 +1492,11 @@ impl<'tcx> ExistentialProjection<'tcx> {
14931492 /// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`,
14941493 /// then this function would return a `exists T. T: Iterator` existential trait
14951494 /// reference.
1496- pub fn trait_ref ( & self , tcx : TyCtxt < ' _ > ) -> ty:: ExistentialTraitRef < ' tcx > {
1497- // FIXME(generic_associated_types): substs is the substs of the
1498- // associated type, which should be truncated to get the correct substs
1499- // for the trait.
1495+ pub fn trait_ref ( & self , tcx : TyCtxt < ' tcx > ) -> ty:: ExistentialTraitRef < ' tcx > {
15001496 let def_id = tcx. associated_item ( self . item_def_id ) . container . id ( ) ;
1501- ty:: ExistentialTraitRef { def_id, substs : self . substs }
1497+ let subst_count = tcx. generics_of ( def_id) . count ( ) - 1 ;
1498+ let substs = tcx. intern_substs ( & self . substs [ ..subst_count] ) ;
1499+ ty:: ExistentialTraitRef { def_id, substs }
15021500 }
15031501
15041502 pub fn with_self_ty (
@@ -1517,6 +1515,20 @@ impl<'tcx> ExistentialProjection<'tcx> {
15171515 ty : self . ty ,
15181516 }
15191517 }
1518+
1519+ pub fn erase_self_ty (
1520+ tcx : TyCtxt < ' tcx > ,
1521+ projection_predicate : ty:: ProjectionPredicate < ' tcx > ,
1522+ ) -> Self {
1523+ // Assert there is a Self.
1524+ projection_predicate. projection_ty . substs . type_at ( 0 ) ;
1525+
1526+ Self {
1527+ item_def_id : projection_predicate. projection_ty . item_def_id ,
1528+ substs : tcx. intern_substs ( & projection_predicate. projection_ty . substs [ 1 ..] ) ,
1529+ ty : projection_predicate. ty ,
1530+ }
1531+ }
15201532}
15211533
15221534impl < ' tcx > PolyExistentialProjection < ' tcx > {
0 commit comments