提交 b78367d8 编写于 作者: S Shotaro Yamada

Support `impl Trait` in inlined documentation

上级 cdff9189
...@@ -217,8 +217,9 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function { ...@@ -217,8 +217,9 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function {
}; };
let predicates = cx.tcx.predicates_of(did); let predicates = cx.tcx.predicates_of(did);
let generics = (cx.tcx.generics_of(did), &predicates).clean(cx); let (generics, decl) = clean::enter_impl_trait(cx, || {
let decl = (did, sig).clean(cx); ((cx.tcx.generics_of(did), &predicates).clean(cx), (did, sig).clean(cx))
});
let (all_types, ret_types) = clean::get_all_types(&generics, &decl, cx); let (all_types, ret_types) = clean::get_all_types(&generics, &decl, cx);
clean::Function { clean::Function {
decl, decl,
...@@ -372,7 +373,9 @@ pub fn build_impl(cx: &DocContext<'_>, did: DefId, attrs: Option<Attrs<'_>>, ...@@ -372,7 +373,9 @@ pub fn build_impl(cx: &DocContext<'_>, did: DefId, attrs: Option<Attrs<'_>>,
None None
} }
}).collect::<Vec<_>>(), }).collect::<Vec<_>>(),
(tcx.generics_of(did), &predicates).clean(cx), clean::enter_impl_trait(cx, || {
(tcx.generics_of(did), &predicates).clean(cx)
}),
) )
}; };
let polarity = tcx.impl_polarity(did); let polarity = tcx.impl_polarity(did);
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
use std::sync::Arc; use std::sync::Arc;
use std::u32; use std::u32;
use crate::core::{self, DocContext}; use crate::core::{self, DocContext, ImplTraitParam};
use crate::doctree; use crate::doctree;
use crate::html::render::{cache, ExternalLocation}; use crate::html::render::{cache, ExternalLocation};
use crate::html::item_type::ItemType; use crate::html::item_type::ItemType;
...@@ -1540,7 +1540,7 @@ fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef { ...@@ -1540,7 +1540,7 @@ fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
ty::GenericParamDefKind::Lifetime => { ty::GenericParamDefKind::Lifetime => {
(self.name.to_string(), GenericParamDefKind::Lifetime) (self.name.to_string(), GenericParamDefKind::Lifetime)
} }
ty::GenericParamDefKind::Type { has_default, .. } => { ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
cx.renderinfo.borrow_mut().external_param_names cx.renderinfo.borrow_mut().external_param_names
.insert(self.def_id, self.name.clean(cx)); .insert(self.def_id, self.name.clean(cx));
let default = if has_default { let default = if has_default {
...@@ -1552,7 +1552,7 @@ fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef { ...@@ -1552,7 +1552,7 @@ fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
did: self.def_id, did: self.def_id,
bounds: vec![], // These are filled in from the where-clauses. bounds: vec![], // These are filled in from the where-clauses.
default, default,
synthetic: None, synthetic,
}) })
} }
ty::GenericParamDefKind::Const { .. } => { ty::GenericParamDefKind::Const { .. } => {
...@@ -1641,7 +1641,7 @@ fn is_impl_trait(param: &hir::GenericParam) -> bool { ...@@ -1641,7 +1641,7 @@ fn is_impl_trait(param: &hir::GenericParam) -> bool {
match param.kind { match param.kind {
GenericParamDefKind::Lifetime => unreachable!(), GenericParamDefKind::Lifetime => unreachable!(),
GenericParamDefKind::Type { did, ref bounds, .. } => { GenericParamDefKind::Type { did, ref bounds, .. } => {
cx.impl_trait_bounds.borrow_mut().insert(did, bounds.clone()); cx.impl_trait_bounds.borrow_mut().insert(did.into(), bounds.clone());
} }
GenericParamDefKind::Const { .. } => unreachable!(), GenericParamDefKind::Const { .. } => unreachable!(),
} }
...@@ -1696,25 +1696,76 @@ fn clean(&self, cx: &DocContext<'_>) -> Generics { ...@@ -1696,25 +1696,76 @@ fn clean(&self, cx: &DocContext<'_>) -> Generics {
let (gens, preds) = *self; let (gens, preds) = *self;
// Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
// since `Clean for ty::Predicate` would consume them.
let mut impl_trait = FxHashMap::<ImplTraitParam, Vec<_>>::default();
// Bounds in the type_params and lifetimes fields are repeated in the // Bounds in the type_params and lifetimes fields are repeated in the
// predicates field (see rustc_typeck::collect::ty_generics), so remove // predicates field (see rustc_typeck::collect::ty_generics), so remove
// them. // them.
let stripped_typarams = gens.params.iter().filter_map(|param| match param.kind { let stripped_typarams = gens.params.iter()
ty::GenericParamDefKind::Lifetime => None, .filter_map(|param| match param.kind {
ty::GenericParamDefKind::Type { .. } => { ty::GenericParamDefKind::Lifetime => None,
if param.name.as_symbol() == kw::SelfUpper { ty::GenericParamDefKind::Type { synthetic, .. } => {
assert_eq!(param.index, 0); if param.name.as_symbol() == kw::SelfUpper {
return None; assert_eq!(param.index, 0);
return None;
}
if synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
impl_trait.insert(param.index.into(), vec![]);
return None;
}
Some(param.clean(cx))
} }
Some(param.clean(cx)) ty::GenericParamDefKind::Const { .. } => None,
} }).collect::<Vec<GenericParamDef>>();
ty::GenericParamDefKind::Const { .. } => None,
}).collect::<Vec<GenericParamDef>>();
let mut where_predicates = preds.predicates.iter() let mut where_predicates = preds.predicates.iter()
.flat_map(|(p, _)| p.clean(cx)) .flat_map(|(p, _)| {
let param_idx = if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
if let ty::Param(param) = trait_ref.self_ty().sty {
Some(param.index)
} else {
None
}
} else if let Some(outlives) = p.to_opt_type_outlives() {
if let ty::Param(param) = outlives.skip_binder().0.sty {
Some(param.index)
} else {
None
}
} else {
None
};
let p = p.clean(cx)?;
if let Some(b) = param_idx.and_then(|i| impl_trait.get_mut(&i.into())) {
b.extend(
p.get_bounds()
.into_iter()
.flatten()
.cloned()
.filter(|b| !b.is_sized_bound(cx))
);
return None;
}
Some(p)
})
.collect::<Vec<_>>(); .collect::<Vec<_>>();
// Move `TraitPredicate`s to the front.
for (_, bounds) in impl_trait.iter_mut() {
bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b {
false
} else {
true
});
}
cx.impl_trait_bounds.borrow_mut().extend(impl_trait);
// Type parameters and have a Sized bound by default unless removed with // Type parameters and have a Sized bound by default unless removed with
// ?Sized. Scan through the predicates and mark any type parameter with // ?Sized. Scan through the predicates and mark any type parameter with
// a Sized bound, removing the bounds as we find them. // a Sized bound, removing the bounds as we find them.
...@@ -2791,7 +2842,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Type { ...@@ -2791,7 +2842,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Type {
if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() { if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() {
return new_ty; return new_ty;
} }
if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did) { if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did.into()) {
return ImplTrait(bounds); return ImplTrait(bounds);
} }
} }
...@@ -3082,7 +3133,13 @@ fn clean(&self, cx: &DocContext<'_>) -> Type { ...@@ -3082,7 +3133,13 @@ fn clean(&self, cx: &DocContext<'_>) -> Type {
ty::Projection(ref data) => data.clean(cx), ty::Projection(ref data) => data.clean(cx),
ty::Param(ref p) => Generic(p.name.to_string()), ty::Param(ref p) => {
if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&p.index.into()) {
ImplTrait(bounds)
} else {
Generic(p.name.to_string())
}
}
ty::Opaque(def_id, substs) => { ty::Opaque(def_id, substs) => {
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
......
...@@ -61,8 +61,8 @@ pub struct DocContext<'tcx> { ...@@ -61,8 +61,8 @@ pub struct DocContext<'tcx> {
pub lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>, pub lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>,
/// Table `DefId` of const parameter -> substituted const /// Table `DefId` of const parameter -> substituted const
pub ct_substs: RefCell<FxHashMap<DefId, clean::Constant>>, pub ct_substs: RefCell<FxHashMap<DefId, clean::Constant>>,
/// Table DefId of `impl Trait` in argument position -> bounds /// Table synthetic type parameter for `impl Trait` in argument position -> bounds
pub impl_trait_bounds: RefCell<FxHashMap<DefId, Vec<clean::GenericBound>>>, pub impl_trait_bounds: RefCell<FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>>,
pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>, pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
pub all_fake_def_ids: RefCell<FxHashSet<DefId>>, pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
/// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`. /// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
...@@ -459,3 +459,23 @@ fn report_deprecated_attr(name: &str, diag: &errors::Handler) { ...@@ -459,3 +459,23 @@ fn report_deprecated_attr(name: &str, diag: &errors::Handler) {
}) })
}) })
} }
/// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter
/// for `impl Trait` in argument position.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum ImplTraitParam {
DefId(DefId),
ParamIndex(u32),
}
impl From<DefId> for ImplTraitParam {
fn from(did: DefId) -> Self {
ImplTraitParam::DefId(did)
}
}
impl From<u32> for ImplTraitParam {
fn from(idx: u32) -> Self {
ImplTraitParam::ParamIndex(idx)
}
}
pub fn func<'a>(_x: impl Clone + Into<Vec<u8>> + 'a) {}
pub struct Foo;
impl Foo {
pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a) {}
}
// aux-build:impl_trait_aux.rs
extern crate impl_trait_aux;
// @has impl_trait/fn.func.html
// @has - '//pre[@class="rust fn"]' "pub fn func<'a>(_x: impl Clone + Into<Vec<u8>> + 'a)"
// @!has - '//pre[@class="rust fn"]' 'where'
pub use impl_trait_aux::func;
// @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'
pub use impl_trait_aux::Foo;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册