@@ -47,7 +47,7 @@ use std::u32;
47
47
48
48
use parking_lot:: ReentrantMutex ;
49
49
50
- use crate :: core:: { self , DocContext } ;
50
+ use crate :: core:: { self , DocContext , ImplTraitParam } ;
51
51
use crate :: doctree;
52
52
use crate :: visit_ast;
53
53
use crate :: html:: render:: { cache, ExternalLocation } ;
@@ -1536,7 +1536,7 @@ impl Clean<GenericParamDef> for ty::GenericParamDef {
1536
1536
ty:: GenericParamDefKind :: Lifetime => {
1537
1537
( self . name . to_string ( ) , GenericParamDefKind :: Lifetime )
1538
1538
}
1539
- ty:: GenericParamDefKind :: Type { has_default, .. } => {
1539
+ ty:: GenericParamDefKind :: Type { has_default, synthetic , .. } => {
1540
1540
cx. renderinfo . borrow_mut ( ) . external_param_names
1541
1541
. insert ( self . def_id , self . name . clean ( cx) ) ;
1542
1542
let default = if has_default {
@@ -1548,7 +1548,7 @@ impl Clean<GenericParamDef> for ty::GenericParamDef {
1548
1548
did : self . def_id ,
1549
1549
bounds : vec ! [ ] , // These are filled in from the where-clauses.
1550
1550
default,
1551
- synthetic : None ,
1551
+ synthetic,
1552
1552
} )
1553
1553
}
1554
1554
ty:: GenericParamDefKind :: Const { .. } => {
@@ -1637,7 +1637,7 @@ impl Clean<Generics> for hir::Generics {
1637
1637
match param. kind {
1638
1638
GenericParamDefKind :: Lifetime => unreachable ! ( ) ,
1639
1639
GenericParamDefKind :: Type { did, ref bounds, .. } => {
1640
- cx. impl_trait_bounds . borrow_mut ( ) . insert ( did, bounds. clone ( ) ) ;
1640
+ cx. impl_trait_bounds . borrow_mut ( ) . insert ( did. into ( ) , bounds. clone ( ) ) ;
1641
1641
}
1642
1642
GenericParamDefKind :: Const { .. } => unreachable ! ( ) ,
1643
1643
}
@@ -1692,25 +1692,116 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
1692
1692
1693
1693
let ( gens, preds) = * self ;
1694
1694
1695
+ // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
1696
+ // since `Clean for ty::Predicate` would consume them.
1697
+ let mut impl_trait = FxHashMap :: < ImplTraitParam , Vec < GenericBound > > :: default ( ) ;
1698
+
1695
1699
// Bounds in the type_params and lifetimes fields are repeated in the
1696
1700
// predicates field (see rustc_typeck::collect::ty_generics), so remove
1697
1701
// them.
1698
- let stripped_typarams = gens. params . iter ( ) . filter_map ( |param| match param. kind {
1699
- ty:: GenericParamDefKind :: Lifetime => None ,
1700
- ty:: GenericParamDefKind :: Type { .. } => {
1701
- if param. name . as_symbol ( ) == kw:: SelfUpper {
1702
- assert_eq ! ( param. index, 0 ) ;
1703
- return None ;
1702
+ let stripped_typarams = gens. params . iter ( )
1703
+ . filter_map ( |param| match param. kind {
1704
+ ty:: GenericParamDefKind :: Lifetime => None ,
1705
+ ty:: GenericParamDefKind :: Type { synthetic, .. } => {
1706
+ if param. name . as_symbol ( ) == kw:: SelfUpper {
1707
+ assert_eq ! ( param. index, 0 ) ;
1708
+ return None ;
1709
+ }
1710
+ if synthetic == Some ( hir:: SyntheticTyParamKind :: ImplTrait ) {
1711
+ impl_trait. insert ( param. index . into ( ) , vec ! [ ] ) ;
1712
+ return None ;
1713
+ }
1714
+ Some ( param. clean ( cx) )
1704
1715
}
1705
- Some ( param. clean ( cx) )
1706
- }
1707
- ty:: GenericParamDefKind :: Const { .. } => None ,
1708
- } ) . collect :: < Vec < GenericParamDef > > ( ) ;
1716
+ ty:: GenericParamDefKind :: Const { .. } => None ,
1717
+ } ) . collect :: < Vec < GenericParamDef > > ( ) ;
1718
+
1719
+ // param index -> [(DefId of trait, associated type name, type)]
1720
+ let mut impl_trait_proj =
1721
+ FxHashMap :: < u32 , Vec < ( DefId , String , Ty < ' tcx > ) > > :: default ( ) ;
1709
1722
1710
1723
let mut where_predicates = preds. predicates . iter ( )
1711
- . flat_map ( |( p, _) | p. clean ( cx) )
1724
+ . flat_map ( |( p, _) | {
1725
+ let mut projection = None ;
1726
+ let param_idx = ( || {
1727
+ if let Some ( trait_ref) = p. to_opt_poly_trait_ref ( ) {
1728
+ if let ty:: Param ( param) = trait_ref. self_ty ( ) . sty {
1729
+ return Some ( param. index ) ;
1730
+ }
1731
+ } else if let Some ( outlives) = p. to_opt_type_outlives ( ) {
1732
+ if let ty:: Param ( param) = outlives. skip_binder ( ) . 0 . sty {
1733
+ return Some ( param. index ) ;
1734
+ }
1735
+ } else if let ty:: Predicate :: Projection ( p) = p {
1736
+ if let ty:: Param ( param) = p. skip_binder ( ) . projection_ty . self_ty ( ) . sty {
1737
+ projection = Some ( p) ;
1738
+ return Some ( param. index ) ;
1739
+ }
1740
+ }
1741
+
1742
+ None
1743
+ } ) ( ) ;
1744
+
1745
+ let p = p. clean ( cx) ?;
1746
+
1747
+ if let Some ( param_idx) = param_idx {
1748
+ if let Some ( b) = impl_trait. get_mut ( & param_idx. into ( ) ) {
1749
+ b. extend (
1750
+ p. get_bounds ( )
1751
+ . into_iter ( )
1752
+ . flatten ( )
1753
+ . cloned ( )
1754
+ . filter ( |b| !b. is_sized_bound ( cx) )
1755
+ ) ;
1756
+
1757
+ let proj = projection
1758
+ . map ( |p| ( p. skip_binder ( ) . projection_ty . clean ( cx) , p. skip_binder ( ) . ty ) ) ;
1759
+ if let Some ( ( ( _, trait_did, name) , rhs) ) =
1760
+ proj. as_ref ( ) . and_then ( |( lhs, rhs) | Some ( ( lhs. projection ( ) ?, rhs) ) )
1761
+ {
1762
+ impl_trait_proj
1763
+ . entry ( param_idx)
1764
+ . or_default ( )
1765
+ . push ( ( trait_did, name. to_string ( ) , rhs) ) ;
1766
+ }
1767
+
1768
+ return None ;
1769
+ }
1770
+ }
1771
+
1772
+ Some ( p)
1773
+ } )
1712
1774
. collect :: < Vec < _ > > ( ) ;
1713
1775
1776
+ // Move `TraitPredicate`s to the front.
1777
+ for ( _, bounds) in impl_trait. iter_mut ( ) {
1778
+ bounds. sort_by_key ( |b| if let GenericBound :: TraitBound ( ..) = b {
1779
+ false
1780
+ } else {
1781
+ true
1782
+ } ) ;
1783
+ }
1784
+
1785
+ for ( param, mut bounds) in impl_trait {
1786
+ if let crate :: core:: ImplTraitParam :: ParamIndex ( idx) = param {
1787
+ if let Some ( proj) = impl_trait_proj. remove ( & idx) {
1788
+ for ( trait_did, name, rhs) in proj {
1789
+ simplify:: merge_bounds (
1790
+ cx,
1791
+ & mut bounds,
1792
+ trait_did,
1793
+ & name,
1794
+ & rhs. clean ( cx) ,
1795
+ ) ;
1796
+ }
1797
+ }
1798
+ } else {
1799
+ unreachable ! ( ) ;
1800
+ }
1801
+
1802
+ cx. impl_trait_bounds . borrow_mut ( ) . insert ( param, bounds) ;
1803
+ }
1804
+
1714
1805
// Type parameters and have a Sized bound by default unless removed with
1715
1806
// ?Sized. Scan through the predicates and mark any type parameter with
1716
1807
// a Sized bound, removing the bounds as we find them.
@@ -2609,6 +2700,21 @@ impl Type {
2609
2700
_ => false ,
2610
2701
}
2611
2702
}
2703
+
2704
+ pub fn projection ( & self ) -> Option < ( & Type , DefId , & str ) > {
2705
+ let ( self_, trait_, name) = match self {
2706
+ QPath { ref self_type, ref trait_, ref name } => {
2707
+ ( self_type, trait_, name)
2708
+ }
2709
+ _ => return None ,
2710
+ } ;
2711
+ let trait_did = match * * trait_ {
2712
+ ResolvedPath { did, .. } => did,
2713
+ _ => return None ,
2714
+ } ;
2715
+ Some ( ( & self_, trait_did, name) )
2716
+ }
2717
+
2612
2718
}
2613
2719
2614
2720
impl GetDefId for Type {
@@ -2787,7 +2893,7 @@ impl Clean<Type> for hir::Ty {
2787
2893
if let Some ( new_ty) = cx. ty_substs . borrow ( ) . get ( & did) . cloned ( ) {
2788
2894
return new_ty;
2789
2895
}
2790
- if let Some ( bounds) = cx. impl_trait_bounds . borrow_mut ( ) . remove ( & did) {
2896
+ if let Some ( bounds) = cx. impl_trait_bounds . borrow_mut ( ) . remove ( & did. into ( ) ) {
2791
2897
return ImplTrait ( bounds) ;
2792
2898
}
2793
2899
}
@@ -3078,7 +3184,13 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
3078
3184
3079
3185
ty:: Projection ( ref data) => data. clean ( cx) ,
3080
3186
3081
- ty:: Param ( ref p) => Generic ( p. name . to_string ( ) ) ,
3187
+ ty:: Param ( ref p) => {
3188
+ if let Some ( bounds) = cx. impl_trait_bounds . borrow_mut ( ) . remove ( & p. index . into ( ) ) {
3189
+ ImplTrait ( bounds)
3190
+ } else {
3191
+ Generic ( p. name . to_string ( ) )
3192
+ }
3193
+ }
3082
3194
3083
3195
ty:: Opaque ( def_id, substs) => {
3084
3196
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
0 commit comments