mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-28 04:45:05 +00:00
Save a bit on empty item trees by deduplicating them
This commit is contained in:
parent
3168ab5b99
commit
5548aecdca
8 changed files with 76 additions and 43 deletions
|
@ -80,9 +80,11 @@ pub trait InternDatabase: SourceDatabase {
|
||||||
|
|
||||||
#[salsa::query_group(DefDatabaseStorage)]
|
#[salsa::query_group(DefDatabaseStorage)]
|
||||||
pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDatabase> {
|
pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDatabase> {
|
||||||
|
/// Whether to expand procedural macros during name resolution.
|
||||||
#[salsa::input]
|
#[salsa::input]
|
||||||
fn expand_proc_attr_macros(&self) -> bool;
|
fn expand_proc_attr_macros(&self) -> bool;
|
||||||
|
|
||||||
|
/// Computes an [`ItemTree`] for the given file or macro expansion.
|
||||||
#[salsa::invoke(ItemTree::file_item_tree_query)]
|
#[salsa::invoke(ItemTree::file_item_tree_query)]
|
||||||
fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>;
|
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)]
|
#[salsa::invoke(DefMap::block_def_map_query)]
|
||||||
fn block_def_map(&self, block: BlockId) -> Arc<DefMap>;
|
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;
|
fn macro_def(&self, m: MacroId) -> MacroDefId;
|
||||||
|
|
||||||
// region:data
|
// region:data
|
||||||
|
|
|
@ -48,6 +48,7 @@ use either::Either;
|
||||||
use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile};
|
use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile};
|
||||||
use intern::Interned;
|
use intern::Interned;
|
||||||
use la_arena::{Arena, Idx, IdxRange, RawIdx};
|
use la_arena::{Arena, Idx, IdxRange, RawIdx};
|
||||||
|
use once_cell::sync::OnceCell;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use span::{AstIdNode, FileAstId, SyntaxContextId};
|
use span::{AstIdNode, FileAstId, SyntaxContextId};
|
||||||
|
@ -100,6 +101,7 @@ pub struct ItemTree {
|
||||||
impl ItemTree {
|
impl ItemTree {
|
||||||
pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<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();
|
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);
|
let syntax = db.parse_or_expand(file_id);
|
||||||
|
|
||||||
|
@ -131,19 +133,48 @@ impl ItemTree {
|
||||||
if let Some(attrs) = top_attrs {
|
if let Some(attrs) = top_attrs {
|
||||||
item_tree.attrs.insert(AttrOwner::TopLevel, attrs);
|
item_tree.attrs.insert(AttrOwner::TopLevel, attrs);
|
||||||
}
|
}
|
||||||
|
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();
|
item_tree.shrink_to_fit();
|
||||||
Arc::new(item_tree)
|
Arc::new(item_tree)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> {
|
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 loc = block.lookup(db);
|
||||||
let block = loc.ast_id.to_node(db.upcast());
|
let block = loc.ast_id.to_node(db.upcast());
|
||||||
|
|
||||||
let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
|
let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
|
||||||
let mut item_tree = ctx.lower_block(&block);
|
let mut item_tree = ctx.lower_block(&block);
|
||||||
|
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();
|
item_tree.shrink_to_fit();
|
||||||
Arc::new(item_tree)
|
Arc::new(item_tree)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an iterator over all items located at the top level of the `HirFileId` this
|
/// Returns an iterator over all items located at the top level of the `HirFileId` this
|
||||||
/// `ItemTree` was created from.
|
/// `ItemTree` was created from.
|
||||||
|
|
|
@ -977,6 +977,14 @@ impl GenericDefId {
|
||||||
_ => None,
|
_ => 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 {
|
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)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum AttrDefId {
|
pub enum AttrDefId {
|
||||||
ModuleId(ModuleId),
|
ModuleId(ModuleId),
|
||||||
|
|
|
@ -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> {
|
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 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 generic_params = generics(db.upcast(), generic_def);
|
||||||
let (sig, binders) = db.callable_item_signature(callable_def).into_value_and_skipped_binders();
|
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);
|
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 {
|
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 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(
|
Variances::from_iter(
|
||||||
Interner,
|
Interner,
|
||||||
std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()),
|
std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()),
|
||||||
|
|
|
@ -188,7 +188,7 @@ impl TyExt for Ty {
|
||||||
fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> {
|
fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> {
|
||||||
match *self.kind(Interner) {
|
match *self.kind(Interner) {
|
||||||
TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
|
TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
|
||||||
TyKind::FnDef(callable, ..) => Some(GenericDefId::from(
|
TyKind::FnDef(callable, ..) => Some(GenericDefId::from_callable(
|
||||||
db.upcast(),
|
db.upcast(),
|
||||||
db.lookup_intern_callable_def(callable.into()),
|
db.lookup_intern_callable_def(callable.into()),
|
||||||
)),
|
)),
|
||||||
|
|
|
@ -80,8 +80,32 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||||
#[salsa::cycle(crate::consteval::const_eval_discriminant_recover)]
|
#[salsa::cycle(crate::consteval::const_eval_discriminant_recover)]
|
||||||
fn const_eval_discriminant(&self, def: EnumVariantId) -> Result<i128, ConstEvalError>;
|
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
|
// 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::invoke(crate::lower::ty_query)]
|
||||||
#[salsa::cycle(crate::lower::ty_recover)]
|
#[salsa::cycle(crate::lower::ty_recover)]
|
||||||
fn ty(&self, def: TyDefId) -> Binders<Ty>;
|
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)]
|
#[salsa::invoke(crate::lower::field_types_query)]
|
||||||
fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>>;
|
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)]
|
#[salsa::invoke(crate::lower::callable_item_sig)]
|
||||||
fn callable_item_signature(&self, def: CallableDefId) -> PolyFnSig;
|
fn callable_item_signature(&self, def: CallableDefId) -> PolyFnSig;
|
||||||
|
|
||||||
|
|
|
@ -988,7 +988,7 @@ impl HirDisplay for Ty {
|
||||||
f.end_location_link();
|
f.end_location_link();
|
||||||
|
|
||||||
if parameters.len(Interner) > 0 {
|
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 generics = generics(db.upcast(), generic_def_id);
|
||||||
let (parent_len, self_param, type_, const_, impl_, lifetime) =
|
let (parent_len, self_param, type_, const_, impl_, lifetime) =
|
||||||
generics.provenance_split();
|
generics.provenance_split();
|
||||||
|
|
|
@ -1896,7 +1896,7 @@ impl InferenceContext<'_> {
|
||||||
if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(Interner) {
|
if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(Interner) {
|
||||||
let def: CallableDefId = from_chalk(self.db, *fn_def);
|
let def: CallableDefId = from_chalk(self.db, *fn_def);
|
||||||
let generic_predicates =
|
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() {
|
for predicate in generic_predicates.iter() {
|
||||||
let (predicate, binders) = predicate
|
let (predicate, binders) = predicate
|
||||||
.clone()
|
.clone()
|
||||||
|
|
Loading…
Reference in a new issue