@@ -498,6 +498,35 @@ pub enum TyParamBound {
498
498
TraitBound ( PolyTrait , ast:: TraitBoundModifier )
499
499
}
500
500
501
+ impl TyParamBound {
502
+ fn maybe_sized ( cx : & DocContext ) -> TyParamBound {
503
+ use syntax:: ast:: TraitBoundModifier as TBM ;
504
+ let mut sized_bound = ty:: BuiltinBound :: BoundSized . clean ( cx) ;
505
+ if let TyParamBound :: TraitBound ( _, ref mut tbm) = sized_bound {
506
+ * tbm = TBM :: Maybe
507
+ } ;
508
+ sized_bound
509
+ }
510
+
511
+ fn is_sized_bound ( & self , cx : & DocContext ) -> bool {
512
+ use syntax:: ast:: TraitBoundModifier as TBM ;
513
+ if let Some ( tcx) = cx. tcx_opt ( ) {
514
+ let sized_did = match tcx. lang_items . sized_trait ( ) {
515
+ Some ( did) => did,
516
+ None => return false
517
+ } ;
518
+ if let TyParamBound :: TraitBound ( PolyTrait {
519
+ trait_ : Type :: ResolvedPath { did, .. } , ..
520
+ } , TBM :: None ) = * self {
521
+ if did == sized_did {
522
+ return true
523
+ }
524
+ }
525
+ }
526
+ false
527
+ }
528
+ }
529
+
501
530
impl Clean < TyParamBound > for ast:: TyParamBound {
502
531
fn clean ( & self , cx : & DocContext ) -> TyParamBound {
503
532
match * self {
@@ -835,7 +864,9 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
835
864
fn clean ( & self , cx : & DocContext ) -> Type {
836
865
let trait_ = match self . trait_ref . clean ( cx) {
837
866
TyParamBound :: TraitBound ( t, _) => t. trait_ ,
838
- TyParamBound :: RegionBound ( _) => panic ! ( "cleaning a trait got a region??" ) ,
867
+ TyParamBound :: RegionBound ( _) => {
868
+ panic ! ( "cleaning a trait got a region" )
869
+ }
839
870
} ;
840
871
Type :: QPath {
841
872
name : self . item_name . clean ( cx) ,
@@ -868,28 +899,8 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
868
899
subst:: ParamSpace ) {
869
900
fn clean ( & self , cx : & DocContext ) -> Generics {
870
901
use std:: collections:: HashSet ;
871
- use syntax:: ast:: TraitBoundModifier as TBM ;
872
902
use self :: WherePredicate as WP ;
873
903
874
- fn has_sized_bound ( bounds : & [ TyParamBound ] , cx : & DocContext ) -> bool {
875
- if let Some ( tcx) = cx. tcx_opt ( ) {
876
- let sized_did = match tcx. lang_items . sized_trait ( ) {
877
- Some ( did) => did,
878
- None => return false
879
- } ;
880
- for bound in bounds {
881
- if let TyParamBound :: TraitBound ( PolyTrait {
882
- trait_ : Type :: ResolvedPath { did, .. } , ..
883
- } , TBM :: None ) = * bound {
884
- if did == sized_did {
885
- return true
886
- }
887
- }
888
- }
889
- }
890
- false
891
- }
892
-
893
904
let ( gens, preds, space) = * self ;
894
905
895
906
// Bounds in the type_params and lifetimes fields are repeated in the
@@ -904,34 +915,38 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
904
915
srp. clean ( cx)
905
916
} ) . collect :: < Vec < _ > > ( ) ;
906
917
907
- let where_predicates = preds. predicates . get_slice ( space)
908
- . to_vec ( ) . clean ( cx) ;
918
+ let mut where_predicates = preds. predicates . get_slice ( space)
919
+ . to_vec ( ) . clean ( cx) ;
909
920
910
- // Type parameters have a Sized bound by default unless removed with
921
+ // Type parameters and have a Sized bound by default unless removed with
911
922
// ?Sized. Scan through the predicates and mark any type parameter with
912
923
// a Sized bound, removing the bounds as we find them.
924
+ //
925
+ // Note that associated types also have a sized bound by default, but we
926
+ // don't actually konw the set of associated types right here so that's
927
+ // handled in cleaning associated types
913
928
let mut sized_params = HashSet :: new ( ) ;
914
- let mut where_predicates = where_predicates. into_iter ( ) . filter_map ( |pred| {
915
- if let WP :: BoundPredicate { ty : Type :: Generic ( ref g) , ref bounds } = pred {
916
- if has_sized_bound ( & * * bounds, cx) {
917
- sized_params. insert ( g. clone ( ) ) ;
918
- return None
929
+ where_predicates. retain ( |pred| {
930
+ match * pred {
931
+ WP :: BoundPredicate { ty : Generic ( ref g) , ref bounds } => {
932
+ if bounds. iter ( ) . any ( |b| b. is_sized_bound ( cx) ) {
933
+ sized_params. insert ( g. clone ( ) ) ;
934
+ false
935
+ } else {
936
+ true
937
+ }
919
938
}
939
+ _ => true ,
920
940
}
921
- Some ( pred)
922
- } ) . collect :: < Vec < _ > > ( ) ;
941
+ } ) ;
923
942
924
- // Finally, run through the type parameters again and insert a ?Sized
943
+ // Run through the type parameters again and insert a ?Sized
925
944
// unbound for any we didn't find to be Sized.
926
945
for tp in & stripped_typarams {
927
946
if !sized_params. contains ( & tp. name ) {
928
- let mut sized_bound = ty:: BuiltinBound :: BoundSized . clean ( cx) ;
929
- if let TyParamBound :: TraitBound ( _, ref mut tbm) = sized_bound {
930
- * tbm = TBM :: Maybe
931
- } ;
932
947
where_predicates. push ( WP :: BoundPredicate {
933
948
ty : Type :: Generic ( tp. name . clone ( ) ) ,
934
- bounds : vec ! [ sized_bound ]
949
+ bounds : vec ! [ TyParamBound :: maybe_sized ( cx ) ] ,
935
950
} )
936
951
}
937
952
}
@@ -1597,17 +1612,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
1597
1612
}
1598
1613
ty:: ty_tup( ref t) => Tuple ( t. clean ( cx) ) ,
1599
1614
1600
- ty:: ty_projection( ref data) => {
1601
- let trait_ref = match data. trait_ref . clean ( cx) {
1602
- TyParamBound :: TraitBound ( t, _) => t. trait_ ,
1603
- TyParamBound :: RegionBound ( _) => panic ! ( "cleaning a trait got a region??" ) ,
1604
- } ;
1605
- Type :: QPath {
1606
- name : data. item_name . clean ( cx) ,
1607
- self_type : box data. trait_ref . self_ty ( ) . clean ( cx) ,
1608
- trait_ : box trait_ref,
1609
- }
1610
- }
1615
+ ty:: ty_projection( ref data) => data. clean ( cx) ,
1611
1616
1612
1617
ty:: ty_param( ref p) => Generic ( token:: get_name ( p. name ) . to_string ( ) ) ,
1613
1618
@@ -1881,6 +1886,22 @@ pub struct Path {
1881
1886
pub segments : Vec < PathSegment > ,
1882
1887
}
1883
1888
1889
+ impl Path {
1890
+ pub fn singleton ( name : String ) -> Path {
1891
+ Path {
1892
+ global : false ,
1893
+ segments : vec ! [ PathSegment {
1894
+ name: name,
1895
+ params: PathParameters :: AngleBracketed {
1896
+ lifetimes: Vec :: new( ) ,
1897
+ types: Vec :: new( ) ,
1898
+ bindings: Vec :: new( )
1899
+ }
1900
+ } ]
1901
+ }
1902
+ }
1903
+ }
1904
+
1884
1905
impl Clean < Path > for ast:: Path {
1885
1906
fn clean ( & self , cx : & DocContext ) -> Path {
1886
1907
Path {
@@ -2516,21 +2537,66 @@ impl Clean<Stability> for attr::Stability {
2516
2537
2517
2538
impl Clean < Item > for ty:: AssociatedType {
2518
2539
fn clean ( & self , cx : & DocContext ) -> Item {
2540
+ // When loading a cross-crate associated type, the bounds for this type
2541
+ // are actually located on the trait/impl itself, so we need to load
2542
+ // all of the generics from there and then look for bounds that are
2543
+ // applied to this associated type in question.
2544
+ let predicates = ty:: lookup_predicates ( cx. tcx ( ) , self . container . id ( ) ) ;
2545
+ let generics = match self . container {
2546
+ ty:: TraitContainer ( did) => {
2547
+ let def = ty:: lookup_trait_def ( cx. tcx ( ) , did) ;
2548
+ ( & def. generics , & predicates, subst:: TypeSpace ) . clean ( cx)
2549
+ }
2550
+ ty:: ImplContainer ( did) => {
2551
+ let ty = ty:: lookup_item_type ( cx. tcx ( ) , did) ;
2552
+ ( & ty. generics , & predicates, subst:: TypeSpace ) . clean ( cx)
2553
+ }
2554
+ } ;
2555
+ let my_name = self . name . clean ( cx) ;
2556
+ let mut bounds = generics. where_predicates . iter ( ) . filter_map ( |pred| {
2557
+ let ( name, self_type, trait_, bounds) = match * pred {
2558
+ WherePredicate :: BoundPredicate {
2559
+ ty : QPath { ref name, ref self_type, ref trait_ } ,
2560
+ ref bounds
2561
+ } => ( name, self_type, trait_, bounds) ,
2562
+ _ => return None ,
2563
+ } ;
2564
+ if * name != my_name { return None }
2565
+ match * * trait_ {
2566
+ ResolvedPath { did, .. } if did == self . container . id ( ) => { }
2567
+ _ => return None ,
2568
+ }
2569
+ match * * self_type {
2570
+ Generic ( ref s) if * s == "Self" => { }
2571
+ _ => return None ,
2572
+ }
2573
+ Some ( bounds)
2574
+ } ) . flat_map ( |i| i. iter ( ) . cloned ( ) ) . collect :: < Vec < _ > > ( ) ;
2575
+
2576
+ // Our Sized/?Sized bound didn't get handled when creating the generics
2577
+ // because we didn't actually get our whole set of bounds until just now
2578
+ // (some of them may have come from the trait). If we do have a sized
2579
+ // bound, we remove it, and if we don't then we add the `?Sized` bound
2580
+ // at the end.
2581
+ match bounds. iter ( ) . position ( |b| b. is_sized_bound ( cx) ) {
2582
+ Some ( i) => { bounds. remove ( i) ; }
2583
+ None => bounds. push ( TyParamBound :: maybe_sized ( cx) ) ,
2584
+ }
2585
+
2519
2586
Item {
2520
2587
source : DUMMY_SP . clean ( cx) ,
2521
2588
name : Some ( self . name . clean ( cx) ) ,
2522
- attrs : Vec :: new ( ) ,
2523
- // FIXME(#20727): bounds are missing and need to be filled in from the
2524
- // predicates on the trait itself
2525
- inner : AssociatedTypeItem ( vec ! [ ] , None ) ,
2526
- visibility : None ,
2589
+ attrs : inline:: load_attrs ( cx, cx. tcx ( ) , self . def_id ) ,
2590
+ inner : AssociatedTypeItem ( bounds, None ) ,
2591
+ visibility : self . vis . clean ( cx) ,
2527
2592
def_id : self . def_id ,
2528
- stability : None ,
2593
+ stability : stability :: lookup ( cx . tcx ( ) , self . def_id ) . clean ( cx ) ,
2529
2594
}
2530
2595
}
2531
2596
}
2532
2597
2533
- impl < ' a > Clean < Typedef > for ( ty:: TypeScheme < ' a > , ty:: GenericPredicates < ' a > , ParamSpace ) {
2598
+ impl < ' a > Clean < Typedef > for ( ty:: TypeScheme < ' a > , ty:: GenericPredicates < ' a > ,
2599
+ ParamSpace ) {
2534
2600
fn clean ( & self , cx : & DocContext ) -> Typedef {
2535
2601
let ( ref ty_scheme, ref predicates, ps) = * self ;
2536
2602
Typedef {
0 commit comments