about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2024-06-21 19:09:43 +0200
committerLukas Wirth <lukastw97@gmail.com>2024-06-21 19:21:27 +0200
commit54f3f56ee8a510f42a8f482f94309b10a90d5cd2 (patch)
tree586ce70f10a7ee24fb07fef5c876569eb7d5fedc
parent2893153c340986cfc2d4dd1a267b055e2da792cc (diff)
downloadrust-54f3f56ee8a510f42a8f482f94309b10a90d5cd2.tar.gz
rust-54f3f56ee8a510f42a8f482f94309b10a90d5cd2.zip
Save allocations for empty generic_defaults query results
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/db.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs102
3 files changed, 67 insertions, 60 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
index 515fc4c668f..e951048021d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
@@ -21,12 +21,12 @@ use crate::{
     chalk_db,
     consteval::ConstEvalError,
     layout::{Layout, LayoutError},
-    lower::GenericPredicates,
+    lower::{GenericDefaults, GenericPredicates},
     method_resolution::{InherentImpls, TraitImpls, TyFingerprint},
     mir::{BorrowckResult, MirBody, MirLowerError},
-    Binders, CallableDefId, ClosureId, Const, FnDefId, GenericArg, ImplTraitId, ImplTraits,
-    InferenceResult, Interner, PolyFnSig, QuantifiedWhereClause, Substitution, TraitEnvironment,
-    TraitRef, Ty, TyDefId, ValueTyDefId,
+    Binders, CallableDefId, ClosureId, Const, FnDefId, ImplTraitId, ImplTraits, InferenceResult,
+    Interner, PolyFnSig, QuantifiedWhereClause, Substitution, TraitEnvironment, TraitRef, Ty,
+    TyDefId, ValueTyDefId,
 };
 use hir_expand::name::Name;
 
@@ -159,7 +159,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
 
     #[salsa::invoke(crate::lower::generic_defaults_query)]
     #[salsa::cycle(crate::lower::generic_defaults_recover)]
-    fn generic_defaults(&self, def: GenericDefId) -> Arc<[Binders<GenericArg>]>;
+    fn generic_defaults(&self, def: GenericDefId) -> GenericDefaults;
 
     #[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)]
     fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc<InherentImpls>;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index 685aceb2334..257d6c71fd2 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -330,18 +330,15 @@ pub(crate) fn make_single_type_binders<T: HasInterner<Interner = Interner>>(
     )
 }
 
