migrate to salsas interning

This commit is contained in:
Aleksey Kladov 2019-04-09 22:51:22 +03:00
parent 2fc2d4373b
commit 6b993a9760
8 changed files with 109 additions and 111 deletions

View File

@ -9,7 +9,7 @@ use rustc_hash::FxHashMap;
use ra_db::{
CrateGraph, FileId, SourceRoot, SourceRootId, SourceDatabase, salsa,
};
use ra_hir::{db, HirInterner};
use ra_hir::db;
use ra_project_model::ProjectWorkspace;
use ra_vfs::{Vfs, VfsChange};
use vfs_filter::IncludeRustFiles;
@ -20,7 +20,6 @@ type Result<T> = std::result::Result<T, failure::Error>;
#[derive(Debug)]
pub struct BatchDatabase {
runtime: salsa::Runtime<BatchDatabase>,
interner: Arc<HirInterner>,
}
impl salsa::Database for BatchDatabase {
@ -29,12 +28,6 @@ impl salsa::Database for BatchDatabase {
}
}
impl AsRef<HirInterner> for BatchDatabase {
fn as_ref(&self) -> &HirInterner {
&self.interner
}
}
fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId {
FileId(f.0.into())
}
@ -44,8 +37,7 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
impl BatchDatabase {
pub fn load(crate_graph: CrateGraph, vfs: &mut Vfs) -> BatchDatabase {
let mut db =
BatchDatabase { runtime: salsa::Runtime::default(), interner: Default::default() };
let mut db = BatchDatabase { runtime: salsa::Runtime::default() };
db.set_crate_graph(Arc::new(crate_graph));
// wait until Vfs has loaded all roots

View File

@ -1,10 +1,10 @@
use std::sync::Arc;
use ra_syntax::{SyntaxNode, TreeArc, SourceFile};
use ra_syntax::{SyntaxNode, TreeArc, SourceFile, ast};
use ra_db::{SourceDatabase, salsa};
use crate::{
HirFileId, MacroDefId, AstIdMap, ErasedFileAstId, Crate, Module, HirInterner,
HirFileId, MacroDefId, AstIdMap, ErasedFileAstId, Crate, Module, MacroCallLoc,
Function, FnSignature, ExprScopes, TypeAlias,
Struct, Enum, StructField,
Const, ConstSignature, Static,
@ -15,11 +15,29 @@ use crate::{
impl_block::{ModuleImplBlocks, ImplSourceMap},
generics::{GenericParams, GenericDef},
type_ref::TypeRef,
traits::TraitData, Trait, ty::TraitRef
traits::TraitData, Trait, ty::TraitRef,
ids
};
#[salsa::query_group(DefDatabaseStorage)]
pub trait DefDatabase: SourceDatabase + AsRef<HirInterner> {
pub trait DefDatabase: SourceDatabase {
#[salsa::interned]
fn intern_macro(&self, macro_call: MacroCallLoc) -> ids::MacroCallId;
#[salsa::interned]
fn intern_function(&self, loc: ids::ItemLoc<ast::FnDef>) -> ids::FunctionId;
#[salsa::interned]
fn intern_struct(&self, loc: ids::ItemLoc<ast::StructDef>) -> ids::StructId;
#[salsa::interned]
fn intern_enum(&self, loc: ids::ItemLoc<ast::EnumDef>) -> ids::EnumId;
#[salsa::interned]
fn intern_const(&self, loc: ids::ItemLoc<ast::ConstDef>) -> ids::ConstId;
#[salsa::interned]
fn intern_static(&self, loc: ids::ItemLoc<ast::StaticDef>) -> ids::StaticId;
#[salsa::interned]
fn intern_trait(&self, loc: ids::ItemLoc<ast::TraitDef>) -> ids::TraitId;
#[salsa::interned]
fn intern_type_alias(&self, loc: ids::ItemLoc<ast::TypeAliasDef>) -> ids::TypeAliasId;
#[salsa::invoke(crate::ids::macro_def_query)]
fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>;

View File

@ -294,9 +294,9 @@ pub struct ReferenceDescriptor {
#[cfg(test)]
mod tests {
use ra_db::salsa::InternKey;
use ra_syntax::{SourceFile, algo::find_node_at_offset};
use test_utils::{extract_offset, assert_eq_text};
use ra_arena::ArenaId;
use crate::Function;
use crate::expr::{ExprCollector};
@ -316,7 +316,8 @@ mod tests {
let file = SourceFile::parse(&code);
let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap();
let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
let irrelevant_function = Function { id: crate::ids::FunctionId::from_raw(0.into()) };
let irrelevant_function =
Function { id: crate::ids::FunctionId::from_intern_id(0u32.into()) };
let (body, source_map) = collect_fn_body_syntax(irrelevant_function, fn_def);
let scopes = ExprScopes::new(Arc::new(body));
let scopes =
@ -421,7 +422,8 @@ mod tests {
let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap();
let irrelevant_function = Function { id: crate::ids::FunctionId::from_raw(0.into()) };
let irrelevant_function =
Function { id: crate::ids::FunctionId::from_intern_id(0u32.into()) };
let (body, source_map) = collect_fn_body_syntax(irrelevant_function, fn_def);
let scopes = ExprScopes::new(Arc::new(body));
let scopes =

View File

@ -3,40 +3,14 @@ use std::{
sync::Arc,
};
use ra_db::{LocationInterner, FileId};
use ra_db::{FileId, salsa};
use ra_syntax::{TreeArc, SourceFile, AstNode, ast};
use ra_arena::{RawId, ArenaId, impl_arena_id};
use mbe::MacroRules;
use crate::{
Module, DefDatabase, AstId, FileAstId,
};
#[derive(Debug, Default)]
pub struct HirInterner {
macros: LocationInterner<MacroCallLoc, MacroCallId>,
fns: LocationInterner<ItemLoc<ast::FnDef>, FunctionId>,
structs: LocationInterner<ItemLoc<ast::StructDef>, StructId>,
enums: LocationInterner<ItemLoc<ast::EnumDef>, EnumId>,
consts: LocationInterner<ItemLoc<ast::ConstDef>, ConstId>,
statics: LocationInterner<ItemLoc<ast::StaticDef>, StaticId>,
traits: LocationInterner<ItemLoc<ast::TraitDef>, TraitId>,
types: LocationInterner<ItemLoc<ast::TypeAliasDef>, TypeAliasId>,
}
impl HirInterner {
pub fn len(&self) -> usize {
self.macros.len()
+ self.fns.len()
+ self.structs.len()
+ self.enums.len()
+ self.consts.len()
+ self.statics.len()
+ self.traits.len()
+ self.types.len()
}
}
/// hir makes heavy use of ids: integer (u32) handlers to various things. You
/// can think of id as a pointer (but without a lifetime) or a file descriptor
/// (but for hir objects).
@ -135,11 +109,24 @@ pub(crate) fn macro_def_query(db: &impl DefDatabase, id: MacroDefId) -> Option<A
Some(Arc::new(rules))
}
macro_rules! impl_intern_key {
($name:ident) => {
impl salsa::InternKey for $name {
fn from_intern_id(v: salsa::InternId) -> Self {
$name(v)
}
fn as_intern_id(&self) -> salsa::InternId {
self.0
}
}
};
}
/// `MacroCallId` identifies a particular macro invocation, like
/// `println!("Hello, {}", world)`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MacroCallId(RawId);
impl_arena_id!(MacroCallId);
pub struct MacroCallId(salsa::InternId);
impl_intern_key!(MacroCallId);
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MacroCallLoc {
@ -148,14 +135,14 @@ pub struct MacroCallLoc {
}
impl MacroCallId {
pub(crate) fn loc(self, db: &impl AsRef<HirInterner>) -> MacroCallLoc {
db.as_ref().macros.id2loc(self)
pub(crate) fn loc(self, db: &impl DefDatabase) -> MacroCallLoc {
db.lookup_intern_macro(self)
}
}
impl MacroCallLoc {
pub(crate) fn id(&self, db: &impl AsRef<HirInterner>) -> MacroCallId {
db.as_ref().macros.loc2id(&self)
pub(crate) fn id(self, db: &impl DefDatabase) -> MacroCallId {
db.intern_macro(self)
}
}
@ -204,8 +191,10 @@ impl<'a, DB: DefDatabase> LocationCtx<&'a DB> {
}
}
pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<N>, Self>;
pub(crate) trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
fn intern(db: &impl DefDatabase, loc: ItemLoc<N>) -> Self;
fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<N>;
fn from_ast(ctx: LocationCtx<&impl DefDatabase>, ast: &N) -> Self {
let items = ctx.db.ast_id_map(ctx.file_id);
let item_id = items.ast_id(ast);
@ -213,80 +202,100 @@ pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
}
fn from_ast_id(ctx: LocationCtx<&impl DefDatabase>, ast_id: FileAstId<N>) -> Self {
let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) };
Self::interner(ctx.db.as_ref()).loc2id(&loc)
Self::intern(ctx.db, loc)
}
fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<N>) {
let int = Self::interner(db.as_ref());
let loc = int.id2loc(self);
let loc = self.lookup_intern(db);
let ast = loc.ast_id.to_node(db);
(loc.ast_id.file_id(), ast)
}
fn module(self, db: &impl DefDatabase) -> Module {
let int = Self::interner(db.as_ref());
let loc = int.id2loc(self);
let loc = self.lookup_intern(db);
loc.module
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct FunctionId(RawId);
impl_arena_id!(FunctionId);
pub struct FunctionId(salsa::InternId);
impl_intern_key!(FunctionId);
impl AstItemDef<ast::FnDef> for FunctionId {
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::FnDef>, Self> {
&interner.fns
fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::FnDef>) -> Self {
db.intern_function(loc)
}
fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::FnDef> {
db.lookup_intern_function(self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct StructId(RawId);
impl_arena_id!(StructId);
pub struct StructId(salsa::InternId);
impl_intern_key!(StructId);
impl AstItemDef<ast::StructDef> for StructId {
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::StructDef>, Self> {
&interner.structs
fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::StructDef>) -> Self {
db.intern_struct(loc)
}
fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::StructDef> {
db.lookup_intern_struct(self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct EnumId(RawId);
impl_arena_id!(EnumId);
pub struct EnumId(salsa::InternId);
impl_intern_key!(EnumId);
impl AstItemDef<ast::EnumDef> for EnumId {
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::EnumDef>, Self> {
&interner.enums
fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::EnumDef>) -> Self {
db.intern_enum(loc)
}
fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::EnumDef> {
db.lookup_intern_enum(self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct ConstId(RawId);
impl_arena_id!(ConstId);
pub struct ConstId(salsa::InternId);
impl_intern_key!(ConstId);
impl AstItemDef<ast::ConstDef> for ConstId {
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::ConstDef>, Self> {
&interner.consts
fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::ConstDef>) -> Self {
db.intern_const(loc)
}
fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::ConstDef> {
db.lookup_intern_const(self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct StaticId(RawId);
impl_arena_id!(StaticId);
pub struct StaticId(salsa::InternId);
impl_intern_key!(StaticId);
impl AstItemDef<ast::StaticDef> for StaticId {
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::StaticDef>, Self> {
&interner.statics
fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::StaticDef>) -> Self {
db.intern_static(loc)
}
fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::StaticDef> {
db.lookup_intern_static(self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct TraitId(RawId);
impl_arena_id!(TraitId);
pub struct TraitId(salsa::InternId);
impl_intern_key!(TraitId);
impl AstItemDef<ast::TraitDef> for TraitId {
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TraitDef>, Self> {
&interner.traits
fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::TraitDef>) -> Self {
db.intern_trait(loc)
}
fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::TraitDef> {
db.lookup_intern_trait(self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct TypeAliasId(RawId);
impl_arena_id!(TypeAliasId);
pub struct TypeAliasId(salsa::InternId);
impl_intern_key!(TypeAliasId);
impl AstItemDef<ast::TypeAliasDef> for TypeAliasId {
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TypeAliasDef>, Self> {
&interner.types
fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::TypeAliasDef>) -> Self {
db.intern_type_alias(loc)
}
fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::TypeAliasDef> {
db.lookup_intern_type_alias(self)
}
}

View File

@ -55,7 +55,7 @@ pub use self::{
path::{Path, PathKind},
name::Name,
source_id::{AstIdMap, ErasedFileAstId},
ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc, HirInterner},
ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc},
nameres::{PerNs, Namespace, ImportId, ImportSource},
ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay},
impl_block::{ImplBlock, ImplItem},

View File

@ -9,7 +9,7 @@ use relative_path::RelativePathBuf;
use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset};
use rustc_hash::FxHashMap;
use crate::{db, HirInterner, diagnostics::DiagnosticSink};
use crate::{db, diagnostics::DiagnosticSink};
pub const WORKSPACE: SourceRootId = SourceRootId(0);
@ -18,7 +18,6 @@ pub const WORKSPACE: SourceRootId = SourceRootId(0);
pub struct MockDatabase {
events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>,
runtime: salsa::Runtime<MockDatabase>,
interner: Arc<HirInterner>,
files: FxHashMap<String, FileId>,
}
@ -195,7 +194,6 @@ impl Default for MockDatabase {
let mut db = MockDatabase {
events: Default::default(),
runtime: salsa::Runtime::default(),
interner: Default::default(),
files: FxHashMap::default(),
};
db.set_crate_graph(Default::default());
@ -208,19 +206,12 @@ impl salsa::ParallelDatabase for MockDatabase {
salsa::Snapshot::new(MockDatabase {
events: Default::default(),
runtime: self.runtime.snapshot(self),
interner: Arc::clone(&self.interner),
// only the root database can be used to get file_id by path.
files: FxHashMap::default(),
})
}
}
impl AsRef<HirInterner> for MockDatabase {
fn as_ref(&self) -> &HirInterner {
&self.interner
}
}
impl MockDatabase {
pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> {
*self.events.lock() = Some(Vec::new());

View File

@ -20,7 +20,6 @@ use crate::{LineIndex, symbol_index::{self, SymbolsDatabase}};
#[derive(Debug)]
pub(crate) struct RootDatabase {
runtime: salsa::Runtime<RootDatabase>,
interner: Arc<hir::HirInterner>,
pub(crate) last_gc: time::Instant,
pub(crate) last_gc_check: time::Instant,
}
@ -38,7 +37,6 @@ impl Default for RootDatabase {
fn default() -> RootDatabase {
let mut db = RootDatabase {
runtime: salsa::Runtime::default(),
interner: Default::default(),
last_gc: time::Instant::now(),
last_gc_check: time::Instant::now(),
};
@ -53,19 +51,12 @@ impl salsa::ParallelDatabase for RootDatabase {
fn snapshot(&self) -> salsa::Snapshot<RootDatabase> {
salsa::Snapshot::new(RootDatabase {
runtime: self.runtime.snapshot(self),
interner: Arc::clone(&self.interner),
last_gc: self.last_gc.clone(),
last_gc_check: self.last_gc_check.clone(),
})
}
}
impl AsRef<hir::HirInterner> for RootDatabase {
fn as_ref(&self) -> &hir::HirInterner {
&self.interner
}
}
#[salsa::query_group(LineIndexDatabaseStorage)]
pub(crate) trait LineIndexDatabase: ra_db::SourceDatabase + CheckCanceled {
fn line_index(&self, file_id: FileId) -> Arc<LineIndex>;

View File

@ -23,16 +23,11 @@ pub(crate) fn status(db: &RootDatabase) -> String {
let files_stats = db.query(FileTextQuery).entries::<FilesStats>();
let syntax_tree_stats = syntax_tree_stats(db);
let symbols_stats = db.query(LibrarySymbolsQuery).entries::<LibrarySymbolsStats>();
let n_defs = {
let interner: &hir::HirInterner = db.as_ref();
interner.len()
};
format!(
"{}\n{}\n{}\n{} defs\n\nmemory:\n{}\ngc {:?} seconds ago",
"{}\n{}\n{}\n\n\nmemory:\n{}\ngc {:?} seconds ago",
files_stats,
symbols_stats,
syntax_tree_stats,
n_defs,
MemoryStats::current(),
db.last_gc.elapsed().as_secs(),
)