rust-lang / rust-analyzer

A Rust compiler front-end for IDEs
https://rust-analyzer.github.io/
Apache License 2.0
14.39k stars 1.62k forks source link

Split HirDatabase into volatile an persistent parts #706

Closed matklad closed 5 years ago

matklad commented 5 years ago

Although salsa is a great framework for incremental computation, most IDE computations are lazy, but not incremental. Specifically, stuff like per-function type inference does not really needs to be incremental, however it must be lazy (that is, for completion, we should be able to infer type of a single function only).

Salsa supports purely lazy computations via volatile queries, but they don't jibe to well with inremental queries (a volatile dependency causes everything to be recomputed).

So we should split HirDatabase into two PersisrentHirDatabase (for stuff like modules) and HirDatabase: PersistentHirDatabase, which includes volatile queries for type-inference, etc.

Specifically, this trait should be split into

trait PersistentDatabase {
    fn hir_parse(&self, file_id: HirFileId) -> TreeArc<SourceFile>;
    fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>;
    fn struct_data(&self, s: Struct) -> Arc<StructData>;
    fn enum_data(&self, e: Enum) -> Arc<EnumData>;
    fn fn_signature(&self, func: Function) -> Arc<FnSignature>;
    fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>;
    fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>;
    fn submodules(
        &self,
        file_id: HirFileId,
        delc_id: Option<SourceFileItemId>,
    ) -> Arc<Vec<crate::module_tree::Submodule>>;
    fn lower_module(&self, module: Module) -> (Arc<LoweredModule>, Arc<ImportSourceMap>);
    fn lower_module_module(&self, module: Module) -> Arc<LoweredModule>;
    fn lower_module_source_map(&self, module: Module) -> Arc<ImportSourceMap>;
    fn item_map(&self, crate_id: CrateId) -> Arc<ItemMap>;
    fn module_tree(&self, crate_id: CrateId) -> Arc<ModuleTree>;
    fn impls_in_module(&self, module: Module) -> Arc<ModuleImplBlocks>;
    fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;
}

and

trait HirDatabase: PersistentHirDatabase {
    fn fn_scopes(&self, func: Function) -> Arc<FnScopes>;
    fn infer(&self, func: Function) -> Arc<InferenceResult>;
    fn type_for_def(&self, def: TypableDef) -> Ty;
    fn type_for_field(&self, field: StructField) -> Ty;
    fn file_item(&self, source_item_id: SourceItemId) -> TreeArc<SyntaxNode>;
    fn body_hir(&self, func: Function) -> Arc<crate::expr::Body>;
    fn body_syntax_mapping(&self, func: Function) -> Arc<crate::expr::BodySyntaxMapping>;
}

query defenitions and code_model should be adjusted to use the correct database.

csmoe commented 5 years ago

working on this.

csmoe commented 5 years ago

https://github.com/rust-analyzer/rust-analyzer/blob/1bf47d43db631e096a0125b596fccad021ce6c2c/crates/ra_hir/src/db.rs#L31 @matklad should this new query be persistent?

matklad commented 5 years ago

Nope