@@ -45,7 +45,7 @@ use std::cell::RefCell;
4545use std:: sync:: Arc ;
4646use std:: u32;
4747
48- use crate :: core:: { self , DocContext } ;
48+ use crate :: core:: { self , DocContext , ImplTraitParam } ;
4949use crate :: doctree;
5050use crate :: html:: render:: { cache, ExternalLocation } ;
5151use crate :: html:: item_type:: ItemType ;
@@ -1540,7 +1540,7 @@ impl Clean<GenericParamDef> for ty::GenericParamDef {
15401540 ty:: GenericParamDefKind :: Lifetime => {
15411541 ( self . name . to_string ( ) , GenericParamDefKind :: Lifetime )
15421542 }
1543- ty:: GenericParamDefKind :: Type { has_default, .. } => {
1543+ ty:: GenericParamDefKind :: Type { has_default, synthetic , .. } => {
15441544 cx. renderinfo . borrow_mut ( ) . external_param_names
15451545 . insert ( self . def_id , self . name . clean ( cx) ) ;
15461546 let default = if has_default {
@@ -1552,7 +1552,7 @@ impl Clean<GenericParamDef> for ty::GenericParamDef {
15521552 did : self . def_id ,
15531553 bounds : vec ! [ ] , // These are filled in from the where-clauses.
15541554 default,
1555- synthetic : None ,
1555+ synthetic,
15561556 } )
15571557 }
15581558 ty:: GenericParamDefKind :: Const { .. } => {
@@ -1641,7 +1641,7 @@ impl Clean<Generics> for hir::Generics {
16411641 match param. kind {
16421642 GenericParamDefKind :: Lifetime => unreachable ! ( ) ,
16431643 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 ( ) ) ;
16451645 }
16461646 GenericParamDefKind :: Const { .. } => unreachable ! ( ) ,
16471647 }
@@ -1693,26 +1693,123 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
16931693 & ' a & ' tcx ty:: GenericPredicates < ' tcx > ) {
16941694 fn clean ( & self , cx : & DocContext < ' _ > ) -> Generics {
16951695 use self :: WherePredicate as WP ;
1696+ use std:: collections:: BTreeMap ;
16961697
16971698 let ( gens, preds) = * self ;
16981699
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+
16991704 // Bounds in the type_params and lifetimes fields are repeated in the
17001705 // predicates field (see rustc_typeck::collect::ty_generics), so remove
17011706 // 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+ }
17081800 }
1709- Some ( param. clean ( cx) )
1801+ } else {
1802+ unreachable ! ( ) ;
17101803 }
1711- ty:: GenericParamDefKind :: Const { .. } => None ,
1712- } ) . collect :: < Vec < GenericParamDef > > ( ) ;
17131804
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) )
17161813 . collect :: < Vec < _ > > ( ) ;
17171814
17181815 // Type parameters and have a Sized bound by default unless removed with
@@ -2613,6 +2710,21 @@ impl Type {
26132710 _ => false ,
26142711 }
26152712 }
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+
26162728}
26172729
26182730impl GetDefId for Type {
@@ -2791,7 +2903,7 @@ impl Clean<Type> for hir::Ty {
27912903 if let Some ( new_ty) = cx. ty_substs . borrow ( ) . get ( & did) . cloned ( ) {
27922904 return new_ty;
27932905 }
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 ( ) ) {
27952907 return ImplTrait ( bounds) ;
27962908 }
27972909 }
@@ -3082,7 +3194,13 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
30823194
30833195 ty:: Projection ( ref data) => data. clean ( cx) ,
30843196
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+ }
30863204
30873205 ty:: Opaque ( def_id, substs) => {
30883206 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
0 commit comments