@@ -388,14 +388,35 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
388
388
let trait_ = lifted. trait_ref ( cx. tcx ) . clean ( cx) ;
389
389
let self_type = self . self_ty ( ) . clean ( cx) ;
390
390
Type :: QPath {
391
- name : cx . tcx . associated_item ( self . item_def_id ) . name ,
391
+ assoc : Box :: new ( projection_to_path_segment ( * self , cx ) ) ,
392
392
self_def_id : self_type. def_id ( & cx. cache ) ,
393
393
self_type : box self_type,
394
394
trait_,
395
395
}
396
396
}
397
397
}
398
398
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
+
399
420
impl Clean < GenericParamDef > for ty:: GenericParamDef {
400
421
fn clean ( & self , cx : & mut DocContext < ' _ > ) -> GenericParamDef {
401
422
let ( name, kind) = match self . kind {
@@ -601,8 +622,8 @@ fn clean_ty_generics(
601
622
} )
602
623
. collect :: < Vec < GenericParamDef > > ( ) ;
603
624
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 ( ) ;
606
627
607
628
let where_predicates = preds
608
629
. predicates
@@ -648,8 +669,9 @@ fn clean_ty_generics(
648
669
649
670
let proj = projection
650
671
. 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) ) )
653
675
{
654
676
// FIXME(...): Remove this unwrap()
655
677
impl_trait_proj. entry ( param_idx) . or_default ( ) . push ( (
@@ -992,9 +1014,10 @@ impl Clean<Item> for hir::TraitItem<'_> {
992
1014
TyMethodItem ( t)
993
1015
}
994
1016
hir:: TraitItemKind :: Type ( bounds, ref default) => {
1017
+ let generics = enter_impl_trait ( cx, |cx| self . generics . clean ( cx) ) ;
995
1018
let bounds = bounds. iter ( ) . filter_map ( |x| x. clean ( cx) ) . collect ( ) ;
996
1019
let default = default. map ( |t| t. clean ( cx) ) ;
997
- AssocTypeItem ( bounds, default)
1020
+ AssocTypeItem ( Box :: new ( generics ) , bounds, default)
998
1021
}
999
1022
} ;
1000
1023
let what_rustc_thinks =
@@ -1026,15 +1049,9 @@ impl Clean<Item> for hir::ImplItem<'_> {
1026
1049
}
1027
1050
hir:: ImplItemKind :: TyAlias ( ref hir_ty) => {
1028
1051
let type_ = hir_ty. clean ( cx) ;
1052
+ let generics = self . generics . clean ( cx) ;
1029
1053
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 )
1038
1055
}
1039
1056
} ;
1040
1057
@@ -1140,35 +1157,79 @@ impl Clean<Item> for ty::AssocItem {
1140
1157
ty:: AssocKind :: Type => {
1141
1158
let my_name = self . name ;
1142
1159
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
+
1143
1181
if let ty:: TraitContainer ( _) = self . container {
1144
1182
let bounds = tcx. explicit_item_bounds ( self . def_id ) ;
1145
1183
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.
1147
1188
let mut bounds = generics
1148
1189
. 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
1164
1223
}
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 ! ( )
1168
1231
}
1169
- Some ( bounds)
1170
1232
} )
1171
- . flat_map ( |i| i. iter ( ) . cloned ( ) )
1172
1233
. collect :: < Vec < _ > > ( ) ;
1173
1234
// Our Sized/?Sized bound didn't get handled when creating the generics
1174
1235
// because we didn't actually get our whole set of bounds until just now
@@ -1188,7 +1249,7 @@ impl Clean<Item> for ty::AssocItem {
1188
1249
None
1189
1250
} ;
1190
1251
1191
- AssocTypeItem ( bounds, ty. map ( |t| t. clean ( cx) ) )
1252
+ AssocTypeItem ( Box :: new ( generics ) , bounds, ty. map ( |t| t. clean ( cx) ) )
1192
1253
} else {
1193
1254
// FIXME: when could this happen? Associated items in inherent impls?
1194
1255
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 {
1259
1320
} ;
1260
1321
register_res ( cx, trait_. res ) ;
1261
1322
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 ) ) ,
1263
1324
self_def_id : Some ( DefId :: local ( qself. hir_id . owner . local_def_index ) ) ,
1264
1325
self_type : box qself. clean ( cx) ,
1265
1326
trait_,
@@ -1276,7 +1337,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
1276
1337
let trait_ = hir:: Path { span, res, segments : & [ ] } . clean ( cx) ;
1277
1338
register_res ( cx, trait_. res ) ;
1278
1339
Type :: QPath {
1279
- name : segment. ident . name ,
1340
+ assoc : Box :: new ( segment. clean ( cx ) ) ,
1280
1341
self_def_id : res. opt_def_id ( ) ,
1281
1342
self_type : box qself. clean ( cx) ,
1282
1343
trait_,
@@ -1548,7 +1609,16 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
1548
1609
let mut bindings = vec ! [ ] ;
1549
1610
for pb in obj. projection_bounds ( ) {
1550
1611
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
+ ) ,
1552
1622
kind : TypeBindingKind :: Equality { term : pb. skip_binder ( ) . term . clean ( cx) } ,
1553
1623
} ) ;
1554
1624
}
@@ -1614,10 +1684,10 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
1614
1684
== trait_ref. skip_binder ( )
1615
1685
{
1616
1686
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
+ ) ,
1621
1691
kind : TypeBindingKind :: Equality {
1622
1692
term : proj. term . clean ( cx) ,
1623
1693
} ,
@@ -2160,7 +2230,10 @@ fn clean_maybe_renamed_foreign_item(
2160
2230
2161
2231
impl Clean < TypeBinding > for hir:: TypeBinding < ' _ > {
2162
2232
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
+ }
2164
2237
}
2165
2238
}
2166
2239
0 commit comments