Skip to content

Commit b78367d

Browse files
committed
Support impl Trait in inlined documentation
1 parent cdff918 commit b78367d

File tree

5 files changed

+122
-22
lines changed

5 files changed

+122
-22
lines changed

src/librustdoc/clean/inline.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,9 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function {
217217
};
218218

219219
let predicates = cx.tcx.predicates_of(did);
220-
let generics = (cx.tcx.generics_of(did), &predicates).clean(cx);
221-
let decl = (did, sig).clean(cx);
220+
let (generics, decl) = clean::enter_impl_trait(cx, || {
221+
((cx.tcx.generics_of(did), &predicates).clean(cx), (did, sig).clean(cx))
222+
});
222223
let (all_types, ret_types) = clean::get_all_types(&generics, &decl, cx);
223224
clean::Function {
224225
decl,
@@ -372,7 +373,9 @@ pub fn build_impl(cx: &DocContext<'_>, did: DefId, attrs: Option<Attrs<'_>>,
372373
None
373374
}
374375
}).collect::<Vec<_>>(),
375-
(tcx.generics_of(did), &predicates).clean(cx),
376+
clean::enter_impl_trait(cx, || {
377+
(tcx.generics_of(did), &predicates).clean(cx)
378+
}),
376379
)
377380
};
378381
let polarity = tcx.impl_polarity(did);

src/librustdoc/clean/mod.rs

Lines changed: 74 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use std::cell::RefCell;
4545
use std::sync::Arc;
4646
use std::u32;
4747

48-
use crate::core::{self, DocContext};
48+
use crate::core::{self, DocContext, ImplTraitParam};
4949
use crate::doctree;
5050
use crate::html::render::{cache, ExternalLocation};
5151
use 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
}
@@ -1696,25 +1696,76 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
16961696

16971697
let (gens, preds) = *self;
16981698

1699+
// Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
1700+
// since `Clean for ty::Predicate` would consume them.
1701+
let mut impl_trait = FxHashMap::<ImplTraitParam, Vec<_>>::default();
1702+
16991703
// Bounds in the type_params and lifetimes fields are repeated in the
17001704
// predicates field (see rustc_typeck::collect::ty_generics), so remove
17011705
// 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;
1706+
let stripped_typarams = gens.params.iter()
1707+
.filter_map(|param| match param.kind {
1708+
ty::GenericParamDefKind::Lifetime => None,
1709+
ty::GenericParamDefKind::Type { synthetic, .. } => {
1710+
if param.name.as_symbol() == kw::SelfUpper {
1711+
assert_eq!(param.index, 0);
1712+
return None;
1713+
}
1714+
if synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
1715+
impl_trait.insert(param.index.into(), vec![]);
1716+
return None;
1717+
}
1718+
Some(param.clean(cx))
17081719
}
1709-
Some(param.clean(cx))
1710-
}
1711-
ty::GenericParamDefKind::Const { .. } => None,
1712-
}).collect::<Vec<GenericParamDef>>();
1720+
ty::GenericParamDefKind::Const { .. } => None,
1721+
}).collect::<Vec<GenericParamDef>>();
17131722

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

1758+
// Move `TraitPredicate`s to the front.
1759+
for (_, bounds) in impl_trait.iter_mut() {
1760+
bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b {
1761+
false
1762+
} else {
1763+
true
1764+
});
1765+
}
1766+
1767+
cx.impl_trait_bounds.borrow_mut().extend(impl_trait);
1768+
17181769
// Type parameters and have a Sized bound by default unless removed with
17191770
// ?Sized. Scan through the predicates and mark any type parameter with
17201771
// a Sized bound, removing the bounds as we find them.
@@ -2791,7 +2842,7 @@ impl Clean<Type> for hir::Ty {
27912842
if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() {
27922843
return new_ty;
27932844
}
2794-
if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did) {
2845+
if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did.into()) {
27952846
return ImplTrait(bounds);
27962847
}
27972848
}
@@ -3082,7 +3133,13 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
30823133

30833134
ty::Projection(ref data) => data.clean(cx),
30843135

3085-
ty::Param(ref p) => Generic(p.name.to_string()),
3136+
ty::Param(ref p) => {
3137+
if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&p.index.into()) {
3138+
ImplTrait(bounds)
3139+
} else {
3140+
Generic(p.name.to_string())
3141+
}
3142+
}
30863143

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

src/librustdoc/core.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ pub struct DocContext<'tcx> {
6161
pub lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>,
6262
/// Table `DefId` of const parameter -> substituted const
6363
pub ct_substs: RefCell<FxHashMap<DefId, clean::Constant>>,
64-
/// Table DefId of `impl Trait` in argument position -> bounds
65-
pub impl_trait_bounds: RefCell<FxHashMap<DefId, Vec<clean::GenericBound>>>,
64+
/// Table synthetic type parameter for `impl Trait` in argument position -> bounds
65+
pub impl_trait_bounds: RefCell<FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>>,
6666
pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
6767
pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
6868
/// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
@@ -459,3 +459,23 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
459459
})
460460
})
461461
}
462+
463+
/// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter
464+
/// for `impl Trait` in argument position.
465+
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
466+
pub enum ImplTraitParam {
467+
DefId(DefId),
468+
ParamIndex(u32),
469+
}
470+
471+
impl From<DefId> for ImplTraitParam {
472+
fn from(did: DefId) -> Self {
473+
ImplTraitParam::DefId(did)
474+
}
475+
}
476+
477+
impl From<u32> for ImplTraitParam {
478+
fn from(idx: u32) -> Self {
479+
ImplTraitParam::ParamIndex(idx)
480+
}
481+
}
Lines changed: 7 additions & 0 deletions
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+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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"]' "pub fn func<'a>(_x: impl Clone + Into<Vec<u8>> + 'a)"
7+
// @!has - '//pre[@class="rust fn"]' 'where'
8+
pub use impl_trait_aux::func;
9+
10+
// @has impl_trait/struct.Foo.html
11+
// @has - '//code[@id="method.v"]' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a)"
12+
// @!has - '//code[@id="method.v"]' 'where'
13+
pub use impl_trait_aux::Foo;

0 commit comments

Comments
 (0)