From 4aee911ce41d6ae7a41b74ca83c21bf7f4d2f3d9 Mon Sep 17 00:00:00 2001
From: Lukas Wirth <lukastw97@gmail.com>
Date: Tue, 14 Feb 2023 17:37:20 +0100
Subject: [PATCH] Slim down GenericArgs by one usize once more

---
 crates/hir-def/src/path.rs       |  4 ++--
 crates/hir-def/src/path/lower.rs | 33 +++++++++++++++++++++-----------
 crates/hir-def/src/type_ref.rs   |  2 +-
 crates/hir-ty/src/display.rs     |  2 +-
 4 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/crates/hir-def/src/path.rs b/crates/hir-def/src/path.rs
index 0ebc5c9562a..36d4c36a268 100644
--- a/crates/hir-def/src/path.rs
+++ b/crates/hir-def/src/path.rs
@@ -49,7 +49,7 @@ pub struct Path {
 /// also includes bindings of associated types, like in `Iterator<Item = Foo>`.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct GenericArgs {
-    pub args: Vec<GenericArg>,
+    pub args: Box<[GenericArg]>,
     /// This specifies whether the args contain a Self type as the first
     /// element. This is the case for path segments like `<T as Trait>`, where
     /// `T` is actually a type parameter for the path `Trait` specifying the
@@ -212,7 +212,7 @@ impl GenericArgs {
 
     pub(crate) fn empty() -> GenericArgs {
         GenericArgs {
-            args: Vec::new(),
+            args: Box::default(),
             has_self_type: false,
             bindings: Box::default(),
             desugared_from_fn: false,
diff --git a/crates/hir-def/src/path/lower.rs b/crates/hir-def/src/path/lower.rs
index e82f6b786d0..c85a11db6d1 100644
--- a/crates/hir-def/src/path/lower.rs
+++ b/crates/hir-def/src/path/lower.rs
@@ -1,5 +1,7 @@
 //! Transforms syntax into `Path` objects, ideally with accounting for hygiene
 
+use std::iter;
+
 use crate::type_ref::ConstScalarOrPath;
 
 use either::Either;
@@ -86,15 +88,26 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx<'_>) -> Option<Path
                             generic_args.resize(segments.len(), None);
                         }
 
+                        let self_type = GenericArg::Type(self_type);
+
                         // Insert the type reference (T in the above example) as Self parameter for the trait
                         let last_segment = generic_args.get_mut(segments.len() - num_segments)?;
-                        let mut args_inner = match last_segment {
-                            Some(it) => it.as_ref().clone(),
-                            None => GenericArgs::empty(),
-                        };
-                        args_inner.has_self_type = true;
-                        args_inner.args.insert(0, GenericArg::Type(self_type));
-                        *last_segment = Some(Interned::new(args_inner));
+                        *last_segment = Some(Interned::new(match last_segment.take() {
+                            Some(it) => GenericArgs {
+                                args: iter::once(self_type)
+                                    .chain(it.args.iter().cloned())
+                                    .collect(),
+
+                                has_self_type: true,
+                                bindings: it.bindings.clone(),
+                                desugared_from_fn: it.desugared_from_fn,
+                            },
+                            None => GenericArgs {
+                                args: Box::new([self_type]),
+                                has_self_type: true,
+                                ..GenericArgs::empty()
+                            },
+                        }));
                     }
                 }
             }
@@ -209,7 +222,7 @@ pub(super) fn lower_generic_args(
         return None;
     }
     Some(GenericArgs {
-        args,
+        args: args.into_boxed_slice(),
         has_self_type: false,
         bindings: bindings.into_boxed_slice(),
         desugared_from_fn: false,
@@ -223,15 +236,13 @@ fn lower_generic_args_from_fn_path(
     params: Option<ast::ParamList>,
     ret_type: Option<ast::RetType>,
 ) -> Option<GenericArgs> {
-    let mut args = Vec::new();
     let params = params?;
     let mut param_types = Vec::new();
     for param in params.params() {
         let type_ref = TypeRef::from_ast_opt(ctx, param.ty());
         param_types.push(type_ref);
     }
-    let arg = GenericArg::Type(TypeRef::Tuple(param_types));
-    args.push(arg);
+    let args = Box::new([GenericArg::Type(TypeRef::Tuple(param_types))]);
     let bindings = if let Some(ret_type) = ret_type {
         let type_ref = TypeRef::from_ast_opt(ctx, ret_type.ty());
         Box::new([AssociatedTypeBinding {
diff --git a/crates/hir-def/src/type_ref.rs b/crates/hir-def/src/type_ref.rs
index 7f3c3154807..9652b01b91b 100644
--- a/crates/hir-def/src/type_ref.rs
+++ b/crates/hir-def/src/type_ref.rs
@@ -292,7 +292,7 @@ impl TypeRef {
             }
             for segment in path.segments().iter() {
                 if let Some(args_and_bindings) = segment.args_and_bindings {
-                    for arg in &args_and_bindings.args {
+                    for arg in args_and_bindings.args.iter() {
                         match arg {
                             crate::path::GenericArg::Type(type_ref) => {
                                 go(type_ref, f);
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 3390c7b1e56..b22064d8c42 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -1419,7 +1419,7 @@ impl HirDisplay for Path {
 
                 write!(f, "<")?;
                 let mut first = true;
-                for arg in &generic_args.args {
+                for arg in generic_args.args.iter() {
                     if first {
                         first = false;
                         if generic_args.has_self_type {