Unnamed repository; edit this file 'description' to name the repository.
Save a bit on empty item trees by deduplicating them
Lukas Wirth 2024-06-24
parent 3168ab5 · commit 5548aec
-rw-r--r--crates/hir-def/src/db.rs3
-rw-r--r--crates/hir-def/src/item_tree.rs39
-rw-r--r--crates/hir-def/src/lib.rs18
-rw-r--r--crates/hir-ty/src/chalk_db.rs5
-rw-r--r--crates/hir-ty/src/chalk_ext.rs2
-rw-r--r--crates/hir-ty/src/db.rs48
-rw-r--r--crates/hir-ty/src/display.rs2
-rw-r--r--crates/hir-ty/src/infer/expr.rs2
8 files changed, 76 insertions, 43 deletions
diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs
index 61fed71218..eb45ad343e 100644
--- a/crates/hir-def/src/db.rs
+++ b/crates/hir-def/src/db.rs
@@ -80,9 +80,11 @@ pub trait InternDatabase: SourceDatabase {
#[salsa::query_group(DefDatabaseStorage)]
pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDatabase> {
+ /// Whether to expand procedural macros during name resolution.
#[salsa::input]
fn expand_proc_attr_macros(&self) -> bool;
+ /// Computes an [`ItemTree`] for the given file or macro expansion.
#[salsa::invoke(ItemTree::file_item_tree_query)]
fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>;
@@ -96,6 +98,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
#[salsa::invoke(DefMap::block_def_map_query)]
fn block_def_map(&self, block: BlockId) -> Arc<DefMap>;
+ /// Turns a MacroId into a MacroDefId, describing the macro's definition post name resolution.
fn macro_def(&self, m: MacroId) -> MacroDefId;
// region:data
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index c3b7a78301..be74d15814 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -48,6 +48,7 @@ use either::Either;
use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile};
use intern::Interned;
use la_arena::{Arena, Idx, IdxRange, RawIdx};
+use once_cell::sync::OnceCell;
use rustc_hash::FxHashMap;
use smallvec::SmallVec;
use span::{AstIdNode, FileAstId, SyntaxContextId};
@@ -100,6 +101,7 @@ pub struct ItemTree {
impl ItemTree {
pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> {
let _p = tracing::info_span!("file_item_tree_query", ?file_id).entered();
+ static EMPTY: OnceCell<Arc<ItemTree>> = OnceCell::new();
let syntax = db.parse_or_expand(file_id);
@@ -131,18 +133,47 @@ impl ItemTree {
if let Some(attrs) = top_attrs {
item_tree.attrs.insert(AttrOwner::TopLevel, attrs);
}
- item_tree.shrink_to_fit();
- Arc::new(item_tree)
+ if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty()
+ {
+ EMPTY
+ .get_or_init(|| {
+ Arc::new(ItemTree {
+ top_level: SmallVec::new_const(),
+ attrs: FxHashMap::default(),
+ data: None,
+ })
+ })
+ .clone()
+ } else {
+ item_tree.shrink_to_fit();
+ Arc::new(item_tree)
+ }
}
pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> {
+ let _p = tracing::info_span!("block_item_tree_query", ?block).entered();
+ static EMPTY: OnceCell<Arc<ItemTree>> = OnceCell::new();
+
let loc = block.lookup(db);
let block = loc.ast_id.to_node(db.upcast());
let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
let mut item_tree = ctx.lower_block(&block);
- item_tree.shrink_to_fit();
- Arc::new(item_tree)
+ if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty()
+ {
+ EMPTY
+ .get_or_init(|| {
+ Arc::new(ItemTree {
+ top_level: SmallVec::new_const(),
+ attrs: FxHashMap::default(),
+ data: None,
+ })
+ })
+ .clone()
+ } else {
+ item_tree.shrink_to_fit();
+ Arc::new(item_tree)
+ }
}
/// Returns an iterator over all items located at the top level of the `HirFileId` this
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index b628137ef5..3fa98efbb5 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -977,6 +977,14 @@ impl GenericDefId {
_ => None,
}
}
+
+ pub fn from_callable(db: &dyn DefDatabase, def: CallableDefId) -> GenericDefId {
+ match def {
+ CallableDefId::FunctionId(f) => f.into(),
+ CallableDefId::StructId(s) => s.into(),
+ CallableDefId::EnumVariantId(e) => e.lookup(db).parent.into(),
+ }
+ }
}
impl From<AssocItemId> for GenericDefId {
@@ -1019,16 +1027,6 @@ impl CallableDefId {
}
}
-impl GenericDefId {
- pub fn from(db: &dyn DefDatabase, def: CallableDefId) -> GenericDefId {
- match def {
- CallableDefId::FunctionId(f) => f.into(),
- CallableDefId::StructId(s) => s.into(),
- CallableDefId::EnumVariantId(e) => e.lookup(db).parent.into(),
- }
- }
-}
-
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum AttrDefId {
ModuleId(ModuleId),
diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs
index 43c34a7eda..3ac8cbaaf8 100644
--- a/crates/hir-ty/src/chalk_db.rs
+++ b/crates/hir-ty/src/chalk_db.rs
@@ -915,7 +915,7 @@ fn type_alias_associated_ty_value(
pub(crate) fn fn_def_datum_query(db: &dyn HirDatabase, fn_def_id: FnDefId) -> Arc<FnDefDatum> {
let callable_def: CallableDefId = from_chalk(db, fn_def_id);
- let generic_def = GenericDefId::from(db.upcast(), callable_def);
+ let generic_def = GenericDefId::from_callable(db.upcast(), callable_def);
let generic_params = generics(db.upcast(), generic_def);
let (sig, binders) = db.callable_item_signature(callable_def).into_value_and_skipped_binders();
let bound_vars = generic_params.bound_vars_subst(db, DebruijnIndex::INNERMOST);
@@ -946,7 +946,8 @@ pub(crate) fn fn_def_datum_query(db: &dyn HirDatabase, fn_def_id: FnDefId) -> Ar
pub(crate) fn fn_def_variance_query(db: &dyn HirDatabase, fn_def_id: FnDefId) -> Variances {
let callable_def: CallableDefId = from_chalk(db, fn_def_id);
- let generic_params = generics(db.upcast(), GenericDefId::from(db.upcast(), callable_def));
+ let generic_params =
+ generics(db.upcast(), GenericDefId::from_callable(db.upcast(), callable_def));
Variances::from_iter(
Interner,
std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()),
diff --git a/crates/hir-ty/src/chalk_ext.rs b/crates/hir-ty/src/chalk_ext.rs
index 117fbd7bab..320e5bd8a2 100644
--- a/crates/hir-ty/src/chalk_ext.rs
+++ b/crates/hir-ty/src/chalk_ext.rs
@@ -188,7 +188,7 @@ impl TyExt for Ty {
fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> {
match *self.kind(Interner) {
TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
- TyKind::FnDef(callable, ..) => Some(GenericDefId::from(
+ TyKind::FnDef(callable, ..) => Some(GenericDefId::from_callable(
db.upcast(),
db.lookup_intern_callable_def(callable.into()),
)),
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index 164c244483..734aad4945 100644
--- a/crates/hir-ty/src/db.rs
+++ b/crates/hir-ty/src/db.rs
@@ -80,8 +80,32 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
#[salsa::cycle(crate::consteval::const_eval_discriminant_recover)]
fn const_eval_discriminant(&self, def: EnumVariantId) -> Result<i128, ConstEvalError>;
+ #[salsa::invoke(crate::method_resolution::lookup_impl_method_query)]
+ fn lookup_impl_method(
+ &self,
+ env: Arc<TraitEnvironment>,
+ func: FunctionId,
+ fn_subst: Substitution,
+ ) -> (FunctionId, Substitution);
+
// endregion:mir
+ #[salsa::invoke(crate::layout::layout_of_adt_query)]
+ #[salsa::cycle(crate::layout::layout_of_adt_recover)]
+ fn layout_of_adt(
+ &self,
+ def: AdtId,
+ subst: Substitution,
+ env: Arc<TraitEnvironment>,
+ ) -> Result<Arc<Layout>, LayoutError>;
+
+ #[salsa::invoke(crate::layout::layout_of_ty_query)]
+ #[salsa::cycle(crate::layout::layout_of_ty_recover)]
+ fn layout_of_ty(&self, ty: Ty, env: Arc<TraitEnvironment>) -> Result<Arc<Layout>, LayoutError>;
+
+ #[salsa::invoke(crate::layout::target_data_layout_query)]
+ fn target_data_layout(&self, krate: CrateId) -> Result<Arc<TargetDataLayout>, Arc<str>>;
+
#[salsa::invoke(crate::lower::ty_query)]
#[salsa::cycle(crate::lower::ty_recover)]
fn ty(&self, def: TyDefId) -> Binders<Ty>;
@@ -104,30 +128,6 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
#[salsa::invoke(crate::lower::field_types_query)]
fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>>;
- #[salsa::invoke(crate::layout::layout_of_adt_query)]
- #[salsa::cycle(crate::layout::layout_of_adt_recover)]
- fn layout_of_adt(
- &self,
- def: AdtId,
- subst: Substitution,
- env: Arc<TraitEnvironment>,
- ) -> Result<Arc<Layout>, LayoutError>;
-
- #[salsa::invoke(crate::layout::layout_of_ty_query)]
- #[salsa::cycle(crate::layout::layout_of_ty_recover)]
- fn layout_of_ty(&self, ty: Ty, env: Arc<TraitEnvironment>) -> Result<Arc<Layout>, LayoutError>;
-
- #[salsa::invoke(crate::layout::target_data_layout_query)]
- fn target_data_layout(&self, krate: CrateId) -> Result<Arc<TargetDataLayout>, Arc<str>>;
-
- #[salsa::invoke(crate::method_resolution::lookup_impl_method_query)]
- fn lookup_impl_method(
- &self,
- env: Arc<TraitEnvironment>,
- func: FunctionId,
- fn_subst: Substitution,
- ) -> (FunctionId, Substitution);
-
#[salsa::invoke(crate::lower::callable_item_sig)]
fn callable_item_signature(&self, def: CallableDefId) -> PolyFnSig;
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 70b670f5e8..458970aa70 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -988,7 +988,7 @@ impl HirDisplay for Ty {
f.end_location_link();
if parameters.len(Interner) > 0 {
- let generic_def_id = GenericDefId::from(db.upcast(), def);
+ let generic_def_id = GenericDefId::from_callable(db.upcast(), def);
let generics = generics(db.upcast(), generic_def_id);
let (parent_len, self_param, type_, const_, impl_, lifetime) =
generics.provenance_split();
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index e053b0c1a4..3647243537 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -1896,7 +1896,7 @@ impl InferenceContext<'_> {
if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(Interner) {
let def: CallableDefId = from_chalk(self.db, *fn_def);
let generic_predicates =
- self.db.generic_predicates(GenericDefId::from(self.db.upcast(), def));
+ self.db.generic_predicates(GenericDefId::from_callable(self.db.upcast(), def));
for predicate in generic_predicates.iter() {
let (predicate, binders) = predicate
.clone()