Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions crates/base-db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,26 @@ macro_rules! impl_intern_key {
};
}

/// SAFETY: `old_pointer` must be valid for unique writes
pub unsafe fn unsafe_update_eq<T>(old_pointer: *mut T, new_value: T) -> bool
where
T: PartialEq,
{
// SAFETY: Caller obligation
let old_ref: &mut T = unsafe { &mut *old_pointer };

if *old_ref != new_value {
*old_ref = new_value;
true
} else {
// Subtle but important: Eq impls can be buggy or define equality
// in surprising ways. If it says that the value has not changed,
// we do not modify the existing value, and thus do not have to
// update the revision, as downstream code will not see the new value.
false
}
}

pub const DEFAULT_FILE_TEXT_LRU_CAP: u16 = 16;
pub const DEFAULT_PARSE_LRU_CAP: u16 = 128;
pub const DEFAULT_BORROWCK_LRU_CAP: u16 = 2024;
Expand Down
37 changes: 0 additions & 37 deletions crates/hir/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,5 @@
//!
//! But we need this for at least LRU caching at the query level.
pub use hir_def::db::DefDatabase;
// AttrsQuery, BlockDefMapQuery, BlockItemTreeQuery, BlockItemTreeWithSourceMapQuery, BodyQuery,
// BodyWithSourceMapQuery, ConstDataQuery, ConstVisibilityQuery, CrateDefMapQuery,
// CrateLangItemsQuery, CrateNotableTraitsQuery, CrateSupportsNoStdQuery, DefDatabase,
// DefDatabaseStorage, EnumDataQuery, EnumVariantDataWithDiagnosticsQuery,
// ExpandProcAttrMacrosQuery, ExprScopesQuery, ExternCrateDeclDataQuery, FieldVisibilitiesQuery,
// FieldsAttrsQuery, FieldsAttrsSourceMapQuery, FileItemTreeQuery, FileItemTreeWithSourceMapQuery,
// FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery,
// GenericParamsWithSourceMapQuery, ImplItemsWithDiagnosticsQuery, ImportMapQuery,
// IncludeMacroInvocQuery, InternAnonymousConstQuery, InternBlockQuery, InternConstQuery,
// InternDatabase, InternDatabaseStorage, InternEnumQuery, InternExternBlockQuery,
// InternExternCrateQuery, InternFunctionQuery, InternImplQuery, InternInTypeConstQuery,
// InternMacro2Query, InternMacroRulesQuery, InternProcMacroQuery, InternStaticQuery,
// InternStructQuery, InternTraitAliasQuery, InternTraitQuery, InternTypeAliasQuery,
// InternUnionQuery, InternUseQuery, LangItemQuery, Macro2DataQuery, MacroDefQuery,
// MacroRulesDataQuery, NotableTraitsInDepsQuery, ProcMacroDataQuery, StaticDataQuery,
// StructDataWithDiagnosticsQuery, TraitAliasDataQuery, TraitItemsWithDiagnosticsQuery,
// TypeAliasDataQuery, UnionDataWithDiagnosticsQuery,
// };
pub use hir_expand::db::ExpandDatabase;
// AstIdMapQuery, DeclMacroExpanderQuery, ExpandDatabase, ExpandDatabaseStorage,
// ExpandProcMacroQuery, InternMacroCallQuery, InternSyntaxContextQuery, MacroArgQuery,
// ParseMacroExpansionErrorQuery, ParseMacroExpansionQuery, ProcMacroSpanQuery, ProcMacrosQuery,
// RealSpanMapQuery,
pub use hir_ty::db::HirDatabase;
// AdtDatumQuery, AdtVarianceQuery, AssociatedTyDataQuery, AssociatedTyValueQuery, BorrowckQuery,
// CallableItemSignatureQuery, ConstEvalDiscriminantQuery, ConstEvalQuery, ConstEvalStaticQuery,
// ConstParamTyQuery, DynCompatibilityOfTraitQuery, FieldTypesQuery, FnDefDatumQuery,
// FnDefVarianceQuery, GenericDefaultsQuery, GenericPredicatesForParamQuery,
// GenericPredicatesQuery, GenericPredicatesWithoutParentQuery, HirDatabase, HirDatabaseStorage,
// ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, IncoherentInherentImplCratesQuery, InferQuery,
// InherentImplsInBlockQuery, InherentImplsInCrateQuery, InternCallableDefQuery,
// InternClosureQuery, InternCoroutineQuery, InternImplTraitIdQuery, InternLifetimeParamIdQuery,
// InternTypeOrConstParamIdQuery, LayoutOfAdtQuery, LayoutOfTyQuery, LookupImplMethodQuery,
// MirBodyForClosureQuery, MirBodyQuery, MonomorphizedMirBodyForClosureQuery,
// MonomorphizedMirBodyQuery, ProgramClausesForChalkEnvQuery, ReturnTypeImplTraitsQuery,
// TargetDataLayoutQuery, TraitDatumQuery, TraitEnvironmentQuery, TraitImplsInBlockQuery,
// TraitImplsInCrateQuery, TraitImplsInDepsQuery, TraitSolveQuery, TyQuery,
// TypeAliasImplTraitsQuery, ValueTyQuery,
// };
23 changes: 16 additions & 7 deletions crates/hir/src/symbols.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! File symbol extraction.

