Skip to content

Commit ecda335

Browse files
committed
Support impl Trait in inlined documentation
1 parent 9d5b6ef commit ecda335

File tree

5 files changed

+128
-22
lines changed

5 files changed

+128
-22
lines changed

src/librustdoc/clean/inline.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,9 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function {
210210
};
211211

212212
let predicates = cx.tcx.predicates_of(did);
213-
let generics = (cx.tcx.generics_of(did), &predicates).clean(cx);
214-
let decl = (did, sig).clean(cx);
213+
let (generics, decl) = clean::enter_impl_trait(cx, || {
214+
((cx.tcx.generics_of(did), &predicates).clean(cx), (did, sig).clean(cx))
215+
});
215216
let (all_types, ret_types) = clean::get_all_types(&generics, &decl, cx);
216217
clean::Function {
217218
decl,
@@ -347,7 +348,9 @@ pub fn build_impl(cx: &DocContext<'_>, did: DefId, ret: &mut Vec<clean::Item>) {
347348
None
348349
}
349350
}).collect::<Vec<_>>(),
350-
(tcx.generics_of(did), &predicates).clean(cx),
351+
clean::enter_impl_trait(cx, || {
352+
(tcx.generics_of(did), &predicates).clean(cx)
353+
}),
351354
)
352355
};
353356
let polarity = tcx.impl_polarity(did);

src/librustdoc/clean/mod.rs

+74-17
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ use std::u32;
4747

4848
use parking_lot::ReentrantMutex;
4949

50-
use crate::core::{self, DocContext};
50+
use crate::core::{self, DocContext, ImplTraitParam};
5151
use crate::doctree;
5252
use crate::visit_ast;
5353
use 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,76 @@ 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<_>>::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().enumerate()
1703+
.filter_map(|(i, 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((i as u32).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>>();
17091718

17101719
let mut where_predicates = preds.predicates.iter()
1711-
.flat_map(|(p, _)| p.clean(cx))
1720+
.flat_map(|(p, _)| {
1721+
let param_idx = if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
1722+
if let ty::Param(param) = trait_ref.self_ty().sty {
1723+
Some(param.index)
1724+
} else {
1725+
None
1726+
}
1727+
} else if let Some(outlives) = p.to_opt_type_outlives() {
1728+
if let ty::Param(param) = outlives.skip_binder().0.sty {
1729+
Some(param.index)
1730+
} else {
1731+
None
1732+
}
1733+
} else {
1734+
None
1735+
};
1736+
1737+
let p = p.clean(cx)?;
1738+
1739+
if let Some(b) = param_idx.and_then(|i| impl_trait.get_mut(&i.into())) {
1740+
b.extend(
1741+
p.get_bounds()
1742+
.into_iter()
1743+
.flatten()
1744+
.cloned()
1745+
.filter(|b| !b.is_sized_bound(cx))
1746+
);
1747+
return None;
1748+
}
1749+
1750+
Some(p)
1751+
})
17121752
.collect::<Vec<_>>();
17131753

1754+
// Move `TraitPredicate`s to the front.
1755+
for (_, bounds) in impl_trait.iter_mut() {
1756+
bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b {
1757+
false
1758+
} else {
1759+
true
1760+
});
1761+
}
1762+
1763+
cx.impl_trait_bounds.borrow_mut().extend(impl_trait);
1764+
17141765
// Type parameters and have a Sized bound by default unless removed with
17151766
// ?Sized. Scan through the predicates and mark any type parameter with
17161767
// a Sized bound, removing the bounds as we find them.
@@ -2789,7 +2840,7 @@ impl Clean<Type> for hir::Ty {
27892840
if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() {
27902841
return new_ty;
27912842
}
2792-
if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did) {
2843+
if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did.into()) {
27932844
return ImplTrait(bounds);
27942845
}
27952846
}
@@ -3079,7 +3130,13 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
30793130

30803131
ty::Projection(ref data) => data.clean(cx),
30813132

3082-
ty::Param(ref p) => Generic(p.name.to_string()),
3133+
ty::Param(ref p) => {
3134+
if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&p.index.into()) {
3135+
ImplTrait(bounds)
3136+
} else {
3137+
Generic(p.name.to_string())
3138+
}
3139+
}
30833140

30843141
ty::Opaque(def_id, substs) => {
30853142
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,

src/librustdoc/core.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ pub struct DocContext<'tcx> {
6565
pub lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>,
6666
/// Table `DefId` of const parameter -> substituted const
6767
pub ct_substs: RefCell<FxHashMap<DefId, clean::Constant>>,
68-
/// Table DefId of `impl Trait` in argument position -> bounds
69-
pub impl_trait_bounds: RefCell<FxHashMap<DefId, Vec<clean::GenericBound>>>,
68+
/// Table synthetic type parameter for `impl Trait` in argument position -> bounds
69+
pub impl_trait_bounds: RefCell<FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>>,
7070
pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
7171
pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
7272
/// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
@@ -472,3 +472,23 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
472472
})
473473
})
474474
}
475+
476+
/// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter
477+
/// for `impl Trait` in argument position.
478+
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
479+
pub enum ImplTraitParam {
480+
DefId(DefId),
481+
ParamIndex(u32),
482+
}
483+
484+
impl From<DefId> for ImplTraitParam {
485+
fn from(did: DefId) -> Self {
486+
ImplTraitParam::DefId(did)
487+
}
488+
}
489+
490+
impl From<u32> for ImplTraitParam {
491+
fn from(idx: u32) -> Self {
492+
ImplTraitParam::ParamIndex(idx)
493+
}
494+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pub fn func<'a>(_x: impl Clone + Into<Vec<u8>> + 'a) {}
2+
3+
pub struct Foo;
4+
5+
impl Foo {
6+
pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a) {}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// aux-build:impl_trait_aux.rs
2+
3+
extern crate impl_trait_aux;
4+
5+
// @has impl_trait/fn.func.html
6+
// @has - '//pre[@class="rust fn"]' '(_x: impl '
7+
// @has - '//pre[@class="rust fn"]' 'Clone'
8+
// @has - '//pre[@class="rust fn"]' 'Into'
9+
// @has - '//pre[@class="rust fn"]' "'a"
10+
// @!has - '//pre[@class="rust fn"]' 'where'
11+
pub use impl_trait_aux::func;
12+
13+
// @has impl_trait/struct.Foo.html
14+
// @has - '//code[@id="method.v"]' '(_x: impl '
15+
// @has - '//code[@id="method.v"]' 'Clone'
16+
// @has - '//code[@id="method.v"]' 'Into'
17+
// @has - '//code[@id="method.v"]' "'a"
18+
// @!has - '//code[@id="method.v"]' 'where'
19+
pub use impl_trait_aux::Foo;

0 commit comments

Comments
 (0)