@@ -388,14 +388,35 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
388388 let trait_ = lifted. trait_ref ( cx. tcx ) . clean ( cx) ;
389389 let self_type = self . self_ty ( ) . clean ( cx) ;
390390 Type :: QPath {
391- name : cx . tcx . associated_item ( self . item_def_id ) . name ,
391+ assoc : Box :: new ( projection_to_path_segment ( * self , cx ) ) ,
392392 self_def_id : self_type. def_id ( & cx. cache ) ,
393393 self_type : box self_type,
394394 trait_,
395395 }
396396 }
397397}
398398
399+ fn projection_to_path_segment ( ty : ty:: ProjectionTy < ' _ > , cx : & mut DocContext < ' _ > ) -> PathSegment {
400+ let item = cx. tcx . associated_item ( ty. item_def_id ) ;
401+ let generics = cx. tcx . generics_of ( ty. item_def_id ) ;
402+ PathSegment {
403+ name : item. name ,
404+ args : GenericArgs :: AngleBracketed {
405+ args : ty. substs [ generics. parent_count ..]
406+ . iter ( )
407+ . map ( |ty| match ty. unpack ( ) {
408+ ty:: subst:: GenericArgKind :: Lifetime ( lt) => {
409+ GenericArg :: Lifetime ( lt. clean ( cx) . unwrap ( ) )
410+ }
411+ ty:: subst:: GenericArgKind :: Type ( ty) => GenericArg :: Type ( ty. clean ( cx) ) ,
412+ ty:: subst:: GenericArgKind :: Const ( c) => GenericArg :: Const ( Box :: new ( c. clean ( cx) ) ) ,
413+ } )
414+ . collect ( ) ,
415+ bindings : Default :: default ( ) ,
416+ } ,
417+ }
418+ }
419+
399420impl Clean < GenericParamDef > for ty:: GenericParamDef {
400421 fn clean ( & self , cx : & mut DocContext < ' _ > ) -> GenericParamDef {
401422 let ( name, kind) = match self . kind {
@@ -601,8 +622,8 @@ fn clean_ty_generics(
601622 } )
602623 . collect :: < Vec < GenericParamDef > > ( ) ;
603624
604- // param index -> [(DefId of trait, associated type name, type)]
605- let mut impl_trait_proj = FxHashMap :: < u32 , Vec < ( DefId , Symbol , Ty < ' _ > ) > > :: default ( ) ;
625+ // param index -> [(DefId of trait, associated type name and generics , type)]
626+ let mut impl_trait_proj = FxHashMap :: < u32 , Vec < ( DefId , PathSegment , Ty < ' _ > ) > > :: default ( ) ;
606627
607628 let where_predicates = preds
608629 . predicates
@@ -648,8 +669,9 @@ fn clean_ty_generics(
648669
649670 let proj = projection
650671 . map ( |p| ( p. skip_binder ( ) . projection_ty . clean ( cx) , p. skip_binder ( ) . term ) ) ;
651- if let Some ( ( ( _, trait_did, name) , rhs) ) =
652- proj. as_ref ( ) . and_then ( |( lhs, rhs) | Some ( ( lhs. projection ( ) ?, rhs) ) )
672+ if let Some ( ( ( _, trait_did, name) , rhs) ) = proj
673+ . as_ref ( )
674+ . and_then ( |( lhs, rhs) : & ( Type , _ ) | Some ( ( lhs. projection ( ) ?, rhs) ) )
653675 {
654676 // FIXME(...): Remove this unwrap()
655677 impl_trait_proj. entry ( param_idx) . or_default ( ) . push ( (
@@ -992,9 +1014,10 @@ impl Clean<Item> for hir::TraitItem<'_> {
9921014 TyMethodItem ( t)
9931015 }
9941016 hir:: TraitItemKind :: Type ( bounds, ref default) => {
1017+ let generics = enter_impl_trait ( cx, |cx| self . generics . clean ( cx) ) ;
9951018 let bounds = bounds. iter ( ) . filter_map ( |x| x. clean ( cx) ) . collect ( ) ;
9961019 let default = default. map ( |t| t. clean ( cx) ) ;
997- AssocTypeItem ( bounds, default)
1020+ AssocTypeItem ( Box :: new ( generics ) , bounds, default)
9981021 }
9991022 } ;
10001023 let what_rustc_thinks =
@@ -1026,15 +1049,9 @@ impl Clean<Item> for hir::ImplItem<'_> {
10261049 }
10271050 hir:: ImplItemKind :: TyAlias ( ref hir_ty) => {
10281051 let type_ = hir_ty. clean ( cx) ;
1052+ let generics = self . generics . clean ( cx) ;
10291053 let item_type = hir_ty_to_ty ( cx. tcx , hir_ty) . clean ( cx) ;
1030- TypedefItem (
1031- Typedef {
1032- type_,
1033- generics : Generics :: default ( ) ,
1034- item_type : Some ( item_type) ,
1035- } ,
1036- true ,
1037- )
1054+ TypedefItem ( Typedef { type_, generics, item_type : Some ( item_type) } , true )
10381055 }
10391056 } ;
10401057
@@ -1140,35 +1157,79 @@ impl Clean<Item> for ty::AssocItem {
11401157 ty:: AssocKind :: Type => {
11411158 let my_name = self . name ;
11421159
1160+ fn param_eq_arg ( param : & GenericParamDef , arg : & GenericArg ) -> bool {
1161+ match ( & param. kind , arg) {
1162+ ( GenericParamDefKind :: Type { .. } , GenericArg :: Type ( Type :: Generic ( ty) ) )
1163+ if * ty == param. name =>
1164+ {
1165+ true
1166+ }
1167+ (
1168+ GenericParamDefKind :: Lifetime { .. } ,
1169+ GenericArg :: Lifetime ( Lifetime ( lt) ) ,
1170+ ) if * lt == param. name => true ,
1171+ ( GenericParamDefKind :: Const { .. } , GenericArg :: Const ( c) ) => {
1172+ match & c. kind {
1173+ ConstantKind :: TyConst { expr } => expr == param. name . as_str ( ) ,
1174+ _ => false ,
1175+ }
1176+ }
1177+ _ => false ,
1178+ }
1179+ }
1180+
11431181 if let ty:: TraitContainer ( _) = self . container {
11441182 let bounds = tcx. explicit_item_bounds ( self . def_id ) ;
11451183 let predicates = ty:: GenericPredicates { parent : None , predicates : bounds } ;
1146- let generics = clean_ty_generics ( cx, tcx. generics_of ( self . def_id ) , predicates) ;
1184+ let mut generics =
1185+ clean_ty_generics ( cx, tcx. generics_of ( self . def_id ) , predicates) ;
1186+ // Filter out the bounds that are (likely?) directly attached to the associated type,
1187+ // as opposed to being located in the where clause.
11471188 let mut bounds = generics
11481189 . where_predicates
1149- . iter ( )
1150- . filter_map ( |pred| {
1151- let ( name, self_type, trait_, bounds) = match * pred {
1152- WherePredicate :: BoundPredicate {
1153- ty : QPath { ref name, ref self_type, ref trait_, .. } ,
1154- ref bounds,
1155- ..
1156- } => ( name, self_type, trait_, bounds) ,
1157- _ => return None ,
1158- } ;
1159- if * name != my_name {
1160- return None ;
1161- }
1162- if trait_. def_id ( ) != self . container . id ( ) {
1163- return None ;
1190+ . drain_filter ( |pred| match * pred {
1191+ WherePredicate :: BoundPredicate {
1192+ ty : QPath { ref assoc, ref self_type, ref trait_, .. } ,
1193+ ..
1194+ } => {
1195+ if assoc. name != my_name {
1196+ return false ;
1197+ }
1198+ if trait_. def_id ( ) != self . container . id ( ) {
1199+ return false ;
1200+ }
1201+ match * * self_type {
1202+ Generic ( ref s) if * s == kw:: SelfUpper => { }
1203+ _ => return false ,
1204+ }
1205+ match & assoc. args {
1206+ GenericArgs :: AngleBracketed { args, bindings } => {
1207+ if !bindings. is_empty ( )
1208+ || generics
1209+ . params
1210+ . iter ( )
1211+ . zip ( args)
1212+ . any ( |( param, arg) | !param_eq_arg ( param, arg) )
1213+ {
1214+ return false ;
1215+ }
1216+ }
1217+ GenericArgs :: Parenthesized { .. } => {
1218+ // The only time this happens is if we're inside the rustdoc for Fn(),
1219+ // which only has one associated type, which is not a GAT, so whatever.
1220+ }
1221+ }
1222+ true
11641223 }
1165- match * * self_type {
1166- Generic ( ref s) if * s == kw:: SelfUpper => { }
1167- _ => return None ,
1224+ _ => false ,
1225+ } )
1226+ . flat_map ( |pred| {
1227+ if let WherePredicate :: BoundPredicate { bounds, .. } = pred {
1228+ bounds
1229+ } else {
1230+ unreachable ! ( )
11681231 }
1169- Some ( bounds)
11701232 } )
1171- . flat_map ( |i| i. iter ( ) . cloned ( ) )
11721233 . collect :: < Vec < _ > > ( ) ;
11731234 // Our Sized/?Sized bound didn't get handled when creating the generics
11741235 // because we didn't actually get our whole set of bounds until just now
@@ -1188,7 +1249,7 @@ impl Clean<Item> for ty::AssocItem {
11881249 None
11891250 } ;
11901251
1191- AssocTypeItem ( bounds, ty. map ( |t| t. clean ( cx) ) )
1252+ AssocTypeItem ( Box :: new ( generics ) , bounds, ty. map ( |t| t. clean ( cx) ) )
11921253 } else {
11931254 // FIXME: when could this happen? Associated items in inherent impls?
11941255 let type_ = tcx. type_of ( self . def_id ) . clean ( cx) ;
@@ -1259,7 +1320,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
12591320 } ;
12601321 register_res ( cx, trait_. res ) ;
12611322 Type :: QPath {
1262- name : p. segments . last ( ) . expect ( "segments were empty" ) . ident . name ,
1323+ assoc : Box :: new ( p. segments . last ( ) . expect ( "segments were empty" ) . clean ( cx ) ) ,
12631324 self_def_id : Some ( DefId :: local ( qself. hir_id . owner . local_def_index ) ) ,
12641325 self_type : box qself. clean ( cx) ,
12651326 trait_,
@@ -1276,7 +1337,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
12761337 let trait_ = hir:: Path { span, res, segments : & [ ] } . clean ( cx) ;
12771338 register_res ( cx, trait_. res ) ;
12781339 Type :: QPath {
1279- name : segment. ident . name ,
1340+ assoc : Box :: new ( segment. clean ( cx ) ) ,
12801341 self_def_id : res. opt_def_id ( ) ,
12811342 self_type : box qself. clean ( cx) ,
12821343 trait_,
@@ -1548,7 +1609,16 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
15481609 let mut bindings = vec ! [ ] ;
15491610 for pb in obj. projection_bounds ( ) {
15501611 bindings. push ( TypeBinding {
1551- name : cx. tcx . associated_item ( pb. item_def_id ( ) ) . name ,
1612+ assoc : projection_to_path_segment (
1613+ pb. skip_binder ( )
1614+ . lift_to_tcx ( cx. tcx )
1615+ . unwrap ( )
1616+ // HACK(compiler-errors): Doesn't actually matter what self
1617+ // type we put here, because we're only using the GAT's substs.
1618+ . with_self_ty ( cx. tcx , cx. tcx . types . self_param )
1619+ . projection_ty ,
1620+ cx,
1621+ ) ,
15521622 kind : TypeBindingKind :: Equality { term : pb. skip_binder ( ) . term . clean ( cx) } ,
15531623 } ) ;
15541624 }
@@ -1614,10 +1684,10 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
16141684 == trait_ref. skip_binder ( )
16151685 {
16161686 Some ( TypeBinding {
1617- name : cx
1618- . tcx
1619- . associated_item ( proj . projection_ty . item_def_id )
1620- . name ,
1687+ assoc : projection_to_path_segment (
1688+ proj . projection_ty ,
1689+ cx ,
1690+ ) ,
16211691 kind : TypeBindingKind :: Equality {
16221692 term : proj. term . clean ( cx) ,
16231693 } ,
@@ -2160,7 +2230,10 @@ fn clean_maybe_renamed_foreign_item(
21602230
21612231impl Clean < TypeBinding > for hir:: TypeBinding < ' _ > {
21622232 fn clean ( & self , cx : & mut DocContext < ' _ > ) -> TypeBinding {
2163- TypeBinding { name : self . ident . name , kind : self . kind . clean ( cx) }
2233+ TypeBinding {
2234+ assoc : PathSegment { name : self . ident . name , args : self . gen_args . clean ( cx) } ,
2235+ kind : self . kind . clean ( cx) ,
2236+ }
21642237 }
21652238}
21662239
0 commit comments