use std::marker::PhantomData;

use base_db::FxIndexSet;
use either::Either;
use hir_def::{
Expand All @@ -25,7 +27,7 @@ use crate::{HasCrate, Module, ModuleDef, Semantics};
/// The actual data that is stored in the index. It should be as compact as
/// possible.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FileSymbol {
pub struct FileSymbol<'db> {
pub name: Symbol,
pub def: ModuleDef,
pub loc: DeclarationLocation,
Expand All @@ -35,6 +37,7 @@ pub struct FileSymbol {
pub is_assoc: bool,
pub is_import: bool,
pub do_not_complete: Complete,
_marker: PhantomData<&'db ()>,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
Expand All @@ -61,9 +64,9 @@ struct SymbolCollectorWork {
parent: Option<Name>,
}

pub struct SymbolCollector<'a> {
db: &'a dyn HirDatabase,
symbols: FxIndexSet<FileSymbol>,
pub struct SymbolCollector<'db> {
db: &'db dyn HirDatabase,
symbols: FxIndexSet<FileSymbol<'db>>,
work: Vec<SymbolCollectorWork>,
current_container_name: Option<Symbol>,
collect_pub_only: bool,
Expand All @@ -83,10 +86,10 @@ impl<'a> SymbolCollector<'a> {
}

pub fn new_module(
db: &dyn HirDatabase,
db: &'a dyn HirDatabase,
module: Module,
collect_pub_only: bool,
) -> Box<[FileSymbol]> {
) -> Box<[FileSymbol<'a>]> {
let mut symbol_collector = SymbolCollector::new(db, collect_pub_only);
symbol_collector.collect(module);
symbol_collector.finish()
Expand All @@ -105,7 +108,7 @@ impl<'a> SymbolCollector<'a> {
}
}

pub fn finish(self) -> Box<[FileSymbol]> {
pub fn finish(self) -> Box<[FileSymbol<'a>]> {
self.symbols.into_iter().collect()
}

Expand Down Expand Up @@ -217,6 +220,7 @@ impl<'a> SymbolCollector<'a> {
is_assoc: false,
is_import: true,
do_not_complete: Complete::Yes,
_marker: PhantomData,
});
};

Expand Down Expand Up @@ -251,6 +255,7 @@ impl<'a> SymbolCollector<'a> {
is_assoc: false,
is_import: false,
do_not_complete: Complete::Yes,
_marker: PhantomData,
});
};

Expand Down Expand Up @@ -428,6 +433,7 @@ impl<'a> SymbolCollector<'a> {
is_assoc,
is_import: false,
do_not_complete,
_marker: PhantomData,
});
}
}
Expand All @@ -441,6 +447,7 @@ impl<'a> SymbolCollector<'a> {
is_assoc,
is_import: false,
do_not_complete,
_marker: PhantomData,
});

