@@ -45,7 +45,7 @@ use std::cell::RefCell;
45
45
use std:: sync:: Arc ;
46
46
use std:: u32;
47
47
48
- use crate :: core:: { self , DocContext } ;
48
+ use crate :: core:: { self , DocContext , ImplTraitParam } ;
49
49
use crate :: doctree;
50
50
use crate :: html:: render:: { cache, ExternalLocation } ;
51
51
use crate :: html:: item_type:: ItemType ;
@@ -1540,7 +1540,7 @@ impl Clean<GenericParamDef> for ty::GenericParamDef {
1540
1540
ty:: GenericParamDefKind :: Lifetime => {
1541
1541
( self . name . to_string ( ) , GenericParamDefKind :: Lifetime )
1542
1542
}
1543
- ty:: GenericParamDefKind :: Type { has_default, .. } => {
1543
+ ty:: GenericParamDefKind :: Type { has_default, synthetic , .. } => {
1544
1544
cx. renderinfo . borrow_mut ( ) . external_param_names
1545
1545
. insert ( self . def_id , self . name . clean ( cx) ) ;
1546
1546
let default = if has_default {
@@ -1552,7 +1552,7 @@ impl Clean<GenericParamDef> for ty::GenericParamDef {
1552
1552
did : self . def_id ,
1553
1553
bounds : vec ! [ ] , // These are filled in from the where-clauses.
1554
1554
default,
1555
- synthetic : None ,
1555
+ synthetic,
1556
1556
} )
1557
1557
}
1558
1558
ty:: GenericParamDefKind :: Const { .. } => {
@@ -1641,7 +1641,7 @@ impl Clean<Generics> for hir::Generics {
1641
1641
match param. kind {
1642
1642
GenericParamDefKind :: Lifetime => unreachable ! ( ) ,
1643
1643
GenericParamDefKind :: Type { did, ref bounds, .. } => {
1644
- cx. impl_trait_bounds . borrow_mut ( ) . insert ( did, bounds. clone ( ) ) ;
1644
+ cx. impl_trait_bounds . borrow_mut ( ) . insert ( did. into ( ) , bounds. clone ( ) ) ;
1645
1645
}
1646
1646
GenericParamDefKind :: Const { .. } => unreachable ! ( ) ,
1647
1647
}
@@ -1693,26 +1693,123 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
1693
1693
& ' a & ' tcx ty:: GenericPredicates < ' tcx > ) {
1694
1694
fn clean ( & self , cx : & DocContext < ' _ > ) -> Generics {
1695
1695
use self :: WherePredicate as WP ;
1696
+ use std:: collections:: BTreeMap ;
1696
1697
1697
1698
let ( gens, preds) = * self ;
1698
1699
1700
+ // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
1701
+ // since `Clean for ty::Predicate` would consume them.
1702
+ let mut impl_trait = BTreeMap :: < ImplTraitParam , Vec < GenericBound > > :: default ( ) ;
1703
+
1699
1704
// Bounds in the type_params and lifetimes fields are repeated in the
1700
1705
// predicates field (see rustc_typeck::collect::ty_generics), so remove
1701
1706
// them.
1702
- let stripped_typarams = gens. params . iter ( ) . filter_map ( |param| match param. kind {
1703
- ty:: GenericParamDefKind :: Lifetime => None ,
1704
- ty:: GenericParamDefKind :: Type { .. } => {
1705
- if param. name . as_symbol ( ) == kw:: SelfUpper {
1706
- assert_eq ! ( param. index, 0 ) ;
1707
- return None ;
1707
+ let stripped_typarams = gens. params . iter ( )
1708
+ . filter_map ( |param| match param. kind {
1709
+ ty:: GenericParamDefKind :: Lifetime => None ,
1710
+ ty:: GenericParamDefKind :: Type { synthetic, .. } => {
1711
+ if param. name . as_symbol ( ) == kw:: SelfUpper {
1712
+ assert_eq ! ( param. index, 0 ) ;
1713
+ return None ;
1714
+ }
1715
+ if synthetic == Some ( hir:: SyntheticTyParamKind :: ImplTrait ) {
1716
+ impl_trait. insert ( param. index . into ( ) , vec ! [ ] ) ;
1717
+ return None ;
1718
+ }
1719
+ Some ( param. clean ( cx) )
1720
+ }
1721
+ ty:: GenericParamDefKind :: Const { .. } => None ,
1722
+ } ) . collect :: < Vec < GenericParamDef > > ( ) ;
1723
+
1724
+ // param index -> [(DefId of trait, associated type name, type)]
1725
+ let mut impl_trait_proj =
1726
+ FxHashMap :: < u32 , Vec < ( DefId , String , Ty < ' tcx > ) > > :: default ( ) ;
1727
+
1728
+ let where_predicates = preds. predicates . iter ( )
1729
+ . flat_map ( |( p, _) | {
1730
+ let mut projection = None ;
1731
+ let param_idx = ( || {
1732
+ if let Some ( trait_ref) = p. to_opt_poly_trait_ref ( ) {
1733
+ if let ty:: Param ( param) = trait_ref. self_ty ( ) . sty {
1734
+ return Some ( param. index ) ;
1735
+ }
1736
+ } else if let Some ( outlives) = p. to_opt_type_outlives ( ) {
1737
+ if let ty:: Param ( param) = outlives. skip_binder ( ) . 0 . sty {
1738
+ return Some ( param. index ) ;
1739
+ }
1740
+ } else if let ty:: Predicate :: Projection ( p) = p {
1741
+ if let ty:: Param ( param) = p. skip_binder ( ) . projection_ty . self_ty ( ) . sty {
1742
+ projection = Some ( p) ;
1743
+ return Some ( param. index ) ;
1744
+ }
1745
+ }
1746
+
1747
+ None
1748
+ } ) ( ) ;
1749
+
1750
+ if let Some ( param_idx) = param_idx {
1751
+ if let Some ( b) = impl_trait. get_mut ( & param_idx. into ( ) ) {
1752
+ let p = p. clean ( cx) ?;
1753
+
1754
+ b. extend (
1755
+ p. get_bounds ( )
1756
+ . into_iter ( )
1757
+ . flatten ( )
1758
+ . cloned ( )
1759
+ . filter ( |b| !b. is_sized_bound ( cx) )
1760
+ ) ;
1761
+
1762
+ let proj = projection
1763
+ . map ( |p| ( p. skip_binder ( ) . projection_ty . clean ( cx) , p. skip_binder ( ) . ty ) ) ;
1764
+ if let Some ( ( ( _, trait_did, name) , rhs) ) =
1765
+ proj. as_ref ( ) . and_then ( |( lhs, rhs) | Some ( ( lhs. projection ( ) ?, rhs) ) )
1766
+ {
1767
+ impl_trait_proj
1768
+ . entry ( param_idx)
1769
+ . or_default ( )
1770
+ . push ( ( trait_did, name. to_string ( ) , rhs) ) ;
1771
+ }
1772
+
1773
+ return None ;
1774
+ }
1775
+ }
1776
+
1777
+ Some ( p)
1778
+ } )
1779
+ . collect :: < Vec < _ > > ( ) ;
1780
+
1781
+ for ( param, mut bounds) in impl_trait {
1782
+ // Move trait bounds to the front.
1783
+ bounds. sort_by_key ( |b| if let GenericBound :: TraitBound ( ..) = b {
1784
+ false
1785
+ } else {
1786
+ true
1787
+ } ) ;
1788
+
1789
+ if let crate :: core:: ImplTraitParam :: ParamIndex ( idx) = param {
1790
+ if let Some ( proj) = impl_trait_proj. remove ( & idx) {
1791
+ for ( trait_did, name, rhs) in proj {
1792
+ simplify:: merge_bounds (
1793
+ cx,
1794
+ & mut bounds,
1795
+ trait_did,
1796
+ & name,
1797
+ & rhs. clean ( cx) ,
1798
+ ) ;
1799
+ }
1708
1800
}
1709
- Some ( param. clean ( cx) )
1801
+ } else {
1802
+ unreachable ! ( ) ;
1710
1803
}
1711
- ty:: GenericParamDefKind :: Const { .. } => None ,
1712
- } ) . collect :: < Vec < GenericParamDef > > ( ) ;
1713
1804
1714
- let mut where_predicates = preds. predicates . iter ( )
1715
- . flat_map ( |( p, _) | p. clean ( cx) )
1805
+ cx. impl_trait_bounds . borrow_mut ( ) . insert ( param, bounds) ;
1806
+ }
1807
+
1808
+ // Now that `cx.impl_trait_bounds` is populated, we can process
1809
+ // remaining predicates which could contain `impl Trait`.
1810
+ let mut where_predicates = where_predicates
1811
+ . into_iter ( )
1812
+ . flat_map ( |p| p. clean ( cx) )
1716
1813
. collect :: < Vec < _ > > ( ) ;
1717
1814
1718
1815
// Type parameters and have a Sized bound by default unless removed with
@@ -2613,6 +2710,21 @@ impl Type {
2613
2710
_ => false ,
2614
2711
}
2615
2712
}
2713
+
2714
+ pub fn projection ( & self ) -> Option < ( & Type , DefId , & str ) > {
2715
+ let ( self_, trait_, name) = match self {
2716
+ QPath { ref self_type, ref trait_, ref name } => {
2717
+ ( self_type, trait_, name)
2718
+ }
2719
+ _ => return None ,
2720
+ } ;
2721
+ let trait_did = match * * trait_ {
2722
+ ResolvedPath { did, .. } => did,
2723
+ _ => return None ,
2724
+ } ;
2725
+ Some ( ( & self_, trait_did, name) )
2726
+ }
2727
+
2616
2728
}
2617
2729
2618
2730
impl GetDefId for Type {
@@ -2791,7 +2903,7 @@ impl Clean<Type> for hir::Ty {
2791
2903
if let Some ( new_ty) = cx. ty_substs . borrow ( ) . get ( & did) . cloned ( ) {
2792
2904
return new_ty;
2793
2905
}
2794
- if let Some ( bounds) = cx. impl_trait_bounds . borrow_mut ( ) . remove ( & did) {
2906
+ if let Some ( bounds) = cx. impl_trait_bounds . borrow_mut ( ) . remove ( & did. into ( ) ) {
2795
2907
return ImplTrait ( bounds) ;
2796
2908
}
2797
2909
}
@@ -3082,7 +3194,13 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
3082
3194
3083
3195
ty:: Projection ( ref data) => data. clean ( cx) ,
3084
3196
3085
- ty:: Param ( ref p) => Generic ( p. name . to_string ( ) ) ,
3197
+ ty:: Param ( ref p) => {
3198
+ if let Some ( bounds) = cx. impl_trait_bounds . borrow_mut ( ) . remove ( & p. index . into ( ) ) {
3199
+ ImplTrait ( bounds)
3200
+ } else {
3201
+ Generic ( p. name . to_string ( ) )
3202
+ }
3203
+ }
3086
3204
3087
3205
ty:: Opaque ( def_id, substs) => {
3088
3206
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
0 commit comments