Skip to content

Commit 5f9e263

Browse files
committed
Support nested impl Trait
1 parent 9beff38 commit 5f9e263

File tree

3 files changed

+41
-25
lines changed

3 files changed

+41
-25
lines changed

src/librustdoc/clean/mod.rs

+33-25
Original file line numberDiff line numberDiff line change
@@ -1720,11 +1720,13 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
17201720
ty::GenericParamDefKind::Const { .. } => None,
17211721
}).collect::<Vec<GenericParamDef>>();
17221722

1723-
// (param index, def id of trait) -> (name, type)
1724-
let mut impl_trait_proj = FxHashMap::<(u32, DefId), Vec<(String, Type)>>::default();
1723+
// param index -> [(DefId of trait, associated type name, type)]
1724+
let mut impl_trait_proj =
1725+
FxHashMap::<u32, Vec<(DefId, String, Ty<'tcx>)>>::default();
17251726

17261727
let mut where_predicates = preds.predicates.iter()
17271728
.flat_map(|(p, _)| {
1729+
let mut projection = None;
17281730
let param_idx = (|| {
17291731
if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
17301732
if let ty::Param(param) = trait_ref.self_ty().sty {
@@ -1734,8 +1736,9 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
17341736
if let ty::Param(param) = outlives.skip_binder().0.sty {
17351737
return Some(param.index);
17361738
}
1737-
} else if let ty::Predicate::Projection(proj) = p {
1738-
if let ty::Param(param) = proj.skip_binder().projection_ty.self_ty().sty {
1739+
} else if let ty::Predicate::Projection(p) = p {
1740+
if let ty::Param(param) = p.skip_binder().projection_ty.self_ty().sty {
1741+
projection = Some(p);
17391742
return Some(param.index);
17401743
}
17411744
}
@@ -1755,16 +1758,15 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
17551758
.filter(|b| !b.is_sized_bound(cx))
17561759
);
17571760

1758-
let proj = match &p {
1759-
WherePredicate::EqPredicate { lhs, rhs } => Some((lhs, rhs))
1760-
.and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs))),
1761-
_ => None,
1762-
};
1763-
if let Some(((_, trait_did, name), rhs)) = proj {
1761+
let proj = projection
1762+
.map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().ty));
1763+
if let Some(((_, trait_did, name), rhs)) =
1764+
proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs)))
1765+
{
17641766
impl_trait_proj
1765-
.entry((param_idx, trait_did))
1767+
.entry(param_idx)
17661768
.or_default()
1767-
.push((name.to_string(), rhs.clone()));
1769+
.push((trait_did, name.to_string(), rhs));
17681770
}
17691771

17701772
return None;
@@ -1775,18 +1777,6 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
17751777
})
17761778
.collect::<Vec<_>>();
17771779

1778-
for ((param_idx, trait_did), bounds) in impl_trait_proj {
1779-
for (name, rhs) in bounds {
1780-
simplify::merge_bounds(
1781-
cx,
1782-
impl_trait.get_mut(&param_idx.into()).unwrap(),
1783-
trait_did,
1784-
&name,
1785-
&rhs,
1786-
);
1787-
}
1788-
}
1789-
17901780
// Move `TraitPredicate`s to the front.
17911781
for (_, bounds) in impl_trait.iter_mut() {
17921782
bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b {
@@ -1796,7 +1786,25 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
17961786
});
17971787
}
17981788

1799-
cx.impl_trait_bounds.borrow_mut().extend(impl_trait);
1789+
for (param, mut bounds) in impl_trait {
1790+
if let crate::core::ImplTraitParam::ParamIndex(idx) = param {
1791+
if let Some(proj) = impl_trait_proj.remove(&idx) {
1792+
for (trait_did, name, rhs) in proj {
1793+
simplify::merge_bounds(
1794+
cx,
1795+
&mut bounds,
1796+
trait_did,
1797+
&name,
1798+
&rhs.clean(cx),
1799+
);
1800+
}
1801+
}
1802+
} else {
1803+
unreachable!();
1804+
}
1805+
1806+
cx.impl_trait_bounds.borrow_mut().insert(param, bounds);
1807+
}
18001808

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

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

+2
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

+6
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)