Skip to content

Commit 65d391d

Browse files
committed
Support nested impl Trait
1 parent 9c84324 commit 65d391d

File tree

3 files changed

+40
-24
lines changed

3 files changed

+40
-24
lines changed

src/librustdoc/clean/mod.rs

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,10 +1717,12 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
17171717
}).collect::<Vec<GenericParamDef>>();
17181718

17191719
// (param index, def id of trait) -> (name, type)
1720-
let mut impl_trait_proj = FxHashMap::<(u32, DefId), Vec<(String, Type)>>::default();
1720+
let mut impl_trait_proj =
1721+
FxHashMap::<u32, Vec<(DefId, String, Ty<'tcx>)>>::default();
17211722

17221723
let mut where_predicates = preds.predicates.iter()
17231724
.flat_map(|(p, _)| {
1725+
let mut projection = None;
17241726
let param_idx = (|| {
17251727
if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
17261728
if let ty::Param(param) = trait_ref.self_ty().sty {
@@ -1730,8 +1732,9 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
17301732
if let ty::Param(param) = outlives.skip_binder().0.sty {
17311733
return Some(param.index);
17321734
}
1733-
} else if let ty::Predicate::Projection(proj) = p {
1734-
if let ty::Param(param) = proj.skip_binder().projection_ty.self_ty().sty {
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);
17351738
return Some(param.index);
17361739
}
17371740
}
@@ -1751,16 +1754,15 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
17511754
.filter(|b| !b.is_sized_bound(cx))
17521755
);
17531756

1754-
let proj = match &p {
1755-
WherePredicate::EqPredicate { lhs, rhs } => Some((lhs, rhs))
1756-
.and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs))),
1757-
_ => None,
1758-
};
1759-
if let Some(((_, trait_did, name), rhs)) = proj {
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+
{
17601762
impl_trait_proj
1761-
.entry((param_idx, trait_did))
1763+
.entry(param_idx)
17621764
.or_default()
1763-
.push((name.to_string(), rhs.clone()));
1765+
.push((trait_did, name.to_string(), rhs));
17641766
}
17651767

17661768
return None;
@@ -1771,18 +1773,6 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
17711773
})
17721774
.collect::<Vec<_>>();
17731775

1774-
for ((param_idx, trait_did), bounds) in impl_trait_proj {
1775-
for (name, rhs) in bounds {
1776-
simplify::merge_bounds(
1777-
cx,
1778-
impl_trait.get_mut(&param_idx.into()).unwrap(),
1779-
trait_did,
1780-
&name,
1781-
&rhs,
1782-
);
1783-
}
1784-
}
1785-
17861776
// Move `TraitPredicate`s to the front.
17871777
for (_, bounds) in impl_trait.iter_mut() {
17881778
bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b {
@@ -1792,7 +1782,25 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
17921782
});
17931783
}
17941784

1795-
cx.impl_trait_bounds.borrow_mut().extend(impl_trait);
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+
}
17961804

17971805
// Type parameters and have a Sized bound by default unless removed with
17981806
// ?Sized. Scan through the predicates and mark any type parameter with

src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ pub fn func<'a>(_x: impl Clone + Into<Vec<u8>> + 'a) {}
44

55
pub fn func2<T>(_x: impl Deref<Target = Option<T>> + Iterator<Item = T>, _y: impl Iterator<Item = u8>) {}
66

7+
pub fn func3(_x: impl Iterator<Item = impl Iterator<Item = u8>> + Clone) {}
8+
79
pub struct Foo;
810

911
impl Foo {

src/test/rustdoc/inline_cross/impl_trait.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,17 @@ extern crate impl_trait_aux;
88
pub use impl_trait_aux::func;
99

1010
// @has impl_trait/fn.func2.html
11+
// @has - '//pre[@class="rust fn"]' "func2<T>("
1112
// @has - '//pre[@class="rust fn"]' "_x: impl Deref<Target = Option<T>> + Iterator<Item = T>,"
1213
// @has - '//pre[@class="rust fn"]' "_y: impl Iterator<Item = u8>)"
1314
// @!has - '//pre[@class="rust fn"]' 'where'
1415
pub use impl_trait_aux::func2;
1516

17+
// @has impl_trait/fn.func3.html
18+
// @has - '//pre[@class="rust fn"]' "func3(_x: impl Clone + Iterator<Item = impl Iterator<Item = u8>>)"
19+
// @!has - '//pre[@class="rust fn"]' 'where'
20+
pub use impl_trait_aux::func3;
21+
1622
// @has impl_trait/struct.Foo.html
1723
// @has - '//code[@id="method.v"]' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a)"
1824
// @!has - '//code[@id="method.v"]' 'where'

0 commit comments

Comments
 (0)