Skip to content

Commit

Permalink
Support nested impl Trait
Browse files Browse the repository at this point in the history
  • Loading branch information
sinkuu committed Aug 19, 2019
1 parent 9beff38 commit 5f9e263
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 25 deletions.
58 changes: 33 additions & 25 deletions src/librustdoc/clean/mod.rs
Expand Up @@ -1720,11 +1720,13 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
ty::GenericParamDefKind::Const { .. } => None,
}).collect::<Vec<GenericParamDef>>();

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

let mut where_predicates = preds.predicates.iter()
.flat_map(|(p, _)| {
let mut projection = None;
let param_idx = (|| {
if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
if let ty::Param(param) = trait_ref.self_ty().sty {
Expand All @@ -1734,8 +1736,9 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
if let ty::Param(param) = outlives.skip_binder().0.sty {
return Some(param.index);
}
} else if let ty::Predicate::Projection(proj) = p {
if let ty::Param(param) = proj.skip_binder().projection_ty.self_ty().sty {
} else if let ty::Predicate::Projection(p) = p {
if let ty::Param(param) = p.skip_binder().projection_ty.self_ty().sty {
projection = Some(p);
return Some(param.index);
}
}
Expand All @@ -1755,16 +1758,15 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
.filter(|b| !b.is_sized_bound(cx))
);

let proj = match &p {
WherePredicate::EqPredicate { lhs, rhs } => Some((lhs, rhs))
.and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs))),
_ => None,
};
if let Some(((_, trait_did, name), rhs)) = proj {
let proj = projection
.map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().ty));
if let Some(((_, trait_did, name), rhs)) =
proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs)))
{
impl_trait_proj
.entry((param_idx, trait_did))
.entry(param_idx)
.or_default()
.push((name.to_string(), rhs.clone()));
.push((trait_did, name.to_string(), rhs));
}

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

for ((param_idx, trait_did), bounds) in impl_trait_proj {
for (name, rhs) in bounds {
simplify::merge_bounds(
cx,
impl_trait.get_mut(&param_idx.into()).unwrap(),
trait_did,
&name,
&rhs,
);
}
}

// Move `TraitPredicate`s to the front.
for (_, bounds) in impl_trait.iter_mut() {
bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b {
Expand All @@ -1796,7 +1786,25 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
});
}

cx.impl_trait_bounds.borrow_mut().extend(impl_trait);
for (param, mut bounds) in impl_trait {
if let crate::core::ImplTraitParam::ParamIndex(idx) = param {
if let Some(proj) = impl_trait_proj.remove(&idx) {
for (trait_did, name, rhs) in proj {
simplify::merge_bounds(
cx,
&mut bounds,
trait_did,
&name,
&rhs.clean(cx),
);
}
}
} else {
unreachable!();
}

cx.impl_trait_bounds.borrow_mut().insert(param, bounds);
}

// Type parameters and have a Sized bound by default unless removed with
// ?Sized. Scan through the predicates and mark any type parameter with
Expand Down
2 changes: 2 additions & 0 deletions src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs
Expand Up @@ -4,6 +4,8 @@ pub fn func<'a>(_x: impl Clone + Into<Vec<u8>> + 'a) {}

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

pub fn func3(_x: impl Iterator<Item = impl Iterator<Item = u8>> + Clone) {}

pub struct Foo;

impl Foo {
Expand Down
6 changes: 6 additions & 0 deletions src/test/rustdoc/inline_cross/impl_trait.rs
Expand Up @@ -8,11 +8,17 @@ extern crate impl_trait_aux;
pub use impl_trait_aux::func;

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

// @has impl_trait/fn.func3.html
// @has - '//pre[@class="rust fn"]' "func3(_x: impl Clone + Iterator<Item = impl Iterator<Item = u8>>)"
// @!has - '//pre[@class="rust fn"]' 'where'
pub use impl_trait_aux::func3;

// @has impl_trait/struct.Foo.html
// @has - '//code[@id="method.v"]' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a)"
// @!has - '//code[@id="method.v"]' 'where'
Expand Down

0 comments on commit 5f9e263

Please sign in to comment.