From 2aa4aa70ddd11ebc56667dbb3907c93a5a0176c2 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 16 Aug 2022 12:48:04 -0700 Subject: [PATCH 1/2] rustdoc: factor Type::QPath out into its own box This reduces the size of Type. --- src/librustdoc/clean/auto_trait.rs | 12 +++++++----- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 31 ++++++++++++++---------------- src/librustdoc/clean/types.rs | 27 ++++++++++++++------------ src/librustdoc/html/format.rs | 7 ++++++- src/librustdoc/html/render/mod.rs | 4 ++-- src/librustdoc/json/conversions.rs | 4 ++-- 7 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index a94520b121926..5441a7bd29ec0 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -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' 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/inline.rs b/src/librustdoc/clean/inline.rs index e56a715e85780..bd5dfa4947b4b 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -672,7 +672,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 971617a840036..5e34134597fa9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -410,12 +410,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, trait_: &Path, self_type: &Type) -> bool { @@ -1182,7 +1182,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( .where_predicates .drain_filter(|pred| match *pred { 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 { @@ -1191,7 +1191,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( if trait_.def_id() != assoc_item.container_id(tcx) { return false; } - match **self_type { + match *self_type { Generic(ref s) if *s == kw::SelfUpper => {} _ => 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_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(clean_path_segment( - p.segments.last().expect("segments were empty"), - 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); @@ -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_type = clean_ty(qself, cx); let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type); - Type::QPath { - assoc: Box::new(clean_path_segment(segment, 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"), } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 1a4786c9b0664..7bbd2b19f2e0d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1556,13 +1556,7 @@ pub(crate) enum Type { BorrowedRef { lifetime: Option, mutability: Mutability, type_: Box }, /// A qualified path to an associated item: `::Name` - QPath { - assoc: Box, - self_type: Box, - /// FIXME: compute this field on demand. - should_show_cast: bool, - trait_: Path, - }, + QPath(Box), /// A type that is inferred: `_` Infer, @@ -1660,8 +1654,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 } @@ -1685,7 +1679,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)) @@ -1699,6 +1693,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. @@ -2490,11 +2493,11 @@ mod size_asserts { // These are in alphabetical order, which is easy to maintain. static_assert_size!(Crate, 72); // frequently moved by-value static_assert_size!(DocFragment, 32); - static_assert_size!(GenericArg, 80); + static_assert_size!(GenericArg, 64); static_assert_size!(GenericArgs, 32); static_assert_size!(GenericParamDef, 56); static_assert_size!(Item, 56); static_assert_size!(ItemKind, 112); static_assert_size!(PathSegment, 40); - static_assert_size!(Type, 72); + static_assert_size!(Type, 56); } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 3dee4d1acc819..b023792e95a58 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1079,7 +1079,12 @@ fn fmt_type<'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 should_show_cast { write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))? diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 5ed5299e09bc0..1ac5186f9f6a8 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2623,8 +2623,8 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { clean::Type::BorrowedRef { type_, .. } => { work.push_back(*type_); } - clean::Type::QPath { self_type, trait_, .. } => { - work.push_back(*self_type); + clean::Type::QPath(box clean::QPathData { self_type, trait_, .. }) => { + work.push_back(self_type); process_path(trait_.def_id()); } _ => {} diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 1fedb0144d1d0..6221591ca25e0 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -480,10 +480,10 @@ impl FromWithTcx for Type { mutable: mutability == ast::Mutability::Mut, 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(), 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), }, } From 238bcc940fecd89f69a305b271d06bcd9bc2ed2f Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 16 Aug 2022 13:08:54 -0700 Subject: [PATCH 2/2] rustdoc: box ItemKind::Trait This reduces the memory consumption of ItemKind. --- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 4 ++-- src/librustdoc/clean/types.rs | 4 ++-- src/librustdoc/formats/cache.rs | 2 +- src/librustdoc/json/conversions.rs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index bd5dfa4947b4b..a7048e788b65a 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -62,7 +62,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); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5e34134597fa9..5507ffb871b6e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1951,12 +1951,12 @@ fn clean_maybe_renamed_item<'tcx>( .map(|ti| clean_trait_item(cx.tcx.hir().trait_item(ti.id), cx)) .collect(); - TraitItem(Trait { + TraitItem(Box::new(Trait { def_id, items, 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); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7bbd2b19f2e0d..61cfd7ea40d71 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -727,7 +727,7 @@ pub(crate) enum ItemKind { OpaqueTyItem(OpaqueTy), StaticItem(Static), ConstantItem(Constant), - TraitItem(Trait), + TraitItem(Box), TraitAliasItem(TraitAlias), ImplItem(Box), /// A required method in a trait declaration meaning it's only a function signature. @@ -2497,7 +2497,7 @@ mod size_asserts { static_assert_size!(GenericArgs, 32); static_assert_size!(GenericParamDef, 56); static_assert_size!(Item, 56); - static_assert_size!(ItemKind, 112); + static_assert_size!(ItemKind, 96); static_assert_size!(PathSegment, 40); static_assert_size!(Type, 56); } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 2b2691e53bbcc..86392610d2c28 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -227,7 +227,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { if let clean::TraitItem(ref t) = *item.kind { self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| { clean::TraitWithExtraInfo { - trait_: t.clone(), + trait_: *t.clone(), is_notable: item.attrs.has_doc_flag(sym::notable_trait), } }); diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 6221591ca25e0..c4e8b6f5f8449 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -248,7 +248,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)), FunctionItem(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)), MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, header.unwrap(), tcx)), TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, header.unwrap(), tcx)),