aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_db/src/lib.rs16
-rw-r--r--crates/ra_hir/src/module_tree.rs4
-rw-r--r--crates/ra_hir/src/nameres.rs2
-rw-r--r--crates/ra_hir/src/ty.rs2
-rw-r--r--crates/ra_ide_api/src/symbol_index.rs2
5 files changed, 19 insertions, 7 deletions
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index 0e7f32e66..8473fc050 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -21,11 +21,23 @@ pub use crate::{
21}; 21};
22 22
23pub trait BaseDatabase: salsa::Database + panic::RefUnwindSafe { 23pub trait BaseDatabase: salsa::Database + panic::RefUnwindSafe {
24 fn check_canceled(&self) -> Cancelable<()> { 24 /// Aborts current query if there are pending changes.
25 ///
26 /// rust-analyzer needs to be able to answer semantic questions about the
27 /// code while the code is being modified. A common problem is that a
28 /// long-running query is being calculated when a new change arrives.
29 ///
30 /// We can't just apply the change immediately: this will cause the pending
31 /// query to see inconsistent state (it will observe an absence of
32 /// repeatable read). So what we do is we **cancel** all pending queries
33 /// before applying the change.
34 ///
35 /// We implement cancellation by panicking with a special value and catching
36 /// it on the API boundary. Salsa explicitly supports this use-case.
37 fn check_canceled(&self) {
25 if self.salsa_runtime().is_current_revision_canceled() { 38 if self.salsa_runtime().is_current_revision_canceled() {
26 Canceled::throw() 39 Canceled::throw()
27 } 40 }
28 Ok(())
29 } 41 }
30 42
31 fn catch_canceled<F: FnOnce(&Self) -> T + panic::UnwindSafe, T>( 43 fn catch_canceled<F: FnOnce(&Self) -> T + panic::UnwindSafe, T>(
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs
index 67823e970..fd5a92c5b 100644
--- a/crates/ra_hir/src/module_tree.rs
+++ b/crates/ra_hir/src/module_tree.rs
@@ -42,7 +42,7 @@ impl Submodule {
42 db: &impl HirDatabase, 42 db: &impl HirDatabase,
43 source: SourceItemId, 43 source: SourceItemId,
44 ) -> Cancelable<Arc<Vec<Submodule>>> { 44 ) -> Cancelable<Arc<Vec<Submodule>>> {
45 db.check_canceled()?; 45 db.check_canceled();
46 let file_id = source.file_id; 46 let file_id = source.file_id;
47 let file_items = db.file_items(file_id); 47 let file_items = db.file_items(file_id);
48 let module_source = ModuleSource::from_source_item_id(db, source); 48 let module_source = ModuleSource::from_source_item_id(db, source);
@@ -117,7 +117,7 @@ impl ModuleTree {
117 db: &impl HirDatabase, 117 db: &impl HirDatabase,
118 source_root: SourceRootId, 118 source_root: SourceRootId,
119 ) -> Cancelable<Arc<ModuleTree>> { 119 ) -> Cancelable<Arc<ModuleTree>> {
120 db.check_canceled()?; 120 db.check_canceled();
121 let res = create_module_tree(db, source_root); 121 let res = create_module_tree(db, source_root);
122 Ok(Arc::new(res?)) 122 Ok(Arc::new(res?))
123 } 123 }
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 6bf949654..edb3b1e64 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -327,7 +327,7 @@ where
327 loop { 327 loop {
328 let processed_imports_count = self.processed_imports.len(); 328 let processed_imports_count = self.processed_imports.len();
329 for &module_id in self.input.keys() { 329 for &module_id in self.input.keys() {
330 self.db.check_canceled()?; 330 self.db.check_canceled();
331 self.resolve_imports(module_id)?; 331 self.resolve_imports(module_id)?;
332 } 332 }
333 if processed_imports_count == self.processed_imports.len() { 333 if processed_imports_count == self.processed_imports.len() {
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 5579db8fb..03787bd89 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -1203,7 +1203,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1203} 1203}
1204 1204
1205pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceResult>> { 1205pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceResult>> {
1206 db.check_canceled()?; 1206 db.check_canceled();
1207 let function = Function::new(def_id); // TODO: consts also need inference 1207 let function = Function::new(def_id); // TODO: consts also need inference
1208 let body = function.body(db)?; 1208 let body = function.body(db)?;
1209 let scopes = db.fn_scopes(def_id)?; 1209 let scopes = db.fn_scopes(def_id)?;
diff --git a/crates/ra_ide_api/src/symbol_index.rs b/crates/ra_ide_api/src/symbol_index.rs
index fdda57022..b7a3a3550 100644
--- a/crates/ra_ide_api/src/symbol_index.rs
+++ b/crates/ra_ide_api/src/symbol_index.rs
@@ -54,7 +54,7 @@ salsa::query_group! {
54} 54}
55 55
56fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Cancelable<Arc<SymbolIndex>> { 56fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Cancelable<Arc<SymbolIndex>> {
57 db.check_canceled()?; 57 db.check_canceled();
58 let source_file = db.source_file(file_id); 58 let source_file = db.source_file(file_id);
59 let mut symbols = source_file 59 let mut symbols = source_file
60 .syntax() 60 .syntax()