do_not_complete
Expand Down Expand Up @@ -474,6 +481,7 @@ impl<'a> SymbolCollector<'a> {
is_assoc: false,
is_import: false,
do_not_complete,
_marker: PhantomData,
});
}
}
Expand All @@ -487,6 +495,7 @@ impl<'a> SymbolCollector<'a> {
is_assoc: false,
is_import: false,
do_not_complete,
_marker: PhantomData,
});
}
}
77 changes: 47 additions & 30 deletions crates/ide-db/src/symbol_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use hir::{
};
use rayon::prelude::*;
use rustc_hash::FxHashSet;
use salsa::Update;

use crate::RootDatabase;

Expand Down Expand Up @@ -118,7 +119,7 @@ pub struct LocalRoots {
}

/// The symbol indices of modules that make up a given crate.
pub fn crate_symbols(db: &dyn HirDatabase, krate: Crate) -> Box<[&SymbolIndex]> {
pub fn crate_symbols(db: &dyn HirDatabase, krate: Crate) -> Box<[&SymbolIndex<'_>]> {
let _p = tracing::info_span!("crate_symbols").entered();
krate.modules(db).into_iter().map(|module| SymbolIndex::module_symbols(db, module)).collect()
}
Expand Down Expand Up @@ -148,7 +149,7 @@ pub fn crate_symbols(db: &dyn HirDatabase, krate: Crate) -> Box<[&SymbolIndex]>
// | Editor | Shortcut |
// |---------|-----------|
// | VS Code | <kbd>Ctrl+T</kbd>
pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol<'_>> {
let _p = tracing::info_span!("world_symbols", query = ?query.query).entered();

let indices: Vec<_> = if query.libs {
Expand All @@ -170,9 +171,7 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
crates
.par_iter()
.for_each_with(db.clone(), |snap, &krate| _ = crate_symbols(snap, krate.into()));
let indices: Vec<_> =
crates.into_iter().map(|krate| crate_symbols(db, krate.into())).collect();
indices.iter().flat_map(|indices| indices.iter().cloned()).collect()
crates.into_iter().flat_map(|krate| Vec::from(crate_symbols(db, krate.into()))).collect()
};

let mut res = vec![];
Expand All @@ -184,24 +183,27 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
}

