summaryrefslogtreecommitdiffstats
path: root/src/librustdoc/clean
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:06:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:06:31 +0000
commit2ff14448863ac1a1dd9533461708e29aae170c2d (patch)
tree85b9fea2bbfe3f06473cfa381eed11f273b57c5c /src/librustdoc/clean
parentAdding debian version 1.64.0+dfsg1-1. (diff)
downloadrustc-2ff14448863ac1a1dd9533461708e29aae170c2d.tar.xz
rustc-2ff14448863ac1a1dd9533461708e29aae170c2d.zip
Adding debian version 1.65.0+dfsg1-2.debian/1.65.0+dfsg1-2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/librustdoc/clean')
-rw-r--r--src/librustdoc/clean/auto_trait.rs20
-rw-r--r--src/librustdoc/clean/blanket_impl.rs4
-rw-r--r--src/librustdoc/clean/inline.rs55
-rw-r--r--src/librustdoc/clean/mod.rs1248
-rw-r--r--src/librustdoc/clean/types.rs142
-rw-r--r--src/librustdoc/clean/utils.rs83
6 files changed, 807 insertions, 745 deletions
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index af33c1a6a..175472797 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -123,7 +123,7 @@ where
kind: Box::new(ImplItem(Box::new(Impl {
unsafety: hir::Unsafety::Normal,
generics: new_generics,
- trait_: Some(clean_trait_ref_with_bindings(self.cx, trait_ref, &[])),
+ trait_: Some(clean_trait_ref_with_bindings(self.cx, trait_ref, ThinVec::new())),
for_: clean_middle_ty(ty, self.cx, None),
items: Vec::new(),
polarity,
@@ -476,7 +476,7 @@ where
let mut ty_to_fn: FxHashMap<Type, (PolyTrait, Option<Type>)> = Default::default();
for p in clean_where_predicates {
- let (orig_p, p) = (p, p.clean(self.cx));
+ let (orig_p, p) = (p, clean_predicate(p, self.cx));
if p.is_none() {
continue;
}
@@ -525,8 +525,8 @@ where
GenericBound::TraitBound(ref mut p, _) => {
// Insert regions into the for_generics hash map first, to ensure
// that we don't end up with duplicate bounds (e.g., for<'b, 'b>)
- for_generics.extend(p.generic_params.clone());
- p.generic_params = for_generics.into_iter().collect();
+ for_generics.extend(p.generic_params.drain(..));
+ p.generic_params.extend(for_generics);
self.is_fn_trait(&p.trait_)
}
_ => false,
@@ -551,13 +551,15 @@ where
}
WherePredicate::EqPredicate { lhs, rhs } => {
match lhs {
- Type::QPath { ref assoc, ref self_type, ref trait_, .. } => {
+ Type::QPath(box QPathData {
+ ref assoc, ref self_type, ref trait_, ..
+ }) => {
let ty = &*self_type;
let mut new_trait = trait_.clone();
if self.is_fn_trait(trait_) && assoc.name == sym::Output {
ty_to_fn
- .entry(*ty.clone())
+ .entry(ty.clone())
.and_modify(|e| {
*e = (e.0.clone(), Some(rhs.ty().unwrap().clone()))
})
@@ -582,7 +584,7 @@ where
// to 'T: Iterator<Item=u8>'
GenericArgs::AngleBracketed { ref mut bindings, .. } => {
bindings.push(TypeBinding {
- assoc: *assoc.clone(),
+ assoc: assoc.clone(),
kind: TypeBindingKind::Equality { term: rhs },
});
}
@@ -596,7 +598,7 @@ where
}
}
- let bounds = ty_to_bounds.entry(*ty.clone()).or_default();
+ let bounds = ty_to_bounds.entry(ty.clone()).or_default();
bounds.insert(GenericBound::TraitBound(
PolyTrait { trait_: new_trait, generic_params: Vec::new() },
@@ -613,7 +615,7 @@ where
));
// Avoid creating any new duplicate bounds later in the outer
// loop
- ty_to_traits.entry(*ty.clone()).or_default().insert(trait_.clone());
+ ty_to_traits.entry(ty.clone()).or_default().insert(trait_.clone());
}
_ => panic!("Unexpected LHS {:?} for {:?}", lhs, item_def_id),
}
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 01dd95e6e..cc734389e 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -115,12 +115,12 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
),
// FIXME(eddyb) compute both `trait_` and `for_` from
// the post-inference `trait_ref`, as it's more accurate.
- trait_: Some(clean_trait_ref_with_bindings(cx, trait_ref.0, &[])),
+ trait_: Some(clean_trait_ref_with_bindings(cx, trait_ref.0, ThinVec::new())),
for_: clean_middle_ty(ty.0, cx, None),
items: cx.tcx
.associated_items(impl_def_id)
.in_definition_order()
- .map(|x| x.clean(cx))
+ .map(|x| clean_middle_assoc_item(x, cx))
.collect::<Vec<_>>(),
polarity: ty::ImplPolarity::Positive,
kind: ImplKind::Blanket(Box::new(clean_middle_ty(trait_ref.0.self_ty(), cx, None))),
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 58d0aedb0..df0e9f7cc 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -3,9 +3,10 @@
use std::iter::once;
use std::sync::Arc;
+use thin_vec::ThinVec;
+
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::thin_vec::ThinVec;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
@@ -16,15 +17,14 @@ use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};
use crate::clean::{
- self, clean_fn_decl_from_did_and_sig, clean_middle_field, clean_middle_ty,
- clean_trait_ref_with_bindings, clean_ty, clean_ty_generics, clean_variant_def,
- clean_visibility, utils, Attributes, AttributesExt, Clean, ImplKind, ItemId, Type, Visibility,
+ self, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, clean_middle_assoc_item,
+ clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings, clean_ty,
+ clean_ty_generics, clean_variant_def, clean_visibility, utils, Attributes, AttributesExt,
+ ImplKind, ItemId, Type, Visibility,
};
use crate::core::DocContext;
use crate::formats::item_type::ItemType;
-type Attrs<'hir> = &'hir [ast::Attribute];
-
/// Attempt to inline a definition into this AST.
///
/// This function will fetch the definition specified, and if it is
@@ -45,7 +45,7 @@ pub(crate) fn try_inline(
import_def_id: Option<DefId>,
res: Res,
name: Symbol,
- attrs: Option<Attrs<'_>>,
+ attrs: Option<&[ast::Attribute]>,
visited: &mut FxHashSet<DefId>,
) -> Option<Vec<clean::Item>> {
let did = res.opt_def_id()?;
@@ -61,7 +61,7 @@ pub(crate) fn try_inline(
Res::Def(DefKind::Trait, did) => {
record_extern_fqn(cx, did, ItemType::Trait);
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
- clean::TraitItem(build_external_trait(cx, did))
+ clean::TraitItem(Box::new(build_external_trait(cx, did)))
}
Res::Def(DefKind::Fn, did) => {
record_extern_fqn(cx, did, ItemType::Function);
@@ -171,7 +171,7 @@ pub(crate) fn try_inline_glob(
}
}
-pub(crate) fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> Attrs<'hir> {
+pub(crate) fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> &'hir [ast::Attribute] {
cx.tcx.get_attrs_unchecked(did)
}
@@ -217,7 +217,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
// which causes methods to have a `pub` prefix, which is invalid since items in traits
// can not have a visibility prefix. Thus we override the visibility here manually.
// See https://github.com/rust-lang/rust/issues/81274
- clean::Item { visibility: Visibility::Inherited, ..item.clean(cx) }
+ clean::Item { visibility: Visibility::Inherited, ..clean_middle_assoc_item(item, cx) }
})
.collect();
@@ -286,7 +286,7 @@ pub(crate) fn build_impls(
cx: &mut DocContext<'_>,
parent_module: Option<DefId>,
did: DefId,
- attrs: Option<Attrs<'_>>,
+ attrs: Option<&[ast::Attribute]>,
ret: &mut Vec<clean::Item>,
) {
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_inherent_impls");
@@ -296,14 +296,29 @@ pub(crate) fn build_impls(
for &did in tcx.inherent_impls(did).iter() {
build_impl(cx, parent_module, did, attrs, ret);
}
+
+ // This pretty much exists expressly for `dyn Error` traits that exist in the `alloc` crate.
+ // See also:
+ //
+ // * https://github.com/rust-lang/rust/issues/103170 — where it didn't used to get documented
+ // * https://github.com/rust-lang/rust/pull/99917 — where the feature got used
+ // * https://github.com/rust-lang/rust/issues/53487 — overall tracking issue for Error
+ if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) {
+ use rustc_middle::ty::fast_reject::SimplifiedTypeGen::*;
+ let type_ =
+ if tcx.is_trait(did) { TraitSimplifiedType(did) } else { AdtSimplifiedType(did) };
+ for &did in tcx.incoherent_impls(type_) {
+ build_impl(cx, parent_module, did, attrs, ret);
+ }
+ }
}
/// `parent_module` refers to the parent of the re-export, not the original item
-fn merge_attrs(
+pub(crate) fn merge_attrs(
cx: &mut DocContext<'_>,
parent_module: Option<DefId>,
- old_attrs: Attrs<'_>,
- new_attrs: Option<Attrs<'_>>,
+ old_attrs: &[ast::Attribute],
+ new_attrs: Option<&[ast::Attribute]>,
) -> (clean::Attributes, Option<Arc<clean::cfg::Cfg>>) {
// NOTE: If we have additional attributes (from a re-export),
// always insert them first. This ensure that re-export
@@ -330,7 +345,7 @@ pub(crate) fn build_impl(
cx: &mut DocContext<'_>,
parent_module: Option<DefId>,
did: DefId,
- attrs: Option<Attrs<'_>>,
+ attrs: Option<&[ast::Attribute]>,
ret: &mut Vec<clean::Item>,
) {
if !cx.inlined.insert(did.into()) {
@@ -426,9 +441,9 @@ pub(crate) fn build_impl(
true
}
})
- .map(|item| item.clean(cx))
+ .map(|item| clean_impl_item(item, cx))
.collect::<Vec<_>>(),
- impl_.generics.clean(cx),
+ clean_generics(impl_.generics, cx),
),
None => (
tcx.associated_items(did)
@@ -452,7 +467,7 @@ pub(crate) fn build_impl(
item.visibility(tcx).is_public()
}
})
- .map(|item| item.clean(cx))
+ .map(|item| clean_middle_assoc_item(item, cx))
.collect::<Vec<_>>(),
clean::enter_impl_trait(cx, |cx| {
clean_ty_generics(cx, tcx.generics_of(did), predicates)
@@ -460,7 +475,7 @@ pub(crate) fn build_impl(
),
};
let polarity = tcx.impl_polarity(did);
- let trait_ = associated_trait.map(|t| clean_trait_ref_with_bindings(cx, t, &[]));
+ let trait_ = associated_trait.map(|t| clean_trait_ref_with_bindings(cx, t, ThinVec::new()));
if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
super::build_deref_target_impls(cx, &trait_items, ret);
}
@@ -671,7 +686,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
g.where_predicates.retain(|pred| match pred {
clean::WherePredicate::BoundPredicate {
- ty: clean::QPath { self_type: box clean::Generic(ref s), trait_, .. },
+ ty: clean::QPath(box clean::QPathData { self_type: clean::Generic(ref s), trait_, .. }),
bounds,
..
} => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did),
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 929f5f89b..c8875c272 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -33,7 +33,8 @@ use std::collections::hash_map::Entry;
use std::collections::BTreeMap;
use std::default::Default;
use std::hash::Hash;
-use std::{mem, vec};
+use std::mem;
+use thin_vec::ThinVec;
use crate::core::{self, DocContext, ImplTraitParam};
use crate::formats::item_type::ItemType;
@@ -44,128 +45,126 @@ use utils::*;
pub(crate) use self::types::*;
pub(crate) use self::utils::{get_auto_trait_and_blanket_impls, krate, register_res};
-pub(crate) trait Clean<'tcx, T> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> T;
-}
+pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
+ let mut items: Vec<Item> = vec![];
+ let mut inserted = FxHashSet::default();
+ items.extend(doc.foreigns.iter().map(|(item, renamed)| {
+ let item = clean_maybe_renamed_foreign_item(cx, item, *renamed);
+ if let Some(name) = item.name && !item.attrs.lists(sym::doc).has_word(sym::hidden) {
+ inserted.insert((item.type_(), name));
+ }
+ item
+ }));
+ items.extend(doc.mods.iter().filter_map(|x| {
+ if !inserted.insert((ItemType::Module, x.name)) {
+ return None;
+ }
+ let item = clean_doc_module(x, cx);
+ if item.attrs.lists(sym::doc).has_word(sym::hidden) {
+ // Hidden modules are stripped at a later stage.
+ // If a hidden module has the same name as a visible one, we want
+ // to keep both of them around.
+ inserted.remove(&(ItemType::Module, x.name));
+ }
+ Some(item)
+ }));
-impl<'tcx> Clean<'tcx, Item> for DocModule<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
- let mut items: Vec<Item> = vec![];
- let mut inserted = FxHashSet::default();
- items.extend(self.foreigns.iter().map(|(item, renamed)| {
- let item = clean_maybe_renamed_foreign_item(cx, item, *renamed);
- if let Some(name) = item.name {
+ // Split up imports from all other items.
+ //
+ // This covers the case where somebody does an import which should pull in an item,
+ // but there's already an item with the same namespace and same name. Rust gives
+ // priority to the not-imported one, so we should, too.
+ items.extend(doc.items.iter().flat_map(|(item, renamed)| {
+ // First, lower everything other than imports.
+ if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
+ return Vec::new();
+ }
+ let v = clean_maybe_renamed_item(cx, item, *renamed);
+ for item in &v {
+ if let Some(name) = item.name && !item.attrs.lists(sym::doc).has_word(sym::hidden) {
inserted.insert((item.type_(), name));
}
- item
- }));
- items.extend(self.mods.iter().map(|x| {
- inserted.insert((ItemType::Module, x.name));
- x.clean(cx)
- }));
-
- // Split up imports from all other items.
- //
- // This covers the case where somebody does an import which should pull in an item,
- // but there's already an item with the same namespace and same name. Rust gives
- // priority to the not-imported one, so we should, too.
- items.extend(self.items.iter().flat_map(|(item, renamed)| {
- // First, lower everything other than imports.
- if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
- return Vec::new();
- }
- let v = clean_maybe_renamed_item(cx, item, *renamed);
- for item in &v {
- if let Some(name) = item.name {
- inserted.insert((item.type_(), name));
- }
- }
- v
- }));
- items.extend(self.items.iter().flat_map(|(item, renamed)| {
- // Now we actually lower the imports, skipping everything else.
- if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
- let name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
- clean_use_statement(item, name, path, hir::UseKind::Glob, cx, &mut inserted)
- } else {
- // skip everything else
- Vec::new()
- }
- }));
-
- // determine if we should display the inner contents or
- // the outer `mod` item for the source code.
-
- let span = Span::new({
- let where_outer = self.where_outer(cx.tcx);
- let sm = cx.sess().source_map();
- let outer = sm.lookup_char_pos(where_outer.lo());
- let inner = sm.lookup_char_pos(self.where_inner.lo());
- if outer.file.start_pos == inner.file.start_pos {
- // mod foo { ... }
- where_outer
- } else {
- // mod foo; (and a separate SourceFile for the contents)
- self.where_inner
- }
- });
+ }
+ v
+ }));
+ items.extend(doc.items.iter().flat_map(|(item, renamed)| {
+ // Now we actually lower the imports, skipping everything else.
+ if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
+ let name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
+ clean_use_statement(item, name, path, hir::UseKind::Glob, cx, &mut inserted)
+ } else {
+ // skip everything else
+ Vec::new()
+ }
+ }));
+
+ // determine if we should display the inner contents or
+ // the outer `mod` item for the source code.
+
+ let span = Span::new({
+ let where_outer = doc.where_outer(cx.tcx);
+ let sm = cx.sess().source_map();
+ let outer = sm.lookup_char_pos(where_outer.lo());
+ let inner = sm.lookup_char_pos(doc.where_inner.lo());
+ if outer.file.start_pos == inner.file.start_pos {
+ // mod foo { ... }
+ where_outer
+ } else {
+ // mod foo; (and a separate SourceFile for the contents)
+ doc.where_inner
+ }
+ });
- Item::from_hir_id_and_parts(
- self.id,
- Some(self.name),
- ModuleItem(Module { items, span }),
- cx,
- )
- }
+ Item::from_hir_id_and_parts(doc.id, Some(doc.name), ModuleItem(Module { items, span }), cx)
}
-impl<'tcx> Clean<'tcx, Option<GenericBound>> for hir::GenericBound<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<GenericBound> {
- Some(match *self {
- hir::GenericBound::Outlives(lt) => GenericBound::Outlives(clean_lifetime(lt, cx)),
- hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
- let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
-
- let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder();
-
- let generic_args = generic_args.clean(cx);
- let GenericArgs::AngleBracketed { bindings, .. } = generic_args
- else {
- bug!("clean: parenthesized `GenericBound::LangItemTrait`");
- };
+fn clean_generic_bound<'tcx>(
+ bound: &hir::GenericBound<'tcx>,
+ cx: &mut DocContext<'tcx>,
+) -> Option<GenericBound> {
+ Some(match *bound {
+ hir::GenericBound::Outlives(lt) => GenericBound::Outlives(clean_lifetime(lt, cx)),
+ hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
+ let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
+
+ let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder();
+
+ let generic_args = clean_generic_args(generic_args, cx);
+ let GenericArgs::AngleBracketed { bindings, .. } = generic_args
+ else {
+ bug!("clean: parenthesized `GenericBound::LangItemTrait`");
+ };
- let trait_ = clean_trait_ref_with_bindings(cx, trait_ref, &bindings);
- GenericBound::TraitBound(
- PolyTrait { trait_, generic_params: vec![] },
- hir::TraitBoundModifier::None,
- )
+ let trait_ = clean_trait_ref_with_bindings(cx, trait_ref, bindings);
+ GenericBound::TraitBound(
+ PolyTrait { trait_, generic_params: vec![] },
+ hir::TraitBoundModifier::None,
+ )
+ }
+ hir::GenericBound::Trait(ref t, modifier) => {
+ // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op.
+ if modifier == hir::TraitBoundModifier::MaybeConst
+ && cx.tcx.lang_items().destruct_trait() == Some(t.trait_ref.trait_def_id().unwrap())
+ {
+ return None;
}
- hir::GenericBound::Trait(ref t, modifier) => {
- // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op.
- if modifier == hir::TraitBoundModifier::MaybeConst
- && cx.tcx.lang_items().destruct_trait()
- == Some(t.trait_ref.trait_def_id().unwrap())
- {
- return None;
- }
- GenericBound::TraitBound(t.clean(cx), modifier)
- }
- })
- }
+ GenericBound::TraitBound(clean_poly_trait_ref(t, cx), modifier)
+ }
+ })
}
pub(crate) fn clean_trait_ref_with_bindings<'tcx>(
cx: &mut DocContext<'tcx>,
trait_ref: ty::TraitRef<'tcx>,
- bindings: &[TypeBinding],
+ bindings: ThinVec<TypeBinding>,
) -> Path {
let kind = cx.tcx.def_kind(trait_ref.def_id).into();
if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
span_bug!(cx.tcx.def_span(trait_ref.def_id), "`TraitRef` had unexpected kind {:?}", kind);
}
inline::record_extern_fqn(cx, trait_ref.def_id, kind);
- let path = external_path(cx, trait_ref.def_id, true, bindings.to_vec(), trait_ref.substs);
+ let path = external_path(cx, trait_ref.def_id, true, bindings, trait_ref.substs);
debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs);
@@ -175,7 +174,7 @@ pub(crate) fn clean_trait_ref_with_bindings<'tcx>(
fn clean_poly_trait_ref_with_bindings<'tcx>(
cx: &mut DocContext<'tcx>,
poly_trait_ref: ty::PolyTraitRef<'tcx>,
- bindings: &[TypeBinding],
+ bindings: ThinVec<TypeBinding>,
) -> GenericBound {
let poly_trait_ref = poly_trait_ref.lift_to_tcx(cx.tcx).unwrap();
@@ -200,16 +199,10 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
)
}
-impl<'tcx> Clean<'tcx, GenericBound> for ty::PolyTraitRef<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericBound {
- clean_poly_trait_ref_with_bindings(cx, *self, &[])
- }
-}
-
-fn clean_lifetime<'tcx>(lifetime: hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
+fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
let def = cx.tcx.named_region(lifetime.hir_id);
if let Some(
- rl::Region::EarlyBound(_, node_id)
+ rl::Region::EarlyBound(node_id)
| rl::Region::LateBound(_, _, node_id)
| rl::Region::Free(_, node_id),
) = def
@@ -257,7 +250,6 @@ pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Life
| ty::ReFree(..)
| ty::ReVar(..)
| ty::RePlaceholder(..)
- | ty::ReEmpty(_)
| ty::ReErased => {
debug!("cannot clean region {:?}", region);
None
@@ -265,66 +257,68 @@ pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Life
}
}
-impl<'tcx> Clean<'tcx, Option<WherePredicate>> for hir::WherePredicate<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<WherePredicate> {
- if !self.in_where_clause() {
- return None;
- }
- Some(match *self {
- hir::WherePredicate::BoundPredicate(ref wbp) => {
- let bound_params = wbp
- .bound_generic_params
- .iter()
- .map(|param| {
- // Higher-ranked params must be lifetimes.
- // Higher-ranked lifetimes can't have bounds.
- assert_matches!(
- param,
- hir::GenericParam { kind: hir::GenericParamKind::Lifetime { .. }, .. }
- );
- Lifetime(param.name.ident().name)
- })
- .collect();
- WherePredicate::BoundPredicate {
- ty: clean_ty(wbp.bounded_ty, cx),
- bounds: wbp.bounds.iter().filter_map(|x| x.clean(cx)).collect(),
- bound_params,
- }
+fn clean_where_predicate<'tcx>(
+ predicate: &hir::WherePredicate<'tcx>,
+ cx: &mut DocContext<'tcx>,
+) -> Option<WherePredicate> {
+ if !predicate.in_where_clause() {
+ return None;
+ }
+ Some(match *predicate {
+ hir::WherePredicate::BoundPredicate(ref wbp) => {
+ let bound_params = wbp
+ .bound_generic_params
+ .iter()
+ .map(|param| {
+ // Higher-ranked params must be lifetimes.
+ // Higher-ranked lifetimes can't have bounds.
+ assert_matches!(
+ param,
+ hir::GenericParam { kind: hir::GenericParamKind::Lifetime { .. }, .. }
+ );
+ Lifetime(param.name.ident().name)
+ })
+ .collect();
+ WherePredicate::BoundPredicate {
+ ty: clean_ty(wbp.bounded_ty, cx),
+ bounds: wbp.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
+ bound_params,
}
+ }
- hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
- lifetime: clean_lifetime(wrp.lifetime, cx),
- bounds: wrp.bounds.iter().filter_map(|x| x.clean(cx)).collect(),
- },
+ hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
+ lifetime: clean_lifetime(wrp.lifetime, cx),
+ bounds: wrp.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
+ },
- hir::WherePredicate::EqPredicate(ref wrp) => WherePredicate::EqPredicate {
- lhs: clean_ty(wrp.lhs_ty, cx),
- rhs: clean_ty(wrp.rhs_ty, cx).into(),
- },
- })
- }
+ hir::WherePredicate::EqPredicate(ref wrp) => WherePredicate::EqPredicate {
+ lhs: clean_ty(wrp.lhs_ty, cx),
+ rhs: clean_ty(wrp.rhs_ty, cx).into(),
+ },
+ })
}
-impl<'tcx> Clean<'tcx, Option<WherePredicate>> for ty::Predicate<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<WherePredicate> {
- let bound_predicate = self.kind();
- match bound_predicate.skip_binder() {
- ty::PredicateKind::Trait(pred) => {
- clean_poly_trait_predicate(bound_predicate.rebind(pred), cx)
- }
- ty::PredicateKind::RegionOutlives(pred) => clean_region_outlives_predicate(pred),
- ty::PredicateKind::TypeOutlives(pred) => clean_type_outlives_predicate(pred, cx),
- ty::PredicateKind::Projection(pred) => Some(clean_projection_predicate(pred, cx)),
- ty::PredicateKind::ConstEvaluatable(..) => None,
- ty::PredicateKind::WellFormed(..) => None,
-
- ty::PredicateKind::Subtype(..)
- | ty::PredicateKind::Coerce(..)
- | ty::PredicateKind::ObjectSafe(..)
- | ty::PredicateKind::ClosureKind(..)
- | ty::PredicateKind::ConstEquate(..)
- | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"),
+pub(crate) fn clean_predicate<'tcx>(
+ predicate: ty::Predicate<'tcx>,
+ cx: &mut DocContext<'tcx>,
+) -> Option<WherePredicate> {
+ let bound_predicate = predicate.kind();
+ match bound_predicate.skip_binder() {
+ ty::PredicateKind::Trait(pred) => {
+ clean_poly_trait_predicate(bound_predicate.rebind(pred), cx)
}
+ ty::PredicateKind::RegionOutlives(pred) => clean_region_outlives_predicate(pred),
+ ty::PredicateKind::TypeOutlives(pred) => clean_type_outlives_predicate(pred, cx),
+ ty::PredicateKind::Projection(pred) => Some(clean_projection_predicate(pred, cx)),
+ ty::PredicateKind::ConstEvaluatable(..) => None,
+ ty::PredicateKind::WellFormed(..) => None,
+
+ ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::Coerce(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"),
}
}
@@ -342,7 +336,7 @@ fn clean_poly_trait_predicate<'tcx>(
let poly_trait_ref = pred.map_bound(|pred| pred.trait_ref);
Some(WherePredicate::BoundPredicate {
ty: clean_middle_ty(poly_trait_ref.skip_binder().self_ty(), cx, None),
- bounds: vec![poly_trait_ref.clean(cx)],
+ bounds: vec![clean_poly_trait_ref_with_bindings(cx, poly_trait_ref, ThinVec::new())],
bound_params: Vec::new(),
})
}
@@ -352,10 +346,6 @@ fn clean_region_outlives_predicate<'tcx>(
) -> Option<WherePredicate> {
let ty::OutlivesPredicate(a, b) = pred;
- if a.is_empty() && b.is_empty() {
- return None;
- }
-
Some(WherePredicate::RegionPredicate {
lifetime: clean_middle_region(a).expect("failed to clean lifetime"),
bounds: vec![GenericBound::Outlives(
@@ -370,10 +360,6 @@ fn clean_type_outlives_predicate<'tcx>(
) -> Option<WherePredicate> {
let ty::OutlivesPredicate(ty, lt) = pred;
- if lt.is_empty() {
- return None;
- }
-
Some(WherePredicate::BoundPredicate {
ty: clean_middle_ty(ty, cx, None),
bounds: vec![GenericBound::Outlives(
@@ -384,9 +370,9 @@ fn clean_type_outlives_predicate<'tcx>(
}
fn clean_middle_term<'tcx>(term: ty::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
- match term {
- ty::Term::Ty(ty) => Term::Type(clean_middle_ty(ty, cx, None)),
- ty::Term::Const(c) => Term::Constant(clean_middle_const(c, cx)),
+ match term.unpack() {
+ ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(ty, cx, None)),
+ ty::TermKind::Const(c) => Term::Constant(clean_middle_const(c, cx)),
}
}
@@ -417,7 +403,7 @@ fn clean_projection<'tcx>(
def_id: Option<DefId>,
) -> Type {
let lifted = ty.lift_to_tcx(cx.tcx).unwrap();
- let trait_ = clean_trait_ref_with_bindings(cx, lifted.trait_ref(cx.tcx), &[]);
+ let trait_ = clean_trait_ref_with_bindings(cx, lifted.trait_ref(cx.tcx), ThinVec::new());
let self_type = clean_middle_ty(ty.self_ty(), cx, None);
let self_def_id = if let Some(def_id) = def_id {
cx.tcx.opt_parent(def_id).or(Some(def_id))
@@ -425,12 +411,12 @@ fn clean_projection<'tcx>(
self_type.def_id(&cx.cache)
};
let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type);
- Type::QPath {
- assoc: Box::new(projection_to_path_segment(ty, cx)),
+ Type::QPath(Box::new(QPathData {
+ assoc: projection_to_path_segment(ty, cx),
should_show_cast,
- self_type: Box::new(self_type),
+ self_type,
trait_,
- }
+ }))
}
fn compute_should_show_cast(self_def_id: Option<DefId>, trait_: &Path, self_type: &Type) -> bool {
@@ -509,7 +495,7 @@ fn clean_generic_param<'tcx>(
.filter(|bp| !bp.in_where_clause)
.flat_map(|bp| bp.bounds)
.map(|bound| match bound {
- hir::GenericBound::Outlives(lt) => clean_lifetime(*lt, cx),
+ hir::GenericBound::Outlives(lt) => clean_lifetime(lt, cx),
_ => panic!(),
})
.collect()
@@ -524,7 +510,7 @@ fn clean_generic_param<'tcx>(
.bounds_for_param(did)
.filter(|bp| bp.origin != PredicateOrigin::WhereClause)
.flat_map(|bp| bp.bounds)
- .filter_map(|x| x.clean(cx))
+ .filter_map(|x| clean_generic_bound(x, cx))
.collect()
} else {
Vec::new()
@@ -572,65 +558,68 @@ fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
matches!(param.kind, hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided })
}
-impl<'tcx> Clean<'tcx, Generics> for hir::Generics<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> Generics {
- let impl_trait_params = self
- .params
- .iter()
- .filter(|param| is_impl_trait(param))
- .map(|param| {
- let param = clean_generic_param(cx, Some(self), param);
- match param.kind {
- GenericParamDefKind::Lifetime { .. } => unreachable!(),
- GenericParamDefKind::Type { did, ref bounds, .. } => {
- cx.impl_trait_bounds.insert(did.into(), bounds.clone());
- }
- GenericParamDefKind::Const { .. } => unreachable!(),
+pub(crate) fn clean_generics<'tcx>(
+ gens: &hir::Generics<'tcx>,
+ cx: &mut DocContext<'tcx>,
+) -> Generics {
+ let impl_trait_params = gens
+ .params
+ .iter()
+ .filter(|param| is_impl_trait(param))
+ .map(|param| {
+ let param = clean_generic_param(cx, Some(gens), param);
+ match param.kind {
+ GenericParamDefKind::Lifetime { .. } => unreachable!(),
+ GenericParamDefKind::Type { did, ref bounds, .. } => {
+ cx.impl_trait_bounds.insert(did.into(), bounds.clone());
}
- param
- })
- .collect::<Vec<_>>();
+ GenericParamDefKind::Const { .. } => unreachable!(),
+ }
+ param
+ })
+ .collect::<Vec<_>>();
- let mut params = Vec::with_capacity(self.params.len());
- for p in self.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) {
- let p = clean_generic_param(cx, Some(self), p);
- params.push(p);
- }
- params.extend(impl_trait_params);
+ let mut params = Vec::with_capacity(gens.params.len());
+ for p in gens.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) {
+ let p = clean_generic_param(cx, Some(gens), p);
+ params.push(p);
+ }
+ params.extend(impl_trait_params);
- let mut generics = Generics {
- params,
- where_predicates: self.predicates.iter().filter_map(|x| x.clean(cx)).collect(),
- };
+ let mut generics = Generics {
+ params,
+ where_predicates: gens
+ .predicates
+ .iter()
+ .filter_map(|x| clean_where_predicate(x, cx))
+ .collect(),
+ };
- // Some duplicates are generated for ?Sized bounds between type params and where
- // predicates. The point in here is to move the bounds definitions from type params
- // to where predicates when such cases occur.
- for where_pred in &mut generics.where_predicates {
- match *where_pred {
- WherePredicate::BoundPredicate {
- ty: Generic(ref name), ref mut bounds, ..
- } => {
- if bounds.is_empty() {
- for param in &mut generics.params {
- match param.kind {
- GenericParamDefKind::Lifetime { .. } => {}
- GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
- if &param.name == name {
- mem::swap(bounds, ty_bounds);
- break;
- }
+ // Some duplicates are generated for ?Sized bounds between type params and where
+ // predicates. The point in here is to move the bounds definitions from type params
+ // to where predicates when such cases occur.
+ for where_pred in &mut generics.where_predicates {
+ match *where_pred {
+ WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds, .. } => {
+ if bounds.is_empty() {
+ for param in &mut generics.params {
+ match param.kind {
+ GenericParamDefKind::Lifetime { .. } => {}
+ GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
+ if &param.name == name {
+ mem::swap(bounds, ty_bounds);
+ break;
}
- GenericParamDefKind::Const { .. } => {}
}
+ GenericParamDefKind::Const { .. } => {}
}
}
}
- _ => continue,
}
+ _ => continue,
}
- generics
}
+ generics
}
fn clean_ty_generics<'tcx>(
@@ -701,7 +690,7 @@ fn clean_ty_generics<'tcx>(
if let Some(param_idx) = param_idx {
if let Some(b) = impl_trait.get_mut(&param_idx.into()) {
- let p: WherePredicate = p.clean(cx)?;
+ let p: WherePredicate = clean_predicate(*p, cx)?;
b.extend(
p.get_bounds()
@@ -758,7 +747,7 @@ fn clean_ty_generics<'tcx>(
// Now that `cx.impl_trait_bounds` is populated, we can process
// remaining predicates which could contain `impl Trait`.
let mut where_predicates =
- where_predicates.into_iter().flat_map(|p| p.clean(cx)).collect::<Vec<_>>();
+ where_predicates.into_iter().flat_map(|p| clean_predicate(*p, cx)).collect::<Vec<_>>();
// Type parameters have a Sized bound by default unless removed with
// ?Sized. Scan through the predicates and mark any type parameter with
@@ -896,9 +885,12 @@ fn clean_function<'tcx>(
) -> Box<Function> {
let (generics, decl) = enter_impl_trait(cx, |cx| {
// NOTE: generics must be cleaned before args
- let generics = generics.clean(cx);
+ let generics = clean_generics(generics, cx);
let args = clean_args_from_types_and_body_id(cx, sig.decl.inputs, body_id);
- let decl = clean_fn_decl_with_args(cx, sig.decl, args);
+ let mut decl = clean_fn_decl_with_args(cx, sig.decl, args);
+ if sig.header.is_async() {
+ decl.output = decl.sugared_async_return_type();
+ }
(generics, decl)
});
Box::new(Function { decl, generics })
@@ -994,305 +986,307 @@ fn clean_trait_ref<'tcx>(trait_ref: &hir::TraitRef<'tcx>, cx: &mut DocContext<'t
path
}
-impl<'tcx> Clean<'tcx, PolyTrait> for hir::PolyTraitRef<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> PolyTrait {
- PolyTrait {
- trait_: clean_trait_ref(&self.trait_ref, cx),
- generic_params: self
- .bound_generic_params
- .iter()
- .filter(|p| !is_elided_lifetime(p))
- .map(|x| clean_generic_param(cx, None, x))
- .collect(),
- }
+fn clean_poly_trait_ref<'tcx>(
+ poly_trait_ref: &hir::PolyTraitRef<'tcx>,
+ cx: &mut DocContext<'tcx>,
+) -> PolyTrait {
+ PolyTrait {
+ trait_: clean_trait_ref(&poly_trait_ref.trait_ref, cx),
+ generic_params: poly_trait_ref
+ .bound_generic_params
+ .iter()
+ .filter(|p| !is_elided_lifetime(p))
+ .map(|x| clean_generic_param(cx, None, x))
+ .collect(),
}
}
-impl<'tcx> Clean<'tcx, Item> for hir::TraitItem<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
- let local_did = self.def_id.to_def_id();
- cx.with_param_env(local_did, |cx| {
- let inner = match self.kind {
- hir::TraitItemKind::Const(ty, Some(default)) => AssocConstItem(
- clean_ty(ty, cx),
- ConstantKind::Local { def_id: local_did, body: default },
- ),
- hir::TraitItemKind::Const(ty, None) => TyAssocConstItem(clean_ty(ty, cx)),
- hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
- let m = clean_function(cx, sig, self.generics, body);
- MethodItem(m, None)
- }
- hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
- let (generics, decl) = enter_impl_trait(cx, |cx| {
- // NOTE: generics must be cleaned before args
- let generics = self.generics.clean(cx);
- let args = clean_args_from_types_and_names(cx, sig.decl.inputs, names);
- let decl = clean_fn_decl_with_args(cx, sig.decl, args);
- (generics, decl)
- });
- TyMethodItem(Box::new(Function { decl, generics }))
- }
- hir::TraitItemKind::Type(bounds, Some(default)) => {
- let generics = enter_impl_trait(cx, |cx| self.generics.clean(cx));
- let bounds = bounds.iter().filter_map(|x| x.clean(cx)).collect();
- let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, default), cx, None);
- AssocTypeItem(
- Box::new(Typedef {
- type_: clean_ty(default, cx),
- generics,
- item_type: Some(item_type),
- }),
- bounds,
- )
- }
- hir::TraitItemKind::Type(bounds, None) => {
- let generics = enter_impl_trait(cx, |cx| self.generics.clean(cx));
- let bounds = bounds.iter().filter_map(|x| x.clean(cx)).collect();
- TyAssocTypeItem(Box::new(generics), bounds)
- }
- };
- let what_rustc_thinks =
- Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx);
- // Trait items always inherit the trait's visibility -- we don't want to show `pub`.
- Item { visibility: Inherited, ..what_rustc_thinks }
- })
- }
+fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
+ let local_did = trait_item.def_id.to_def_id();
+ cx.with_param_env(local_did, |cx| {
+ let inner = match trait_item.kind {
+ hir::TraitItemKind::Const(ty, Some(default)) => AssocConstItem(
+ clean_ty(ty, cx),
+ ConstantKind::Local { def_id: local_did, body: default },
+ ),
+ hir::TraitItemKind::Const(ty, None) => TyAssocConstItem(clean_ty(ty, cx)),
+ hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
+ let m = clean_function(cx, sig, trait_item.generics, body);
+ MethodItem(m, None)
+ }
+ hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
+ let (generics, decl) = enter_impl_trait(cx, |cx| {
+ // NOTE: generics must be cleaned before args
+ let generics = clean_generics(trait_item.generics, cx);
+ let args = clean_args_from_types_and_names(cx, sig.decl.inputs, names);
+ let decl = clean_fn_decl_with_args(cx, sig.decl, args);
+ (generics, decl)
+ });
+ TyMethodItem(Box::new(Function { decl, generics }))
+ }
+ hir::TraitItemKind::Type(bounds, Some(default)) => {
+ let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
+ let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
+ let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, default), cx, None);
+ AssocTypeItem(
+ Box::new(Typedef {
+ type_: clean_ty(default, cx),
+ generics,
+ item_type: Some(item_type),
+ }),
+ bounds,
+ )
+ }
+ hir::TraitItemKind::Type(bounds, None) => {
+ let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
+ let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
+ TyAssocTypeItem(Box::new(generics), bounds)
+ }
+ };
+ let what_rustc_thinks =
+ Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx);
+ // Trait items always inherit the trait's visibility -- we don't want to show `pub`.
+ Item { visibility: Inherited, ..what_rustc_thinks }
+ })
}
-impl<'tcx> Clean<'tcx, Item> for hir::ImplItem<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
- let local_did = self.def_id.to_def_id();
- cx.with_param_env(local_did, |cx| {
- let inner = match self.kind {
- hir::ImplItemKind::Const(ty, expr) => {
- let default = ConstantKind::Local { def_id: local_did, body: expr };
- AssocConstItem(clean_ty(ty, cx), default)
- }
- hir::ImplItemKind::Fn(ref sig, body) => {
- let m = clean_function(cx, sig, self.generics, body);
- let defaultness = cx.tcx.impl_defaultness(self.def_id);
- MethodItem(m, Some(defaultness))
- }
- hir::ImplItemKind::TyAlias(hir_ty) => {
- let type_ = clean_ty(hir_ty, cx);
- let generics = self.generics.clean(cx);
- let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
- AssocTypeItem(
- Box::new(Typedef { type_, generics, item_type: Some(item_type) }),
- Vec::new(),
- )
- }
- };
+pub(crate) fn clean_impl_item<'tcx>(
+ impl_: &hir::ImplItem<'tcx>,
+ cx: &mut DocContext<'tcx>,
+) -> Item {
+ let local_did = impl_.def_id.to_def_id();
+ cx.with_param_env(local_did, |cx| {
+ let inner = match impl_.kind {
+ hir::ImplItemKind::Const(ty, expr) => {
+ let default = ConstantKind::Local { def_id: local_did, body: expr };
+ AssocConstItem(clean_ty(ty, cx), default)
+ }
+ hir::ImplItemKind::Fn(ref sig, body) => {
+ let m = clean_function(cx, sig, impl_.generics, body);
+ let defaultness = cx.tcx.impl_defaultness(impl_.def_id);
+ MethodItem(m, Some(defaultness))
+ }
+ hir::ImplItemKind::TyAlias(hir_ty) => {
+ let type_ = clean_ty(hir_ty, cx);
+ let generics = clean_generics(impl_.generics, cx);
+ let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
+ AssocTypeItem(
+ Box::new(Typedef { type_, generics, item_type: Some(item_type) }),
+ Vec::new(),
+ )
+ }
+ };
- let mut what_rustc_thinks =
- Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx);
+ let mut what_rustc_thinks =
+ Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx);
- let impl_ref = cx.tcx.impl_trait_ref(cx.tcx.local_parent(self.def_id));
+ let impl_ref = cx.tcx.impl_trait_ref(cx.tcx.local_parent(impl_.def_id));
- // Trait impl items always inherit the impl's visibility --
- // we don't want to show `pub`.
- if impl_ref.is_some() {
- what_rustc_thinks.visibility = Inherited;
- }
+ // Trait impl items always inherit the impl's visibility --
+ // we don't want to show `pub`.
+ if impl_ref.is_some() {
+ what_rustc_thinks.visibility = Inherited;
+ }
- what_rustc_thinks
- })
- }
+ what_rustc_thinks
+ })
}
-impl<'tcx> Clean<'tcx, Item> for ty::AssocItem {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
- let tcx = cx.tcx;
- let kind = match self.kind {
- ty::AssocKind::Const => {
- let ty = clean_middle_ty(tcx.type_of(self.def_id), cx, Some(self.def_id));
+pub(crate) fn clean_middle_assoc_item<'tcx>(
+ assoc_item: &ty::AssocItem,
+ cx: &mut DocContext<'tcx>,
+) -> Item {
+ let tcx = cx.tcx;
+ let kind = match assoc_item.kind {
+ ty::AssocKind::Const => {
+ let ty = clean_middle_ty(tcx.type_of(assoc_item.def_id), cx, Some(assoc_item.def_id));
- let provided = match self.container {
- ty::ImplContainer => true,
- ty::TraitContainer => tcx.impl_defaultness(self.def_id).has_value(),
- };
- if provided {
- AssocConstItem(ty, ConstantKind::Extern { def_id: self.def_id })
- } else {
- TyAssocConstItem(ty)
- }
+ let provided = match assoc_item.container {
+ ty::ImplContainer => true,
+ ty::TraitContainer => tcx.impl_defaultness(assoc_item.def_id).has_value(),
+ };
+ if provided {
+ AssocConstItem(ty, ConstantKind::Extern { def_id: assoc_item.def_id })
+ } else {
+ TyAssocConstItem(ty)
}
- ty::AssocKind::Fn => {
- let generics = clean_ty_generics(
- cx,
- tcx.generics_of(self.def_id),
- tcx.explicit_predicates_of(self.def_id),
- );
- let sig = tcx.fn_sig(self.def_id);
- let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(self.def_id), sig);
-
- if self.fn_has_self_parameter {
- let self_ty = match self.container {
- ty::ImplContainer => tcx.type_of(self.container_id(tcx)),
- ty::TraitContainer => tcx.types.self_param,
- };
- let self_arg_ty = sig.input(0).skip_binder();
- if self_arg_ty == self_ty {
- decl.inputs.values[0].type_ = Generic(kw::SelfUpper);
- } else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() {
- if ty == self_ty {
- match decl.inputs.values[0].type_ {
- BorrowedRef { ref mut type_, .. } => {
- **type_ = Generic(kw::SelfUpper)
- }
- _ => unreachable!(),
- }
+ }
+ ty::AssocKind::Fn => {
+ let generics = clean_ty_generics(
+ cx,
+ tcx.generics_of(assoc_item.def_id),
+ tcx.explicit_predicates_of(assoc_item.def_id),
+ );
+ let sig = tcx.fn_sig(assoc_item.def_id);
+ let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(assoc_item.def_id), sig);
+
+ if assoc_item.fn_has_self_parameter {
+ let self_ty = match assoc_item.container {
+ ty::ImplContainer => tcx.type_of(assoc_item.container_id(tcx)),
+ ty::TraitContainer => tcx.types.self_param,
+ };
+ let self_arg_ty = sig.input(0).skip_binder();
+ if self_arg_ty == self_ty {
+ decl.inputs.values[0].type_ = Generic(kw::SelfUpper);
+ } else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() {
+ if ty == self_ty {
+ match decl.inputs.values[0].type_ {
+ BorrowedRef { ref mut type_, .. } => **type_ = Generic(kw::SelfUpper),
+ _ => unreachable!(),
}
}
}
+ }
- let provided = match self.container {
- ty::ImplContainer => true,
- ty::TraitContainer => self.defaultness(tcx).has_value(),
+ let provided = match assoc_item.container {
+ ty::ImplContainer => true,
+ ty::TraitContainer => assoc_item.defaultness(tcx).has_value(),
+ };
+ if provided {
+ let defaultness = match assoc_item.container {
+ ty::ImplContainer => Some(assoc_item.defaultness(tcx)),
+ ty::TraitContainer => None,
};
- if provided {
- let defaultness = match self.container {
- ty::ImplContainer => Some(self.defaultness(tcx)),
- ty::TraitContainer => None,
- };
- MethodItem(Box::new(Function { generics, decl }), defaultness)
- } else {
- TyMethodItem(Box::new(Function { generics, decl }))
- }
+ MethodItem(Box::new(Function { generics, decl }), defaultness)
+ } else {
+ TyMethodItem(Box::new(Function { generics, decl }))
}
- ty::AssocKind::Type => {
- let my_name = self.name;
-
- fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
- match (&param.kind, arg) {
- (GenericParamDefKind::Type { .. }, GenericArg::Type(Type::Generic(ty)))
- if *ty == param.name =>
- {
- true
- }
- (
- GenericParamDefKind::Lifetime { .. },
- GenericArg::Lifetime(Lifetime(lt)),
- ) if *lt == param.name => true,
- (GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => {
- match &c.kind {
- ConstantKind::TyConst { expr } => expr == param.name.as_str(),
- _ => false,
- }
- }
- _ => false,
+ }
+ ty::AssocKind::Type => {
+ let my_name = assoc_item.name;
+
+ fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
+ match (&param.kind, arg) {
+ (GenericParamDefKind::Type { .. }, GenericArg::Type(Type::Generic(ty)))
+ if *ty == param.name =>
+ {
+ true
+ }
+ (GenericParamDefKind::Lifetime { .. }, GenericArg::Lifetime(Lifetime(lt)))
+ if *lt == param.name =>
+ {
+ true
}
+ (GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => match &c.kind {
+ ConstantKind::TyConst { expr } => expr == param.name.as_str(),
+ _ => false,
+ },
+ _ => false,
}
+ }
- if let ty::TraitContainer = self.container {
- let bounds = tcx.explicit_item_bounds(self.def_id);
- let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
- let mut generics =
- clean_ty_generics(cx, tcx.generics_of(self.def_id), predicates);
- // Filter out the bounds that are (likely?) directly attached to the associated type,
- // as opposed to being located in the where clause.
- let mut bounds = generics
- .where_predicates
- .drain_filter(|pred| match *pred {
- WherePredicate::BoundPredicate {
- ty: QPath { ref assoc, ref self_type, ref trait_, .. },
- ..
- } => {
- if assoc.name != my_name {
- return false;
- }
- if trait_.def_id() != self.container_id(tcx) {
- return false;
- }
- match **self_type {
- Generic(ref s) if *s == kw::SelfUpper => {}
- _ => return false,
- }
- match &assoc.args {
- GenericArgs::AngleBracketed { args, bindings } => {
- if !bindings.is_empty()
- || generics
- .params
- .iter()
- .zip(args.iter())
- .any(|(param, arg)| !param_eq_arg(param, arg))
- {
- return false;
- }
- }
- GenericArgs::Parenthesized { .. } => {
- // The only time this happens is if we're inside the rustdoc for Fn(),
- // which only has one associated type, which is not a GAT, so whatever.
+ if let ty::TraitContainer = assoc_item.container {
+ let bounds = tcx.explicit_item_bounds(assoc_item.def_id);
+ let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
+ let mut generics =
+ clean_ty_generics(cx, tcx.generics_of(assoc_item.def_id), predicates);
+ // Filter out the bounds that are (likely?) directly attached to the associated type,
+ // as opposed to being located in the where clause.
+ let mut bounds = generics
+ .where_predicates
+ .drain_filter(|pred| match *pred {
+ WherePredicate::BoundPredicate {
+ ty: QPath(box QPathData { ref assoc, ref self_type, ref trait_, .. }),
+ ..
+ } => {
+ if assoc.name != my_name {
+ return false;
+ }
+ if trait_.def_id() != assoc_item.container_id(tcx) {
+ return false;
+ }
+ match *self_type {
+ Generic(ref s) if *s == kw::SelfUpper => {}
+ _ => return false,
+ }
+ match &assoc.args {
+ GenericArgs::AngleBracketed { args, bindings } => {
+ if !bindings.is_empty()
+ || generics
+ .params
+ .iter()
+ .zip(args.iter())
+ .any(|(param, arg)| !param_eq_arg(param, arg))
+ {
+ return false;
}
}
- true
- }
- _ => false,
- })
- .flat_map(|pred| {
- if let WherePredicate::BoundPredicate { bounds, .. } = pred {
- bounds
- } else {
- unreachable!()
+ GenericArgs::Parenthesized { .. } => {
+ // The only time this happens is if we're inside the rustdoc for Fn(),
+ // which only has one associated type, which is not a GAT, so whatever.
+ }
}
- })
- .collect::<Vec<_>>();
- // Our Sized/?Sized bound didn't get handled when creating the generics
- // because we didn't actually get our whole set of bounds until just now
- // (some of them may have come from the trait). If we do have a sized
- // bound, we remove it, and if we don't then we add the `?Sized` bound
- // at the end.
- match bounds.iter().position(|b| b.is_sized_bound(cx)) {
- Some(i) => {
- bounds.remove(i);
+ true
}
- None => bounds.push(GenericBound::maybe_sized(cx)),
+ _ => false,
+ })
+ .flat_map(|pred| {
+ if let WherePredicate::BoundPredicate { bounds, .. } = pred {
+ bounds
+ } else {
+ unreachable!()
+ }
+ })
+ .collect::<Vec<_>>();
+ // Our Sized/?Sized bound didn't get handled when creating the generics
+ // because we didn't actually get our whole set of bounds until just now
+ // (some of them may have come from the trait). If we do have a sized
+ // bound, we remove it, and if we don't then we add the `?Sized` bound
+ // at the end.
+ match bounds.iter().position(|b| b.is_sized_bound(cx)) {
+ Some(i) => {
+ bounds.remove(i);
}
+ None => bounds.push(GenericBound::maybe_sized(cx)),
+ }
- if tcx.impl_defaultness(self.def_id).has_value() {
- AssocTypeItem(
- Box::new(Typedef {
- type_: clean_middle_ty(
- tcx.type_of(self.def_id),
- cx,
- Some(self.def_id),
- ),
- generics,
- // FIXME: should we obtain the Type from HIR and pass it on here?
- item_type: None,
- }),
- bounds,
- )
- } else {
- TyAssocTypeItem(Box::new(generics), bounds)
- }
- } else {
- // FIXME: when could this happen? Associated items in inherent impls?
+ if tcx.impl_defaultness(assoc_item.def_id).has_value() {
AssocTypeItem(
Box::new(Typedef {
- type_: clean_middle_ty(tcx.type_of(self.def_id), cx, Some(self.def_id)),
- generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
+ type_: clean_middle_ty(
+ tcx.type_of(assoc_item.def_id),
+ cx,
+ Some(assoc_item.def_id),
+ ),
+ generics,
+ // FIXME: should we obtain the Type from HIR and pass it on here?
item_type: None,
}),
- Vec::new(),
+ bounds,
)
+ } else {
+ TyAssocTypeItem(Box::new(generics), bounds)
}
+ } else {
+ // FIXME: when could this happen? Associated items in inherent impls?
+ AssocTypeItem(
+ Box::new(Typedef {
+ type_: clean_middle_ty(
+ tcx.type_of(assoc_item.def_id),
+ cx,
+ Some(assoc_item.def_id),
+ ),
+ generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
+ item_type: None,
+ }),
+ Vec::new(),
+ )
}
- };
+ }
+ };
- let mut what_rustc_thinks =
- Item::from_def_id_and_parts(self.def_id, Some(self.name), kind, cx);
+ let mut what_rustc_thinks =
+ Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name), kind, cx);
- let impl_ref = tcx.impl_trait_ref(tcx.parent(self.def_id));
+ let impl_ref = tcx.impl_trait_ref(tcx.parent(assoc_item.def_id));
- // Trait impl items always inherit the impl's visibility --
- // we don't want to show `pub`.
- if impl_ref.is_some() {
- what_rustc_thinks.visibility = Visibility::Inherited;
- }
-
- what_rustc_thinks
+ // Trait impl items always inherit the impl's visibility --
+ // we don't want to show `pub`.
+ if impl_ref.is_some() {
+ what_rustc_thinks.visibility = Visibility::Inherited;
}
+
+ what_rustc_thinks
}
fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type {
@@ -1328,18 +1322,18 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
let trait_def = cx.tcx.associated_item(p.res.def_id()).container_id(cx.tcx);
let trait_ = self::Path {
res: Res::Def(DefKind::Trait, trait_def),
- segments: trait_segments.iter().map(|x| x.clean(cx)).collect(),
+ segments: trait_segments.iter().map(|x| clean_path_segment(x, cx)).collect(),
};
register_res(cx, trait_.res);
let self_def_id = DefId::local(qself.hir_id.owner.local_def_index);
let self_type = clean_ty(qself, cx);
let should_show_cast = compute_should_show_cast(Some(self_def_id), &trait_, &self_type);
- Type::QPath {
- assoc: Box::new(p.segments.last().expect("segments were empty").clean(cx)),
+ Type::QPath(Box::new(QPathData {
+ assoc: clean_path_segment(p.segments.last().expect("segments were empty"), cx),
should_show_cast,
- self_type: Box::new(self_type),
+ self_type,
trait_,
- }
+ }))
}
hir::QPath::TypeRelative(qself, segment) => {
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
@@ -1354,12 +1348,12 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
let self_def_id = res.opt_def_id();
let self_type = clean_ty(qself, cx);
let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type);
- Type::QPath {
- assoc: Box::new(segment.clean(cx)),
+ Type::QPath(Box::new(QPathData {
+ assoc: clean_path_segment(segment, cx),
should_show_cast,
- self_type: Box::new(self_type),
+ self_type,
trait_,
- }
+ }))
}
hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"),
}
@@ -1398,7 +1392,7 @@ fn maybe_expand_private_type_alias<'tcx>(
}
_ => None,
});
- if let Some(lt) = lifetime.cloned() {
+ if let Some(lt) = lifetime {
let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
let cleaned =
if !lt.is_elided() { clean_lifetime(lt, cx) } else { Lifetime::elided() };
@@ -1498,22 +1492,22 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
Array(Box::new(clean_ty(ty, cx)), length)
}
TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()),
- TyKind::OpaqueDef(item_id, _) => {
+ TyKind::OpaqueDef(item_id, _, _) => {
let item = cx.tcx.hir().item(item_id);
if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
- ImplTrait(ty.bounds.iter().filter_map(|x| x.clean(cx)).collect())
+ ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect())
} else {
unreachable!()
}
}
TyKind::Path(_) => clean_qpath(ty, cx),
TyKind::TraitObject(bounds, ref lifetime, _) => {
- let bounds = bounds.iter().map(|bound| bound.clean(cx)).collect();
+ let bounds = bounds.iter().map(|bound| clean_poly_trait_ref(bound, cx)).collect();
let lifetime =
if !lifetime.is_elided() { Some(clean_lifetime(*lifetime, cx)) } else { None };
DynTrait(bounds, lifetime)
}
- TyKind::BareFn(barefn) => BareFunction(Box::new(barefn.clean(cx))),
+ TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),
// Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
TyKind::Infer | TyKind::Err => Infer,
TyKind::Typeof(..) => panic!("unimplemented type {:?}", ty.kind),
@@ -1598,21 +1592,22 @@ pub(crate) fn clean_middle_ty<'tcx>(
AdtKind::Enum => ItemType::Enum,
};
inline::record_extern_fqn(cx, did, kind);
- let path = external_path(cx, did, false, vec![], substs);
+ let path = external_path(cx, did, false, ThinVec::new(), substs);
Type::Path { path }
}
ty::Foreign(did) => {
inline::record_extern_fqn(cx, did, ItemType::ForeignType);
- let path = external_path(cx, did, false, vec![], InternalSubsts::empty());
+ let path = external_path(cx, did, false, ThinVec::new(), InternalSubsts::empty());
Type::Path { path }
}
- ty::Dynamic(obj, ref reg) => {
+ ty::Dynamic(obj, ref reg, _) => {
// HACK: pick the first `did` as the `did` of the trait object. Someone
// might want to implement "native" support for marker-trait-only
// trait objects.
- let mut dids = obj.principal_def_id().into_iter().chain(obj.auto_traits());
- let did = dids
- .next()
+ let mut dids = obj.auto_traits();
+ let did = obj
+ .principal_def_id()
+ .or_else(|| dids.next())
.unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", this));
let substs = match obj.principal() {
Some(principal) => principal.skip_binder().substs,
@@ -1623,19 +1618,18 @@ pub(crate) fn clean_middle_ty<'tcx>(
inline::record_extern_fqn(cx, did, ItemType::Trait);
let lifetime = clean_middle_region(*reg);
- let mut bounds = vec![];
-
- for did in dids {
- let empty = cx.tcx.intern_substs(&[]);
- let path = external_path(cx, did, false, vec![], empty);
- inline::record_extern_fqn(cx, did, ItemType::Trait);
- let bound = PolyTrait { trait_: path, generic_params: Vec::new() };
- bounds.push(bound);
- }
+ let mut bounds = dids
+ .map(|did| {
+ let empty = cx.tcx.intern_substs(&[]);
+ let path = external_path(cx, did, false, ThinVec::new(), empty);
+ inline::record_extern_fqn(cx, did, ItemType::Trait);
+ PolyTrait { trait_: path, generic_params: Vec::new() }
+ })
+ .collect::<Vec<_>>();
- let mut bindings = vec![];
- for pb in obj.projection_bounds() {
- bindings.push(TypeBinding {
+ let bindings = obj
+ .projection_bounds()
+ .map(|pb| TypeBinding {
assoc: projection_to_path_segment(
pb.skip_binder()
.lift_to_tcx(cx.tcx)
@@ -1649,8 +1643,8 @@ pub(crate) fn clean_middle_ty<'tcx>(
kind: TypeBindingKind::Equality {
term: clean_middle_term(pb.skip_binder().term, cx),
},
- });
- }
+ })
+ .collect();
let path = external_path(cx, did, false, bindings, substs);
bounds.insert(0, PolyTrait { trait_: path, generic_params: Vec::new() });
@@ -1703,7 +1697,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
}
}
- let bindings: Vec<_> = bounds
+ let bindings: ThinVec<_> = bounds
.iter()
.filter_map(|bound| {
if let ty::PredicateKind::Projection(proj) = bound.kind().skip_binder()
@@ -1724,7 +1718,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
})
.collect();
- Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, &bindings))
+ Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, bindings))
})
.collect::<Vec<_>>();
bounds.extend(regions);
@@ -1783,21 +1777,19 @@ fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
}
}
-pub(crate) fn clean_visibility(vis: ty::Visibility) -> Visibility {
+pub(crate) fn clean_visibility(vis: ty::Visibility<DefId>) -> Visibility {
match vis {
ty::Visibility::Public => Visibility::Public,
- // NOTE: this is not quite right: `ty` uses `Invisible` to mean 'private',
- // while rustdoc really does mean inherited. That means that for enum variants, such as
- // `pub enum E { V }`, `V` will be marked as `Public` by `ty`, but as `Inherited` by rustdoc.
- // Various parts of clean override `tcx.visibility` explicitly to make sure this distinction is captured.
- ty::Visibility::Invisible => Visibility::Inherited,
ty::Visibility::Restricted(module) => Visibility::Restricted(module),
}
}
pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocContext<'tcx>) -> Item {
let kind = match variant.ctor_kind {
- CtorKind::Const => Variant::CLike,
+ CtorKind::Const => Variant::CLike(match variant.discr {
+ ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }),
+ ty::VariantDiscr::Relative(_) => None,
+ }),
CtorKind::Fn => Variant::Tuple(
variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
),
@@ -1814,6 +1806,7 @@ pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocCont
fn clean_variant_data<'tcx>(
variant: &hir::VariantData<'tcx>,
+ disr_expr: &Option<hir::AnonConst>,
cx: &mut DocContext<'tcx>,
) -> Variant {
match variant {
@@ -1824,66 +1817,75 @@ fn clean_variant_data<'tcx>(
hir::VariantData::Tuple(..) => {
Variant::Tuple(variant.fields().iter().map(|x| clean_field(x, cx)).collect())
}
- hir::VariantData::Unit(..) => Variant::CLike,
+ hir::VariantData::Unit(..) => Variant::CLike(disr_expr.map(|disr| Discriminant {
+ expr: Some(disr.body),
+ value: cx.tcx.hir().local_def_id(disr.hir_id).to_def_id(),
+ })),
}
}
fn clean_path<'tcx>(path: &hir::Path<'tcx>, cx: &mut DocContext<'tcx>) -> Path {
- Path { res: path.res, segments: path.segments.iter().map(|x| x.clean(cx)).collect() }
+ Path {
+ res: path.res,
+ segments: path.segments.iter().map(|x| clean_path_segment(x, cx)).collect(),
+ }
}
-impl<'tcx> Clean<'tcx, GenericArgs> for hir::GenericArgs<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericArgs {
- if self.parenthesized {
- let output = clean_ty(self.bindings[0].ty(), cx);
- let output =
- if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None };
- let inputs = self.inputs().iter().map(|x| clean_ty(x, cx)).collect::<Vec<_>>().into();
- GenericArgs::Parenthesized { inputs, output }
- } else {
- let args = self
- .args
- .iter()
- .map(|arg| match arg {
- hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
- GenericArg::Lifetime(clean_lifetime(*lt, cx))
- }
- hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
- hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)),
- hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(clean_const(ct, cx))),
- hir::GenericArg::Infer(_inf) => GenericArg::Infer,
- })
- .collect::<Vec<_>>()
- .into();
- let bindings =
- self.bindings.iter().map(|x| clean_type_binding(x, cx)).collect::<Vec<_>>().into();
- GenericArgs::AngleBracketed { args, bindings }
- }
+fn clean_generic_args<'tcx>(
+ generic_args: &hir::GenericArgs<'tcx>,
+ cx: &mut DocContext<'tcx>,
+) -> GenericArgs {
+ if generic_args.parenthesized {
+ let output = clean_ty(generic_args.bindings[0].ty(), cx);
+ let output = if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None };
+ let inputs =
+ generic_args.inputs().iter().map(|x| clean_ty(x, cx)).collect::<Vec<_>>().into();
+ GenericArgs::Parenthesized { inputs, output }
+ } else {
+ let args = generic_args
+ .args
+ .iter()
+ .map(|arg| match arg {
+ hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
+ GenericArg::Lifetime(clean_lifetime(*lt, cx))
+ }
+ hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
+ hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)),
+ hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(clean_const(ct, cx))),
+ hir::GenericArg::Infer(_inf) => GenericArg::Infer,
+ })
+ .collect::<Vec<_>>()
+ .into();
+ let bindings =
+ generic_args.bindings.iter().map(|x| clean_type_binding(x, cx)).collect::<ThinVec<_>>();
+ GenericArgs::AngleBracketed { args, bindings }
}
}
-impl<'tcx> Clean<'tcx, PathSegment> for hir::PathSegment<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> PathSegment {
- PathSegment { name: self.ident.name, args: self.args().clean(cx) }
- }
+fn clean_path_segment<'tcx>(
+ path: &hir::PathSegment<'tcx>,
+ cx: &mut DocContext<'tcx>,
+) -> PathSegment {
+ PathSegment { name: path.ident.name, args: clean_generic_args(path.args(), cx) }
}
-impl<'tcx> Clean<'tcx, BareFunctionDecl> for hir::BareFnTy<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> BareFunctionDecl {
- let (generic_params, decl) = enter_impl_trait(cx, |cx| {
- // NOTE: generics must be cleaned before args
- let generic_params = self
- .generic_params
- .iter()
- .filter(|p| !is_elided_lifetime(p))
- .map(|x| clean_generic_param(cx, None, x))
- .collect();
- let args = clean_args_from_types_and_names(cx, self.decl.inputs, self.param_names);
- let decl = clean_fn_decl_with_args(cx, self.decl, args);
- (generic_params, decl)
- });
- BareFunctionDecl { unsafety: self.unsafety, abi: self.abi, decl, generic_params }
- }
+fn clean_bare_fn_ty<'tcx>(
+ bare_fn: &hir::BareFnTy<'tcx>,
+ cx: &mut DocContext<'tcx>,
+) -> BareFunctionDecl {
+ let (generic_params, decl) = enter_impl_trait(cx, |cx| {
+ // NOTE: generics must be cleaned before args
+ let generic_params = bare_fn
+ .generic_params
+ .iter()
+ .filter(|p| !is_elided_lifetime(p))
+ .map(|x| clean_generic_param(cx, None, x))
+ .collect();
+ let args = clean_args_from_types_and_names(cx, bare_fn.decl.inputs, bare_fn.param_names);
+ let decl = clean_fn_decl_with_args(cx, bare_fn.decl, args);
+ (generic_params, decl)
+ });
+ BareFunctionDecl { unsafety: bare_fn.unsafety, abi: bare_fn.abi, decl, generic_params }
}
fn clean_maybe_renamed_item<'tcx>(
@@ -1905,33 +1907,33 @@ fn clean_maybe_renamed_item<'tcx>(
kind: ConstantKind::Local { body: body_id, def_id },
}),
ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
- bounds: ty.bounds.iter().filter_map(|x| x.clean(cx)).collect(),
- generics: ty.generics.clean(cx),
+ bounds: ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
+ generics: clean_generics(ty.generics, cx),
}),
ItemKind::TyAlias(hir_ty, generics) => {
let rustdoc_ty = clean_ty(hir_ty, cx);
let ty = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
TypedefItem(Box::new(Typedef {
type_: rustdoc_ty,
- generics: generics.clean(cx),
+ generics: clean_generics(generics, cx),
item_type: Some(ty),
}))
}
ItemKind::Enum(ref def, generics) => EnumItem(Enum {
- variants: def.variants.iter().map(|v| v.clean(cx)).collect(),
- generics: generics.clean(cx),
+ variants: def.variants.iter().map(|v| clean_variant(v, cx)).collect(),
+ generics: clean_generics(generics, cx),
}),
ItemKind::TraitAlias(generics, bounds) => TraitAliasItem(TraitAlias {
- generics: generics.clean(cx),
- bounds: bounds.iter().filter_map(|x| x.clean(cx)).collect(),
+ generics: clean_generics(generics, cx),
+ bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
}),
ItemKind::Union(ref variant_data, generics) => UnionItem(Union {
- generics: generics.clean(cx),
+ generics: clean_generics(generics, cx),
fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
}),
ItemKind::Struct(ref variant_data, generics) => StructItem(Struct {
struct_type: CtorKind::from_hir(variant_data),
- generics: generics.clean(cx),
+ generics: clean_generics(generics, cx),
fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
}),
ItemKind::Impl(impl_) => return clean_impl(impl_, item.hir_id(), cx),
@@ -1946,15 +1948,17 @@ fn clean_maybe_renamed_item<'tcx>(
})
}
ItemKind::Trait(_, _, generics, bounds, item_ids) => {
- let items =
- item_ids.iter().map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx)).collect();
+ let items = item_ids
+ .iter()
+ .map(|ti| clean_trait_item(cx.tcx.hir().trait_item(ti.id), cx))
+ .collect();
- TraitItem(Trait {
+ TraitItem(Box::new(Trait {
def_id,
items,
- generics: generics.clean(cx),
- bounds: bounds.iter().filter_map(|x| x.clean(cx)).collect(),
- })
+ generics: clean_generics(generics, cx),
+ bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
+ }))
}
ItemKind::ExternCrate(orig_name) => {
return clean_extern_crate(item, name, orig_name, cx);
@@ -1969,14 +1973,12 @@ fn clean_maybe_renamed_item<'tcx>(
})
}
-impl<'tcx> Clean<'tcx, Item> for hir::Variant<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
- let kind = VariantItem(clean_variant_data(&self.data, cx));
- let what_rustc_thinks =
- Item::from_hir_id_and_parts(self.id, Some(self.ident.name), kind, cx);
- // don't show `pub` for variants, which are always public
- Item { visibility: Inherited, ..what_rustc_thinks }
- }
+fn clean_variant<'tcx>(variant: &hir::Variant<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
+ let kind = VariantItem(clean_variant_data(&variant.data, &variant.disr_expr, cx));
+ let what_rustc_thinks =
+ Item::from_hir_id_and_parts(variant.id, Some(variant.ident.name), kind, cx);
+ // don't show `pub` for variants, which are always public
+ Item { visibility: Inherited, ..what_rustc_thinks }
}
fn clean_impl<'tcx>(
@@ -1987,8 +1989,11 @@ fn clean_impl<'tcx>(
let tcx = cx.tcx;
let mut ret = Vec::new();
let trait_ = impl_.of_trait.as_ref().map(|t| clean_trait_ref(t, cx));
- let items =
- impl_.items.iter().map(|ii| tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>();
+ let items = impl_
+ .items
+ .iter()
+ .map(|ii| clean_impl_item(tcx.hir().impl_item(ii.id), cx))
+ .collect::<Vec<_>>();
let def_id = tcx.hir().local_def_id(hir_id);
// If this impl block is an implementation of the Deref trait, then we
@@ -2005,7 +2010,7 @@ fn clean_impl<'tcx>(
let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
let kind = ImplItem(Box::new(Impl {
unsafety: impl_.unsafety,
- generics: impl_.generics.clean(cx),
+ generics: clean_generics(impl_.generics, cx),
trait_,
for_,
items,
@@ -2106,8 +2111,8 @@ fn clean_use_statement<'tcx>(
// `pub(super)` or higher. If the current module is the top level
// module, there isn't really a parent module, which makes the results
// meaningless. In this case, we make sure the answer is `false`.
- let is_visible_from_parent_mod = visibility.is_accessible_from(parent_mod.to_def_id(), cx.tcx)
- && !current_mod.is_top_level_module();
+ let is_visible_from_parent_mod =
+ visibility.is_accessible_from(parent_mod, cx.tcx) && !current_mod.is_top_level_module();
if pub_underscore {
if let Some(ref inline) = inline_attr {
@@ -2202,7 +2207,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
hir::ForeignItemKind::Fn(decl, names, generics) => {
let (generics, decl) = enter_impl_trait(cx, |cx| {
// NOTE: generics must be cleaned before args
- let generics = generics.clean(cx);
+ let generics = clean_generics(generics, cx);
let args = clean_args_from_types_and_names(cx, decl.inputs, names);
let decl = clean_fn_decl_with_args(cx, decl, args);
(generics, decl)
@@ -2229,13 +2234,16 @@ fn clean_type_binding<'tcx>(
cx: &mut DocContext<'tcx>,
) -> TypeBinding {
TypeBinding {
- assoc: PathSegment { name: type_binding.ident.name, args: type_binding.gen_args.clean(cx) },
+ assoc: PathSegment {
+ name: type_binding.ident.name,
+ args: clean_generic_args(type_binding.gen_args, cx),
+ },
kind: match type_binding.kind {
hir::TypeBindingKind::Equality { ref term } => {
TypeBindingKind::Equality { term: clean_hir_term(term, cx) }
}
hir::TypeBindingKind::Constraint { bounds } => TypeBindingKind::Constraint {
- bounds: bounds.iter().filter_map(|b| b.clean(cx)).collect(),
+ bounds: bounds.iter().filter_map(|b| clean_generic_bound(b, cx)).collect(),
},
},
}
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 0e6de842c..f973fd088 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -8,6 +8,7 @@ use std::sync::OnceLock as OnceCell;
use std::{cmp, fmt, iter};
use arrayvec::ArrayVec;
+use thin_vec::ThinVec;
use rustc_ast::attr;
use rustc_ast::util::comments::beautify_doc_string;
@@ -15,7 +16,6 @@ use rustc_ast::{self as ast, AttrStyle};
use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
use rustc_const_eval::const_eval::is_unstable_const_fn;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::thin_vec::ThinVec;
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
@@ -415,29 +415,28 @@ impl Item {
.unwrap_or(false)
}
- pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Span {
+ pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option<Span> {
let kind = match &*self.kind {
ItemKind::StrippedItem(k) => k,
_ => &*self.kind,
};
match kind {
- ItemKind::ModuleItem(Module { span, .. }) => *span,
- ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => Span::dummy(),
+ ItemKind::ModuleItem(Module { span, .. }) => Some(*span),
+ ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => None,
ItemKind::ImplItem(box Impl { kind: ImplKind::Blanket(_), .. }) => {
if let ItemId::Blanket { impl_id, .. } = self.item_id {
- rustc_span(impl_id, tcx)
+ Some(rustc_span(impl_id, tcx))
} else {
panic!("blanket impl item has non-blanket ID")
}
}
- _ => {
- self.item_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy)
- }
+ _ => self.item_id.as_def_id().map(|did| rustc_span(did, tcx)),
}
}
pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
- crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span(tcx).inner())
+ crate::passes::span_of_attrs(&self.attrs)
+ .unwrap_or_else(|| self.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner()))
}
/// Finds the `doc` attribute as a NameValue and returns the corresponding
@@ -483,7 +482,7 @@ impl Item {
cx: &mut DocContext<'_>,
cfg: Option<Arc<Cfg>>,
) -> Item {
- trace!("name={:?}, def_id={:?}", name, def_id);
+ trace!("name={:?}, def_id={:?} cfg={:?}", name, def_id, cfg);
// Primitives and Keywords are written in the source code as private modules.
// The modules need to be private so that nobody actually uses them, but the
@@ -511,7 +510,7 @@ impl Item {
.get(&self.item_id)
.map_or(&[][..], |v| v.as_slice())
.iter()
- .filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
+ .filter_map(|ItemLink { link: s, link_text, page_id: did, ref fragment }| {
debug!(?did);
if let Ok((mut href, ..)) = href(*did, cx) {
debug!(?href);
@@ -728,7 +727,7 @@ pub(crate) enum ItemKind {
OpaqueTyItem(OpaqueTy),
StaticItem(Static),
ConstantItem(Constant),
- TraitItem(Trait),
+ TraitItem(Box<Trait>),
TraitAliasItem(TraitAlias),
ImplItem(Box<Impl>),
/// A required method in a trait declaration meaning it's only a function signature.
@@ -802,6 +801,31 @@ impl ItemKind {
| KeywordItem => [].iter(),
}
}
+
+ /// Returns `true` if this item does not appear inside an impl block.
+ pub(crate) fn is_non_assoc(&self) -> bool {
+ matches!(
+ self,
+ StructItem(_)
+ | UnionItem(_)
+ | EnumItem(_)
+ | TraitItem(_)
+ | ModuleItem(_)
+ | ExternCrateItem { .. }
+ | FunctionItem(_)
+ | TypedefItem(_)
+ | OpaqueTyItem(_)
+ | StaticItem(_)
+ | ConstantItem(_)
+ | TraitAliasItem(_)
+ | ForeignFunctionItem(_)
+ | ForeignStaticItem(_)
+ | ForeignTypeItem
+ | MacroItem(_)
+ | ProcMacroItem(_)
+ | PrimitiveItem(_)
+ )
+ }
}
#[derive(Clone, Debug)]
@@ -821,8 +845,6 @@ pub(crate) trait AttributesExt {
fn inner_docs(&self) -> bool;
- fn other_attrs(&self) -> Vec<ast::Attribute>;
-
fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>>;
}
@@ -849,10 +871,6 @@ impl AttributesExt for [ast::Attribute] {
self.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == AttrStyle::Inner)
}
- fn other_attrs(&self) -> Vec<ast::Attribute> {
- self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect()
- }
-
fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
let sess = tcx.sess;
let doc_cfg_active = tcx.features().doc_cfg;
@@ -1116,7 +1134,10 @@ pub(crate) struct ItemLink {
/// This may not be the same as `link` if there was a disambiguator
/// in an intra-doc link (e.g. \[`fn@f`\])
pub(crate) link_text: String,
- pub(crate) did: DefId,
+ /// The `DefId` of the Item whose **HTML Page** contains the item being
+ /// linked to. This will be different to `item_id` on item's that don't
+ /// have their own page, such as struct fields and enum variants.
+ pub(crate) page_id: DefId,
/// The url fragment to append to the link
pub(crate) fragment: Option<UrlFragment>,
}
@@ -1137,7 +1158,7 @@ pub struct RenderedLink {
#[derive(Clone, Debug, Default)]
pub(crate) struct Attributes {
pub(crate) doc_strings: Vec<DocFragment>,
- pub(crate) other_attrs: Vec<ast::Attribute>,
+ pub(crate) other_attrs: ast::AttrVec,
}
impl Attributes {
@@ -1180,7 +1201,7 @@ impl Attributes {
doc_only: bool,
) -> Attributes {
let mut doc_strings = Vec::new();
- let mut other_attrs = Vec::new();
+ let mut other_attrs = ast::AttrVec::new();
for (attr, parent_module) in attrs {
if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
trace!("got doc_str={doc_str:?}");
@@ -1285,7 +1306,7 @@ impl GenericBound {
pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
let did = cx.tcx.require_lang_item(LangItem::Sized, None);
let empty = cx.tcx.intern_substs(&[]);
- let path = external_path(cx, did, false, vec![], empty);
+ let path = external_path(cx, did, false, ThinVec::new(), empty);
inline::record_extern_fqn(cx, did, ItemType::Trait);
GenericBound::TraitBound(
PolyTrait { trait_: path, generic_params: Vec::new() },
@@ -1557,13 +1578,7 @@ pub(crate) enum Type {
BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: Box<Type> },
/// A qualified path to an associated item: `<Type as Trait>::Name`
- QPath {
- assoc: Box<PathSegment>,
- self_type: Box<Type>,
- /// FIXME: compute this field on demand.
- should_show_cast: bool,
- trait_: Path,
- },
+ QPath(Box<QPathData>),
/// A type that is inferred: `_`
Infer,
@@ -1661,8 +1676,8 @@ impl Type {
}
pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
- if let QPath { self_type, trait_, assoc, .. } = self {
- Some((self_type, trait_.def_id(), *assoc.clone()))
+ if let QPath(box QPathData { self_type, trait_, assoc, .. }) = self {
+ Some((self_type, trait_.def_id(), assoc.clone()))
} else {
None
}
@@ -1686,7 +1701,7 @@ impl Type {
Slice(..) => PrimitiveType::Slice,
Array(..) => PrimitiveType::Array,
RawPointer(..) => PrimitiveType::RawPointer,
- QPath { ref self_type, .. } => return self_type.inner_def_id(cache),
+ QPath(box QPathData { ref self_type, .. }) => return self_type.inner_def_id(cache),
Generic(_) | Infer | ImplTrait(_) => return None,
};
cache.and_then(|c| Primitive(t).def_id(c))
@@ -1700,6 +1715,15 @@ impl Type {
}
}
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub(crate) struct QPathData {
+ pub assoc: PathSegment,
+ pub self_type: Type,
+ /// FIXME: compute this field on demand.
+ pub should_show_cast: bool,
+ pub trait_: Path,
+}
+
/// A primitive (aka, builtin) type.
///
/// This represents things like `i32`, `str`, etc.
@@ -2077,7 +2101,7 @@ impl Enum {
#[derive(Clone, Debug)]
pub(crate) enum Variant {
- CLike,
+ CLike(Option<Discriminant>),
Tuple(Vec<Item>),
Struct(VariantStruct),
}
@@ -2086,11 +2110,31 @@ impl Variant {
pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
match *self {
Self::Struct(ref struct_) => Some(struct_.has_stripped_entries()),
- Self::CLike | Self::Tuple(_) => None,
+ Self::CLike(..) | Self::Tuple(_) => None,
}
}
}
+#[derive(Clone, Debug)]
+pub(crate) struct Discriminant {
+ // In the case of cross crate re-exports, we don't have the nessesary information
+ // to reconstruct the expression of the discriminant, only the value.
+ pub(super) expr: Option<BodyId>,
+ pub(super) value: DefId,
+}
+
+impl Discriminant {
+ /// Will be `None` in the case of cross-crate reexports, and may be
+ /// simplified
+ pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
+ self.expr.map(|body| print_const_expr(tcx, body))
+ }
+ /// Will always be a machine readable number, without underscores or suffixes.
+ pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> String {
+ print_evaluated_const(tcx, self.value, false).unwrap()
+ }
+}
+
/// Small wrapper around [`rustc_span::Span`] that adds helper methods
/// and enforces calling [`rustc_span::Span::source_callsite()`].
#[derive(Copy, Clone, Debug)]
@@ -2109,14 +2153,6 @@ impl Span {
self.0
}
- pub(crate) fn dummy() -> Self {
- Self(rustc_span::DUMMY_SP)
- }
-
- pub(crate) fn is_dummy(&self) -> bool {
- self.0.is_dummy()
- }
-
pub(crate) fn filename(&self, sess: &Session) -> FileName {
sess.source_map().span_to_filename(self.0)
}
@@ -2325,7 +2361,7 @@ impl ConstantKind {
match *self {
ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
- print_evaluated_const(tcx, def_id)
+ print_evaluated_const(tcx, def_id, true)
}
}
}
@@ -2495,14 +2531,16 @@ impl SubstParam {
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
mod size_asserts {
use super::*;
+ use rustc_data_structures::static_assert_size;
// These are in alphabetical order, which is easy to maintain.
- rustc_data_structures::static_assert_size!(Crate, 72); // frequently moved by-value
- rustc_data_structures::static_assert_size!(DocFragment, 32);
- rustc_data_structures::static_assert_size!(GenericArg, 80);
- rustc_data_structures::static_assert_size!(GenericArgs, 32);
- rustc_data_structures::static_assert_size!(GenericParamDef, 56);
- rustc_data_structures::static_assert_size!(Item, 56);
- rustc_data_structures::static_assert_size!(ItemKind, 112);
- rustc_data_structures::static_assert_size!(PathSegment, 40);
- rustc_data_structures::static_assert_size!(Type, 72);
+ static_assert_size!(Crate, 72); // frequently moved by-value
+ static_assert_size!(DocFragment, 32);
+ #[cfg(not(bootstrap))]
+ static_assert_size!(GenericArg, 56);
+ static_assert_size!(GenericArgs, 32);
+ static_assert_size!(GenericParamDef, 56);
+ static_assert_size!(Item, 56);
+ static_assert_size!(ItemKind, 96);
+ static_assert_size!(PathSegment, 40);
+ static_assert_size!(Type, 56);
}
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 43e71e90a..3eaedaf10 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -2,9 +2,9 @@ use crate::clean::auto_trait::AutoTraitFinder;
use crate::clean::blanket_impl::BlanketImplFinder;
use crate::clean::render_macro_matchers::render_macro_matcher;
use crate::clean::{
- clean_middle_const, clean_middle_region, clean_middle_ty, inline, Clean, Crate, ExternalCrate,
- Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime, Path, PathSegment,
- Primitive, PrimitiveType, Type, TypeBinding, Visibility,
+ clean_doc_module, clean_middle_const, clean_middle_region, clean_middle_ty, inline, Crate,
+ ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime, Path,
+ PathSegment, Primitive, PrimitiveType, Type, TypeBinding, Visibility,
};
use crate::core::DocContext;
use crate::formats::item_type::ItemType;
@@ -12,7 +12,6 @@ use crate::visit_lib::LibEmbargoVisitor;
use rustc_ast as ast;
use rustc_ast::tokenstream::TokenTree;
-use rustc_data_structures::thin_vec::ThinVec;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
@@ -23,6 +22,7 @@ use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_span::symbol::{kw, sym, Symbol};
use std::fmt::Write as _;
use std::mem;
+use thin_vec::ThinVec;
#[cfg(test)]
mod tests;
@@ -37,7 +37,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
// Clean the crate, translating the entire librustc_ast AST to one that is
// understood by rustdoc.
- let mut module = module.clean(cx);
+ let mut module = clean_doc_module(&module, cx);
match *module.kind {
ItemKind::ModuleItem(ref module) => {
@@ -102,7 +102,7 @@ fn external_generic_args<'tcx>(
cx: &mut DocContext<'tcx>,
did: DefId,
has_self: bool,
- bindings: Vec<TypeBinding>,
+ bindings: ThinVec<TypeBinding>,
substs: SubstsRef<'tcx>,
) -> GenericArgs {
let args = substs_to_args(cx, substs, has_self);
@@ -112,7 +112,7 @@ fn external_generic_args<'tcx>(
// The trait's first substitution is the one after self, if there is one.
match substs.iter().nth(if has_self { 1 } else { 0 }).unwrap().expect_ty().kind() {
ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(t, cx, None)).collect::<Vec<_>>().into(),
- _ => return GenericArgs::AngleBracketed { args: args.into(), bindings: bindings.into() },
+ _ => return GenericArgs::AngleBracketed { args: args.into(), bindings },
};
let output = None;
// FIXME(#20299) return type comes from a projection now
@@ -130,7 +130,7 @@ pub(super) fn external_path<'tcx>(
cx: &mut DocContext<'tcx>,
did: DefId,
has_self: bool,
- bindings: Vec<TypeBinding>,
+ bindings: ThinVec<TypeBinding>,
substs: SubstsRef<'tcx>,
) -> Path {
let def_kind = cx.tcx.def_kind(did);
@@ -235,14 +235,13 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
match n.kind() {
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => {
- let mut s = if let Some(def) = def.as_local() {
+ assert_eq!(promoted, ());
+ let s = if let Some(def) = def.as_local() {
print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def.did))
} else {
inline::print_inlined_const(cx.tcx, def.did)
};
- if let Some(promoted) = promoted {
- s.push_str(&format!("::{:?}", promoted))
- }
+
s
}
_ => {
@@ -261,7 +260,11 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
}
}
-pub(crate) fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<String> {
+pub(crate) fn print_evaluated_const(
+ tcx: TyCtxt<'_>,
+ def_id: DefId,
+ underscores_and_type: bool,
+) -> Option<String> {
tcx.const_eval_poly(def_id).ok().and_then(|val| {
let ty = tcx.type_of(def_id);
match (val, ty.kind()) {
@@ -269,7 +272,7 @@ pub(crate) fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<St
(ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
(ConstValue::Scalar(_), _) => {
let const_ = mir::ConstantKind::from_value(val, ty);
- Some(print_const_with_custom_print_scalar(tcx, const_))
+ Some(print_const_with_custom_print_scalar(tcx, const_, underscores_and_type))
}
_ => None,
}
@@ -302,23 +305,35 @@ fn format_integer_with_underscore_sep(num: &str) -> String {
.collect()
}
-fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: mir::ConstantKind<'_>) -> String {
+fn print_const_with_custom_print_scalar(
+ tcx: TyCtxt<'_>,
+ ct: mir::ConstantKind<'_>,
+ underscores_and_type: bool,
+) -> String {
// Use a slightly different format for integer types which always shows the actual value.
// For all other types, fallback to the original `pretty_print_const`.
match (ct, ct.ty().kind()) {
(mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Uint(ui)) => {
- format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
+ if underscores_and_type {
+ format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
+ } else {
+ int.to_string()
+ }
}
(mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Int(i)) => {
let ty = tcx.lift(ct.ty()).unwrap();
let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
let data = int.assert_bits(size);
let sign_extended_data = size.sign_extend(data) as i128;
- format!(
- "{}{}",
- format_integer_with_underscore_sep(&sign_extended_data.to_string()),
- i.name_str()
- )
+ if underscores_and_type {
+ format!(
+ "{}{}",
+ format_integer_with_underscore_sep(&sign_extended_data.to_string()),
+ i.name_str()
+ )
+ } else {
+ sign_extended_data.to_string()
+ }
}
_ => ct.to_string(),
}
@@ -475,30 +490,14 @@ pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId {
use DefKind::*;
debug!("register_res({:?})", res);
- let (did, kind) = match res {
- // These should be added to the cache using `record_extern_fqn`.
+ let (kind, did) = match res {
Res::Def(
kind @ (AssocTy | AssocFn | AssocConst | Variant | Fn | TyAlias | Enum | Trait | Struct
| Union | Mod | ForeignTy | Const | Static(_) | Macro(..) | TraitAlias),
- i,
- ) => (i, kind.into()),
- // This is part of a trait definition or trait impl; document the trait.
- Res::SelfTy { trait_: Some(trait_def_id), alias_to: _ } => (trait_def_id, ItemType::Trait),
- // This is an inherent impl or a type definition; it doesn't have its own page.
- Res::SelfTy { trait_: None, alias_to: Some((item_def_id, _)) } => return item_def_id,
- Res::SelfTy { trait_: None, alias_to: None }
- | Res::PrimTy(_)
- | Res::ToolMod
- | Res::SelfCtor(_)
- | Res::Local(_)
- | Res::NonMacroAttr(_)
- | Res::Err => return res.def_id(),
- Res::Def(
- TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst
- | InlineConst | OpaqueTy | Field | LifetimeParam | GlobalAsm | Impl | Closure
- | Generator,
- id,
- ) => return id,
+ did,
+ ) => (kind.into(), did),
+
+ _ => panic!("register_res: unexpected {:?}", res),
};
if did.is_local() {
return did;