-pub(crate) fn make_binders_with_count<T: HasInterner<Interner = Interner>>(
+pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>(
     db: &dyn HirDatabase,
-    count: usize,
     generics: &Generics,
     value: T,
 ) -> Binders<T> {
-    let it = generics.iter_id().take(count);
-
     Binders::new(
         VariableKinds::from_iter(
             Interner,
-            it.map(|x| match x {
+            generics.iter_id().map(|x| match x {
                 hir_def::GenericParamId::ConstParamId(id) => {
                     chalk_ir::VariableKind::Const(db.const_param_ty(id))
                 }
@@ -355,14 +352,6 @@ pub(crate) fn make_binders_with_count<T: HasInterner<Interner = Interner>>(
     )
 }
 
-pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>(
-    db: &dyn HirDatabase,
-    generics: &Generics,
-    value: T,
-) -> Binders<T> {
-    make_binders_with_count(db, usize::MAX, generics, value)
-}
-
 // FIXME: get rid of this, just replace it by FnPointer
 /// A function signature as seen by type inference: Several parameter types and
 /// one return type.
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index 49422443964..ac2eae03e69 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -8,7 +8,7 @@
 use std::{
     cell::{Cell, RefCell, RefMut},
     iter,
-    ops::Not as _,
+    ops::{self, Not as _},
 };
 
 use base_db::{
@@ -1693,9 +1693,11 @@ pub(crate) fn trait_environment_query(
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct GenericPredicates(Option<Arc<[Binders<QuantifiedWhereClause>]>>);
 
-impl GenericPredicates {
-    pub fn iter(&self) -> impl Iterator<Item = &Binders<QuantifiedWhereClause>> + '_ + Clone {
-        self.0.as_ref().into_iter().flat_map(Arc::as_ref)
+impl ops::Deref for GenericPredicates {
+    type Target = [Binders<crate::QuantifiedWhereClause>];
+
+    fn deref(&self) -> &Self::Target {
+        self.0.as_deref().unwrap_or(&[])
     }
 }
 
@@ -1767,68 +1769,84 @@ fn implicitly_sized_clauses<'a, 'subst: 'a>(
     })
 }
 
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct GenericDefaults(Option<Arc<[Binders<crate::GenericArg>]>>);
+
+impl ops::Deref for GenericDefaults {
+    type Target = [Binders<crate::GenericArg>];
+
+    fn deref(&self) -> &Self::Target {
+        self.0.as_deref().unwrap_or(&[])
+    }
+}
+
 /// Resolve the default type params from generics
-pub(crate) fn generic_defaults_query(
-    db: &dyn HirDatabase,
-    def: GenericDefId,
-) -> Arc<[Binders<crate::GenericArg>]> {
-    let resolver = def.resolver(db.upcast());
+pub(crate) fn generic_defaults_query(db: &dyn HirDatabase, def: GenericDefId) -> GenericDefaults {
     let generic_params = generics(db.upcast(), def);
+    if generic_params.len() == 0 {
+        return GenericDefaults(None);
+    }
+    let resolver = def.resolver(db.upcast());
     let parent_start_idx = generic_params.len_self();
 
     let ctx = TyLoweringContext::new(db, &resolver, def.into())
         .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed)
         .with_type_param_mode(ParamLoweringMode::Variable);
-    Arc::from_iter(generic_params.iter().enumerate().map(|(idx, (id, p))| {
-        match p {
-            GenericParamDataRef::TypeParamData(p) => {
-                let mut ty =
-                    p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t));
-                // Each default can only refer to previous parameters.
-                // Type variable default referring to parameter coming
-                // after it is forbidden (FIXME: report diagnostic)
-                ty = fallback_bound_vars(ty, idx, parent_start_idx);
-                crate::make_binders(db, &generic_params, ty.cast(Interner))
-            }
-            GenericParamDataRef::ConstParamData(p) => {
-                let GenericParamId::ConstParamId(id) = id else {
-                    unreachable!("Unexpected lifetime or type argument")
-                };
+    GenericDefaults(Some(Arc::from_iter(generic_params.iter().enumerate().map(
+        |(idx, (id, p))| {
+            match p {
+                GenericParamDataRef::TypeParamData(p) => {
+                    let ty = p.default.as_ref().map_or(TyKind::Error.intern(Interner), |ty| {
+                        // Each default can only refer to previous parameters.
+                        // Type variable default referring to parameter coming
+                        // after it is forbidden (FIXME: report diagnostic)
+                        fallback_bound_vars(ctx.lower_ty(ty), idx, parent_start_idx)
+                    });
+                    crate::make_binders(db, &generic_params, ty.cast(Interner))
+                }
+                GenericParamDataRef::ConstParamData(p) => {
+                    let GenericParamId::ConstParamId(id) = id else {
+                        unreachable!("Unexpected lifetime or type argument")
+                    };
 
-                let mut val = p.default.as_ref().map_or_else(
-                    || unknown_const_as_generic(db.const_param_ty(id)),
-                    |c| {
-                        let c = ctx.lower_const(c, ctx.lower_ty(&p.ty));
-                        c.cast(Interner)
-                    },
-                );
-                // Each default can only refer to previous parameters, see above.
-                val = fallback_bound_vars(val, idx, parent_start_idx);
-                make_binders(db, &generic_params, val)
-            }
-            GenericParamDataRef::LifetimeParamData(_) => {
-                make_binders(db, &generic_params, error_lifetime().cast(Interner))
+                    let mut val = p.default.as_ref().map_or_else(
+                        || unknown_const_as_generic(db.const_param_ty(id)),
+                        |c| {
+                            let c = ctx.lower_const(c, ctx.lower_ty(&p.ty));
+                            c.cast(Interner)
+                        },
+                    );
+                    // Each default can only refer to previous parameters, see above.
+                    val = fallback_bound_vars(val, idx, parent_start_idx);
+                    make_binders(db, &generic_params, val)
+                }
+                GenericParamDataRef::LifetimeParamData(_) => {
+                    make_binders(db, &generic_params, error_lifetime().cast(Interner))
+                }
             }
-        }
-    }))
+        },
+    ))))
 }
 
 pub(crate) fn generic_defaults_recover(
     db: &dyn HirDatabase,
     _cycle: &Cycle,
     def: &GenericDefId,
-) -> Arc<[Binders<crate::GenericArg>]> {
+) -> GenericDefaults {
     let generic_params = generics(db.upcast(), *def);
+    if generic_params.len() == 0 {
+        return GenericDefaults(None);
+    }
     // FIXME: this code is not covered in tests.
     // we still need one default per parameter
-    Arc::from_iter(generic_params.iter_id().map(|id| {
+    GenericDefaults(Some(Arc::from_iter(generic_params.iter_id().map(|id| {
         let val = match id {
             GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
             GenericParamId::ConstParamId(id) => unknown_const_as_generic(db.const_param_ty(id)),
             GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
         };
         crate::make_binders(db, &generic_params, val)
-    }))
+    }))))
 }
 
 fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {