Auto merge of #100645 - notriddle:notriddle/rustdoc-diet-plan, r=GuillaumeGomez
rustdoc: strategic boxing to reduce the size of ItemKind and Type The `Type` change redesigns `QPath` to box the entire data structure instead of boxing `self_type` and the `trait_`. This reduces the size of several `ItemKind` variants, leaving `Impl` as the biggest variant. The `ItemKind` change boxes that variant's payload.
This commit is contained in:
commit
650bff80a6
8 changed files with 54 additions and 47 deletions
|
@ -551,13 +551,15 @@ where
|
||||||
}
|
}
|
||||||
WherePredicate::EqPredicate { lhs, rhs } => {
|
WherePredicate::EqPredicate { lhs, rhs } => {
|
||||||
match lhs {
|
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 ty = &*self_type;
|
||||||
let mut new_trait = trait_.clone();
|
let mut new_trait = trait_.clone();
|
||||||
|
|
||||||
if self.is_fn_trait(trait_) && assoc.name == sym::Output {
|
if self.is_fn_trait(trait_) && assoc.name == sym::Output {
|
||||||
ty_to_fn
|
ty_to_fn
|
||||||
.entry(*ty.clone())
|
.entry(ty.clone())
|
||||||
.and_modify(|e| {
|
.and_modify(|e| {
|
||||||
*e = (e.0.clone(), Some(rhs.ty().unwrap().clone()))
|
*e = (e.0.clone(), Some(rhs.ty().unwrap().clone()))
|
||||||
})
|
})
|
||||||
|
@ -582,7 +584,7 @@ where
|
||||||
// to 'T: Iterator<Item=u8>'
|
// to 'T: Iterator<Item=u8>'
|
||||||
GenericArgs::AngleBracketed { ref mut bindings, .. } => {
|
GenericArgs::AngleBracketed { ref mut bindings, .. } => {
|
||||||
bindings.push(TypeBinding {
|
bindings.push(TypeBinding {
|
||||||
assoc: *assoc.clone(),
|
assoc: assoc.clone(),
|
||||||
kind: TypeBindingKind::Equality { term: rhs },
|
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(
|
bounds.insert(GenericBound::TraitBound(
|
||||||
PolyTrait { trait_: new_trait, generic_params: Vec::new() },
|
PolyTrait { trait_: new_trait, generic_params: Vec::new() },
|
||||||
|
@ -613,7 +615,7 @@ where
|
||||||
));
|
));
|
||||||
// Avoid creating any new duplicate bounds later in the outer
|
// Avoid creating any new duplicate bounds later in the outer
|
||||||
// loop
|
// 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),
|
_ => panic!("Unexpected LHS {:?} for {:?}", lhs, item_def_id),
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ pub(crate) fn try_inline(
|
||||||
Res::Def(DefKind::Trait, did) => {
|
Res::Def(DefKind::Trait, did) => {
|
||||||
record_extern_fqn(cx, did, ItemType::Trait);
|
record_extern_fqn(cx, did, ItemType::Trait);
|
||||||
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
|
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) => {
|
Res::Def(DefKind::Fn, did) => {
|
||||||
record_extern_fqn(cx, did, ItemType::Function);
|
record_extern_fqn(cx, did, ItemType::Function);
|
||||||
|
@ -672,7 +672,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
|
||||||
|
|
||||||
g.where_predicates.retain(|pred| match pred {
|
g.where_predicates.retain(|pred| match pred {
|
||||||
clean::WherePredicate::BoundPredicate {
|
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,
|
||||||
..
|
..
|
||||||
} => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did),
|
} => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did),
|
||||||
|
|
|
@ -410,12 +410,12 @@ fn clean_projection<'tcx>(
|
||||||
self_type.def_id(&cx.cache)
|
self_type.def_id(&cx.cache)
|
||||||
};
|
};
|
||||||
let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type);
|
let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type);
|
||||||
Type::QPath {
|
Type::QPath(Box::new(QPathData {
|
||||||
assoc: Box::new(projection_to_path_segment(ty, cx)),
|
assoc: projection_to_path_segment(ty, cx),
|
||||||
should_show_cast,
|
should_show_cast,
|
||||||
self_type: Box::new(self_type),
|
self_type,
|
||||||
trait_,
|
trait_,
|
||||||
}
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_should_show_cast(self_def_id: Option<DefId>, trait_: &Path, self_type: &Type) -> bool {
|
fn compute_should_show_cast(self_def_id: Option<DefId>, trait_: &Path, self_type: &Type) -> bool {
|
||||||
|
@ -1182,7 +1182,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
|
||||||
.where_predicates
|
.where_predicates
|
||||||
.drain_filter(|pred| match *pred {
|
.drain_filter(|pred| match *pred {
|
||||||
WherePredicate::BoundPredicate {
|
WherePredicate::BoundPredicate {
|
||||||
ty: QPath { ref assoc, ref self_type, ref trait_, .. },
|
ty: QPath(box QPathData { ref assoc, ref self_type, ref trait_, .. }),
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if assoc.name != my_name {
|
if assoc.name != my_name {
|
||||||
|
@ -1191,7 +1191,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
|
||||||
if trait_.def_id() != assoc_item.container_id(tcx) {
|
if trait_.def_id() != assoc_item.container_id(tcx) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
match **self_type {
|
match *self_type {
|
||||||
Generic(ref s) if *s == kw::SelfUpper => {}
|
Generic(ref s) if *s == kw::SelfUpper => {}
|
||||||
_ => return false,
|
_ => return false,
|
||||||
}
|
}
|
||||||
|
@ -1324,15 +1324,12 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
|
||||||
let self_def_id = DefId::local(qself.hir_id.owner.local_def_index);
|
let self_def_id = DefId::local(qself.hir_id.owner.local_def_index);
|
||||||
let self_type = clean_ty(qself, cx);
|
let self_type = clean_ty(qself, cx);
|
||||||
let should_show_cast = compute_should_show_cast(Some(self_def_id), &trait_, &self_type);
|
let should_show_cast = compute_should_show_cast(Some(self_def_id), &trait_, &self_type);
|
||||||
Type::QPath {
|
Type::QPath(Box::new(QPathData {
|
||||||
assoc: Box::new(clean_path_segment(
|
assoc: clean_path_segment(p.segments.last().expect("segments were empty"), cx),
|
||||||
p.segments.last().expect("segments were empty"),
|
|
||||||
cx,
|
|
||||||
)),
|
|
||||||
should_show_cast,
|
should_show_cast,
|
||||||
self_type: Box::new(self_type),
|
self_type,
|
||||||
trait_,
|
trait_,
|
||||||
}
|
}))
|
||||||
}
|
}
|
||||||
hir::QPath::TypeRelative(qself, segment) => {
|
hir::QPath::TypeRelative(qself, segment) => {
|
||||||
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
|
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
|
||||||
|
@ -1347,12 +1344,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_def_id = res.opt_def_id();
|
||||||
let self_type = clean_ty(qself, cx);
|
let self_type = clean_ty(qself, cx);
|
||||||
let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type);
|
let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type);
|
||||||
Type::QPath {
|
Type::QPath(Box::new(QPathData {
|
||||||
assoc: Box::new(clean_path_segment(segment, cx)),
|
assoc: clean_path_segment(segment, cx),
|
||||||
should_show_cast,
|
should_show_cast,
|
||||||
self_type: Box::new(self_type),
|
self_type,
|
||||||
trait_,
|
trait_,
|
||||||
}
|
}))
|
||||||
}
|
}
|
||||||
hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"),
|
hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"),
|
||||||
}
|
}
|
||||||
|
@ -1954,12 +1951,12 @@ fn clean_maybe_renamed_item<'tcx>(
|
||||||
.map(|ti| clean_trait_item(cx.tcx.hir().trait_item(ti.id), cx))
|
.map(|ti| clean_trait_item(cx.tcx.hir().trait_item(ti.id), cx))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
TraitItem(Trait {
|
TraitItem(Box::new(Trait {
|
||||||
def_id,
|
def_id,
|
||||||
items,
|
items,
|
||||||
generics: clean_generics(generics, cx),
|
generics: clean_generics(generics, cx),
|
||||||
bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
|
bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
ItemKind::ExternCrate(orig_name) => {
|
ItemKind::ExternCrate(orig_name) => {
|
||||||
return clean_extern_crate(item, name, orig_name, cx);
|
return clean_extern_crate(item, name, orig_name, cx);
|
||||||
|
|
|
@ -727,7 +727,7 @@ pub(crate) enum ItemKind {
|
||||||
OpaqueTyItem(OpaqueTy),
|
OpaqueTyItem(OpaqueTy),
|
||||||
StaticItem(Static),
|
StaticItem(Static),
|
||||||
ConstantItem(Constant),
|
ConstantItem(Constant),
|
||||||
TraitItem(Trait),
|
TraitItem(Box<Trait>),
|
||||||
TraitAliasItem(TraitAlias),
|
TraitAliasItem(TraitAlias),
|
||||||
ImplItem(Box<Impl>),
|
ImplItem(Box<Impl>),
|
||||||
/// A required method in a trait declaration meaning it's only a function signature.
|
/// A required method in a trait declaration meaning it's only a function signature.
|
||||||
|
@ -1550,13 +1550,7 @@ pub(crate) enum Type {
|
||||||
BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: Box<Type> },
|
BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: Box<Type> },
|
||||||
|
|
||||||
/// A qualified path to an associated item: `<Type as Trait>::Name`
|
/// A qualified path to an associated item: `<Type as Trait>::Name`
|
||||||
QPath {
|
QPath(Box<QPathData>),
|
||||||
assoc: Box<PathSegment>,
|
|
||||||
self_type: Box<Type>,
|
|
||||||
/// FIXME: compute this field on demand.
|
|
||||||
should_show_cast: bool,
|
|
||||||
trait_: Path,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// A type that is inferred: `_`
|
/// A type that is inferred: `_`
|
||||||
Infer,
|
Infer,
|
||||||
|
@ -1654,8 +1648,8 @@ impl Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
|
pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
|
||||||
if let QPath { self_type, trait_, assoc, .. } = self {
|
if let QPath(box QPathData { self_type, trait_, assoc, .. }) = self {
|
||||||
Some((self_type, trait_.def_id(), *assoc.clone()))
|
Some((self_type, trait_.def_id(), assoc.clone()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -1679,7 +1673,7 @@ impl Type {
|
||||||
Slice(..) => PrimitiveType::Slice,
|
Slice(..) => PrimitiveType::Slice,
|
||||||
Array(..) => PrimitiveType::Array,
|
Array(..) => PrimitiveType::Array,
|
||||||
RawPointer(..) => PrimitiveType::RawPointer,
|
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,
|
Generic(_) | Infer | ImplTrait(_) => return None,
|
||||||
};
|
};
|
||||||
cache.and_then(|c| Primitive(t).def_id(c))
|
cache.and_then(|c| Primitive(t).def_id(c))
|
||||||
|
@ -1693,6 +1687,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.
|
/// A primitive (aka, builtin) type.
|
||||||
///
|
///
|
||||||
/// This represents things like `i32`, `str`, etc.
|
/// This represents things like `i32`, `str`, etc.
|
||||||
|
@ -2484,11 +2487,11 @@ mod size_asserts {
|
||||||
// These are in alphabetical order, which is easy to maintain.
|
// These are in alphabetical order, which is easy to maintain.
|
||||||
static_assert_size!(Crate, 72); // frequently moved by-value
|
static_assert_size!(Crate, 72); // frequently moved by-value
|
||||||
static_assert_size!(DocFragment, 32);
|
static_assert_size!(DocFragment, 32);
|
||||||
static_assert_size!(GenericArg, 80);
|
static_assert_size!(GenericArg, 64);
|
||||||
static_assert_size!(GenericArgs, 32);
|
static_assert_size!(GenericArgs, 32);
|
||||||
static_assert_size!(GenericParamDef, 56);
|
static_assert_size!(GenericParamDef, 56);
|
||||||
static_assert_size!(Item, 56);
|
static_assert_size!(Item, 56);
|
||||||
static_assert_size!(ItemKind, 112);
|
static_assert_size!(ItemKind, 96);
|
||||||
static_assert_size!(PathSegment, 40);
|
static_assert_size!(PathSegment, 40);
|
||||||
static_assert_size!(Type, 72);
|
static_assert_size!(Type, 56);
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,7 +227,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||||
if let clean::TraitItem(ref t) = *item.kind {
|
if let clean::TraitItem(ref t) = *item.kind {
|
||||||
self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| {
|
self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| {
|
||||||
clean::TraitWithExtraInfo {
|
clean::TraitWithExtraInfo {
|
||||||
trait_: t.clone(),
|
trait_: *t.clone(),
|
||||||
is_notable: item.attrs.has_doc_flag(sym::notable_trait),
|
is_notable: item.attrs.has_doc_flag(sym::notable_trait),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1079,7 +1079,12 @@ fn fmt_type<'cx>(
|
||||||
write!(f, "impl {}", print_generic_bounds(bounds, cx))
|
write!(f, "impl {}", print_generic_bounds(bounds, cx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clean::QPath { ref assoc, ref self_type, ref trait_, should_show_cast } => {
|
clean::QPath(box clean::QPathData {
|
||||||
|
ref assoc,
|
||||||
|
ref self_type,
|
||||||
|
ref trait_,
|
||||||
|
should_show_cast,
|
||||||
|
}) => {
|
||||||
if f.alternate() {
|
if f.alternate() {
|
||||||
if should_show_cast {
|
if should_show_cast {
|
||||||
write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))?
|
write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))?
|
||||||
|
|
|
@ -2632,8 +2632,8 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
|
||||||
clean::Type::BorrowedRef { type_, .. } => {
|
clean::Type::BorrowedRef { type_, .. } => {
|
||||||
work.push_back(*type_);
|
work.push_back(*type_);
|
||||||
}
|
}
|
||||||
clean::Type::QPath { self_type, trait_, .. } => {
|
clean::Type::QPath(box clean::QPathData { self_type, trait_, .. }) => {
|
||||||
work.push_back(*self_type);
|
work.push_back(self_type);
|
||||||
process_path(trait_.def_id());
|
process_path(trait_.def_id());
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -248,7 +248,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
|
||||||
VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)),
|
VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)),
|
||||||
FunctionItem(f) => ItemEnum::Function(from_function(f, header.unwrap(), tcx)),
|
FunctionItem(f) => ItemEnum::Function(from_function(f, header.unwrap(), tcx)),
|
||||||
ForeignFunctionItem(f) => ItemEnum::Function(from_function(f, header.unwrap(), tcx)),
|
ForeignFunctionItem(f) => ItemEnum::Function(from_function(f, header.unwrap(), tcx)),
|
||||||
TraitItem(t) => ItemEnum::Trait(t.into_tcx(tcx)),
|
TraitItem(t) => ItemEnum::Trait((*t).into_tcx(tcx)),
|
||||||
TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)),
|
TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)),
|
||||||
MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, header.unwrap(), tcx)),
|
MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, header.unwrap(), tcx)),
|
||||||
TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, header.unwrap(), tcx)),
|
TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, header.unwrap(), tcx)),
|
||||||
|
@ -480,10 +480,10 @@ impl FromWithTcx<clean::Type> for Type {
|
||||||
mutable: mutability == ast::Mutability::Mut,
|
mutable: mutability == ast::Mutability::Mut,
|
||||||
type_: Box::new((*type_).into_tcx(tcx)),
|
type_: Box::new((*type_).into_tcx(tcx)),
|
||||||
},
|
},
|
||||||
QPath { assoc, self_type, trait_, .. } => Type::QualifiedPath {
|
QPath(box clean::QPathData { assoc, self_type, trait_, .. }) => Type::QualifiedPath {
|
||||||
name: assoc.name.to_string(),
|
name: assoc.name.to_string(),
|
||||||
args: Box::new(assoc.args.clone().into_tcx(tcx)),
|
args: Box::new(assoc.args.clone().into_tcx(tcx)),
|
||||||
self_type: Box::new((*self_type).into_tcx(tcx)),
|
self_type: Box::new(self_type.into_tcx(tcx)),
|
||||||
trait_: trait_.into_tcx(tcx),
|
trait_: trait_.into_tcx(tcx),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue