@@ -47,7 +47,7 @@ use std::u32;
4747
4848use parking_lot:: ReentrantMutex ;
4949
50- use crate :: core:: { self , DocContext } ;
50+ use crate :: core:: { self , DocContext , ImplTraitParam } ;
5151use crate :: doctree;
5252use crate :: visit_ast;
5353use crate :: html:: render:: { cache, ExternalLocation } ;
@@ -1536,7 +1536,7 @@ impl Clean<GenericParamDef> for ty::GenericParamDef {
15361536 ty:: GenericParamDefKind :: Lifetime => {
15371537 ( self . name . to_string ( ) , GenericParamDefKind :: Lifetime )
15381538 }
1539- ty:: GenericParamDefKind :: Type { has_default, .. } => {
1539+ ty:: GenericParamDefKind :: Type { has_default, synthetic , .. } => {
15401540 cx. renderinfo . borrow_mut ( ) . external_param_names
15411541 . insert ( self . def_id , self . name . clean ( cx) ) ;
15421542 let default = if has_default {
@@ -1548,7 +1548,7 @@ impl Clean<GenericParamDef> for ty::GenericParamDef {
15481548 did : self . def_id ,
15491549 bounds : vec ! [ ] , // These are filled in from the where-clauses.
15501550 default,
1551- synthetic : None ,
1551+ synthetic,
15521552 } )
15531553 }
15541554 ty:: GenericParamDefKind :: Const { .. } => {
@@ -1637,7 +1637,7 @@ impl Clean<Generics> for hir::Generics {
16371637 match param. kind {
16381638 GenericParamDefKind :: Lifetime => unreachable ! ( ) ,
16391639 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 ( ) ) ;
16411641 }
16421642 GenericParamDefKind :: Const { .. } => unreachable ! ( ) ,
16431643 }
@@ -1692,25 +1692,116 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
16921692
16931693 let ( gens, preds) = * self ;
16941694
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+
16951699 // Bounds in the type_params and lifetimes fields are repeated in the
16961700 // predicates field (see rustc_typeck::collect::ty_generics), so remove
16971701 // 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) )
17041715 }
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 ( ) ;
17091722
17101723 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+ } )
17121774 . collect :: < Vec < _ > > ( ) ;
17131775
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+
17141805 // Type parameters and have a Sized bound by default unless removed with
17151806 // ?Sized. Scan through the predicates and mark any type parameter with
17161807 // a Sized bound, removing the bounds as we find them.
@@ -2609,6 +2700,21 @@ impl Type {
26092700 _ => false ,
26102701 }
26112702 }
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+
26122718}
26132719
26142720impl GetDefId for Type {
@@ -2787,7 +2893,7 @@ impl Clean<Type> for hir::Ty {
27872893 if let Some ( new_ty) = cx. ty_substs . borrow ( ) . get ( & did) . cloned ( ) {
27882894 return new_ty;
27892895 }
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 ( ) ) {
27912897 return ImplTrait ( bounds) ;
27922898 }
27932899 }
@@ -3078,7 +3184,13 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
30783184
30793185 ty:: Projection ( ref data) => data. clean ( cx) ,
30803186
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+ }
30823194
30833195 ty:: Opaque ( def_id, substs) => {
30843196 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
0 commit comments