about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNoah Lev <camelidcamel@gmail.com>2021-08-22 21:35:01 -0700
committerNoah Lev <camelidcamel@gmail.com>2021-08-31 20:32:17 -0700
commit2d1240e6f7709d06caddc396f689ba0bc77f80a3 (patch)
tree12c26b83912898d125c49c656cdc6a91a770fde8
parent5d6804469d80aaf26f98090ae016af45e267f58f (diff)
downloadrust-2d1240e6f7709d06caddc396f689ba0bc77f80a3.tar.gz
rust-2d1240e6f7709d06caddc396f689ba0bc77f80a3.zip
Box `GenericArgs::Parenthesized.output`
This reduces the size of `GenericArgs` from 104 bytes to 56 bytes,
essentially reducing it by half.

`GenericArgs` is one of the fields of `PathSegment`, so this should
reduce the amount of memory allocated for `PathSegment`s in the cases
where the generics are not for a `Fn`, `FnMut`, or `FnOnce` trait.

I also added `static_assert_size!`s to `GenericArgs` and `PathSegment`
to ensure they don't increase in size unexpectedly.
-rw-r--r--src/librustdoc/clean/auto_trait.rs6
-rw-r--r--src/librustdoc/clean/mod.rs7
-rw-r--r--src/librustdoc/clean/simplify.rs4
-rw-r--r--src/librustdoc/clean/types.rs12
-rw-r--r--src/librustdoc/json/conversions.rs2
5 files changed, 21 insertions, 10 deletions
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 8ad09a9edc0..f98059b1a74 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -350,8 +350,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
             .into_iter()
             .flat_map(|(ty, mut bounds)| {
                 if let Some(data) = ty_to_fn.get(&ty) {
-                    let (poly_trait, output) =
-                        (data.0.as_ref().expect("as_ref failed").clone(), data.1.as_ref().cloned());
+                    let (poly_trait, output) = (
+                        data.0.as_ref().expect("as_ref failed").clone(),
+                        data.1.as_ref().cloned().map(Box::new),
+                    );
                     let new_ty = match poly_trait.trait_ {
                         Type::ResolvedPath { ref path, ref did, ref is_generic } => {
                             let mut new_path = path.clone();
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 640acffb114..b866455e51b 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1763,10 +1763,9 @@ impl Clean<GenericArgs> for hir::GenericArgs<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> GenericArgs {
         if self.parenthesized {
             let output = self.bindings[0].ty().clean(cx);
-            GenericArgs::Parenthesized {
-                inputs: self.inputs().clean(cx),
-                output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None },
-            }
+            let output =
+                if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None };
+            GenericArgs::Parenthesized { inputs: self.inputs().clean(cx), output }
         } else {
             GenericArgs::AngleBracketed {
                 args: self
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index c0d52d34928..d139b19f5dc 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -116,10 +116,10 @@ crate fn merge_bounds(
                 });
             }
             PP::Parenthesized { ref mut output, .. } => match output {
-                Some(o) => assert_eq!(o, rhs),
+                Some(o) => assert_eq!(o.as_ref(), rhs),
                 None => {
                     if *rhs != clean::Type::Tuple(Vec::new()) {
-                        *output = Some(rhs.clone());
+                        *output = Some(Box::new(rhs.clone()));
                     }
                 }
             },
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 70255749143..1cbcf621eb6 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -2018,15 +2018,25 @@ crate enum GenericArg {
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 crate enum GenericArgs {
     AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
-    Parenthesized { inputs: Vec<Type>, output: Option<Type> },
+    Parenthesized { inputs: Vec<Type>, output: Option<Box<Type>> },
 }
 
+// `GenericArgs` is in every `PathSegment`, so its size can significantly
+// affect rustdoc's memory usage.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(GenericArgs, 56);
+
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 crate struct PathSegment {
     crate name: Symbol,
     crate args: GenericArgs,
 }
 
+// `PathSegment` usually occurs multiple times in every `Path`, so its size can
+// significantly affect rustdoc's memory usage.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(PathSegment, 64);
+
 #[derive(Clone, Debug)]
 crate struct Typedef {
     crate type_: Type,
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index f3eeea6c6ae..da6428a58cb 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -127,7 +127,7 @@ impl FromWithTcx<clean::GenericArgs> for GenericArgs {
             },
             Parenthesized { inputs, output } => GenericArgs::Parenthesized {
                 inputs: inputs.into_iter().map(|a| a.into_tcx(tcx)).collect(),
-                output: output.map(|a| a.into_tcx(tcx)),
+                output: output.map(|a| (*a).into_tcx(tcx)),
             },
         }
     }