#[derive(Default)]
pub struct SymbolIndex {
symbols: Box<[FileSymbol]>,
pub struct SymbolIndex<'db> {
symbols: Box<[FileSymbol<'db>]>,
map: fst::Map<Vec<u8>>,
}

impl SymbolIndex {
impl<'db> SymbolIndex<'db> {
/// The symbol index for a given source root within library_roots.
pub fn library_symbols(db: &dyn HirDatabase, source_root_id: SourceRootId) -> &SymbolIndex {
pub fn library_symbols(
db: &'db dyn HirDatabase,
source_root_id: SourceRootId,
) -> &'db SymbolIndex<'db> {
// FIXME:
#[salsa::interned]
struct InternedSourceRootId {
id: SourceRootId,
}
#[salsa::tracked(returns(ref))]
fn library_symbols(
db: &dyn HirDatabase,
source_root_id: InternedSourceRootId<'_>,
) -> SymbolIndex {
fn library_symbols<'db>(
db: &'db dyn HirDatabase,
source_root_id: InternedSourceRootId<'db>,
) -> SymbolIndex<'db> {
let _p = tracing::info_span!("library_symbols").entered();

// We call this without attaching because this runs in parallel, so we need to attach here.
Expand All @@ -224,15 +226,18 @@ impl SymbolIndex {

/// The symbol index for a given module. These modules should only be in source roots that
/// are inside local_roots.
pub fn module_symbols(db: &dyn HirDatabase, module: Module) -> &SymbolIndex {
pub fn module_symbols(db: &dyn HirDatabase, module: Module) -> &SymbolIndex<'_> {
// FIXME:
#[salsa::interned]
struct InternedModuleId {
id: hir::ModuleId,
}

#[salsa::tracked(returns(ref))]
fn module_symbols(db: &dyn HirDatabase, module: InternedModuleId<'_>) -> SymbolIndex {
fn module_symbols<'db>(
db: &'db dyn HirDatabase,
module: InternedModuleId<'db>,
) -> SymbolIndex<'db> {
let _p = tracing::info_span!("module_symbols").entered();

// We call this without attaching because this runs in parallel, so we need to attach here.
Expand All @@ -250,29 +255,41 @@ impl SymbolIndex {
}
}

impl fmt::Debug for SymbolIndex {
impl fmt::Debug for SymbolIndex<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SymbolIndex").field("n_symbols", &self.symbols.len()).finish()
}
}

impl PartialEq for SymbolIndex {
fn eq(&self, other: &SymbolIndex) -> bool {
impl PartialEq for SymbolIndex<'_> {
fn eq(&self, other: &SymbolIndex<'_>) -> bool {
self.symbols == other.symbols
}
}

impl Eq for SymbolIndex {}
impl Eq for SymbolIndex<'_> {}

impl Hash for SymbolIndex {
impl Hash for SymbolIndex<'_> {
fn hash<H: Hasher>(&self, hasher: &mut H) {
self.symbols.hash(hasher)
}
}

impl SymbolIndex {
fn new(mut symbols: Box<[FileSymbol]>) -> SymbolIndex {
fn cmp(lhs: &FileSymbol, rhs: &FileSymbol) -> Ordering {
unsafe impl Update for SymbolIndex<'_> {
unsafe fn maybe_update(old_pointer: *mut Self, new_value: Self) -> bool {
let this = unsafe { &mut *old_pointer };
if *this == new_value {
false
} else {
*this = new_value;
true
}
}
}

impl<'db> SymbolIndex<'db> {
fn new(mut symbols: Box<[FileSymbol<'db>]>) -> SymbolIndex<'db> {
fn cmp(lhs: &FileSymbol<'_>, rhs: &FileSymbol<'_>) -> Ordering {
let lhs_chars = lhs.name.as_str().chars().map(|c| c.to_ascii_lowercase());
let rhs_chars = rhs.name.as_str().chars().map(|c| c.to_ascii_lowercase());
lhs_chars.cmp(rhs_chars)
Expand Down Expand Up @@ -318,7 +335,7 @@ impl SymbolIndex {
}

pub fn memory_size(&self) -> usize {
self.map.as_fst().size() + self.symbols.len() * size_of::<FileSymbol>()
self.map.as_fst().size() + self.symbols.len() * size_of::<FileSymbol<'_>>()
}

fn range_to_map_value(start: usize, end: usize) -> u64 {
Expand All @@ -336,10 +353,10 @@ impl SymbolIndex {
}

impl Query {
pub(crate) fn search<'sym, T>(
pub(crate) fn search<'db, T>(
self,
indices: &'sym [&SymbolIndex],
cb: impl FnMut(&'sym FileSymbol) -> ControlFlow<T>,
indices: &[&'db SymbolIndex<'db>],
cb: impl FnMut(&'db FileSymbol<'db>) -> ControlFlow<T>,
) -> Option<T> {
let _p = tracing::info_span!("symbol_index::Query::search").entered();
let mut op = fst::map::OpBuilder::new();
Expand Down Expand Up @@ -371,11 +388,11 @@ impl Query {
}
}

fn search_maps<'sym, T>(
fn search_maps<'db, T>(
&self,
indices: &'sym [&SymbolIndex],
indices: &[&'db SymbolIndex<'db>],
mut stream: fst::map::Union<'_>,
mut cb: impl FnMut(&'sym FileSymbol) -> ControlFlow<T>,
mut cb: impl FnMut(&'db FileSymbol<'db>) -> ControlFlow<T>,
) -> Option<T> {
let ignore_underscore_prefixed = !self.query.starts_with("__");
while let Some((_, indexed_values)) = stream.next() {
Expand Down
2 changes: 1 addition & 1 deletion crates/ide/src/navigation_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ impl NavigationTarget {
}
}

impl TryToNav for FileSymbol {
impl<'db> TryToNav for FileSymbol<'db> {
fn try_to_nav(
&self,
sema: &Semantics<'_, RootDatabase>,
Expand Down
Loading