diff --git a/Cargo.lock b/Cargo.lock index 42eaeb01f1f2..d1e9c373cbf8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2448,8 +2448,6 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "salsa" version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e2aa2fca57727371eeafc975acc8e6f4c52f8166a78035543f6ee1c74c2dcc" dependencies = [ "boxcar", "crossbeam-queue", @@ -2473,14 +2471,10 @@ dependencies = [ [[package]] name = "salsa-macro-rules" version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfc2a1e7bf06964105515451d728f2422dedc3a112383324a00b191a5c397a3" [[package]] name = "salsa-macros" version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d844c1aa34946da46af683b5c27ec1088a3d9d84a2b837a108223fd830220e1" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 8003cb2fba8e..40125b6ebf14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,9 +44,9 @@ debug = 2 # ungrammar = { path = "lin/ungrammar" } -# salsa = { path = "../salsa" } -# salsa-macros = { path = "../salsa/components/salsa-macros" } -# salsa-macro-rules = { path = "../salsa/components/salsa-macro-rules" } +salsa = { path = "../salsa" } +salsa-macros = { path = "../salsa/components/salsa-macros" } +salsa-macro-rules = { path = "../salsa/components/salsa-macro-rules" } [workspace.dependencies] # local crates diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 930eaf2262d9..2e618550f92f 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -67,7 +67,7 @@ use ide_db::{ FxHashMap, FxIndexSet, LineIndexDatabase, base_db::{ CrateOrigin, CrateWorkspaceData, Env, FileSet, RootQueryDb, SourceDatabase, VfsPath, - salsa::{Cancelled, Database}, + salsa::{CancellationToken, Cancelled, Database}, }, prime_caches, symbol_index, }; @@ -947,6 +947,10 @@ impl Analysis { // We use `attach_db_allow_change()` and not `attach_db()` because fixture injection can change the database. hir::attach_db_allow_change(&self.db, || Cancelled::catch(|| f(&self.db))) } + + pub fn cancellation_token(&self) -> CancellationToken { + self.db.cancellation_token() + } } #[test] diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 9beab3c0e45c..68368b582a09 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -15,7 +15,7 @@ use hir::ChangeWithProcMacros; use ide::{Analysis, AnalysisHost, Cancellable, FileId, SourceRootId}; use ide_db::{ MiniCore, - base_db::{Crate, ProcMacroPaths, SourceDatabase, salsa::Revision}, + base_db::{Crate, ProcMacroPaths, SourceDatabase, salsa::CancellationToken, salsa::Revision}, }; use itertools::Itertools; use load_cargo::SourceRootConfig; @@ -89,6 +89,7 @@ pub(crate) struct GlobalState { pub(crate) task_pool: Handle, Receiver>, pub(crate) fmt_pool: Handle, Receiver>, pub(crate) cancellation_pool: thread::Pool, + pub(crate) cancellation_tokens: FxHashMap, pub(crate) config: Arc, pub(crate) config_errors: Option, @@ -265,6 +266,7 @@ impl GlobalState { task_pool, fmt_pool, cancellation_pool, + cancellation_tokens: Default::default(), loader, config: Arc::new(config.clone()), analysis_host, @@ -616,6 +618,7 @@ impl GlobalState { } pub(crate) fn respond(&mut self, response: lsp_server::Response) { + self.cancellation_tokens.remove(&response.id); if let Some((method, start)) = self.req_queue.incoming.complete(&response.id) { if let Some(err) = &response.error && err.message.starts_with("server panicked") @@ -630,6 +633,9 @@ impl GlobalState { } pub(crate) fn cancel(&mut self, request_id: lsp_server::RequestId) { + if let Some(token) = self.cancellation_tokens.remove(&request_id) { + token.cancel(); + } if let Some(response) = self.req_queue.incoming.cancel(request_id) { self.send(response.into()); } diff --git a/crates/rust-analyzer/src/handlers/dispatch.rs b/crates/rust-analyzer/src/handlers/dispatch.rs index 10bbb0bb31d9..b2d216858dc4 100644 --- a/crates/rust-analyzer/src/handlers/dispatch.rs +++ b/crates/rust-analyzer/src/handlers/dispatch.rs @@ -253,6 +253,9 @@ impl RequestDispatcher<'_> { tracing::debug!(?params); let world = self.global_state.snapshot(); + self.global_state + .cancellation_tokens + .insert(req.id.clone(), world.analysis.cancellation_token()); if RUSTFMT { &mut self.global_state.fmt_pool.handle } else { @@ -265,7 +268,19 @@ impl RequestDispatcher<'_> { }); match thread_result_to_response::(req.id.clone(), result) { Ok(response) => Task::Response(response), - Err(_cancelled) if ALLOW_RETRYING => Task::Retry(req), + Err(HandlerCancelledError::Inner( + Cancelled::PendingWrite | Cancelled::PropagatedPanic, + )) if ALLOW_RETRYING => Task::Retry(req), + // Note: Technically the return value here does not matter as we have already responded to the client with this error. + Err(HandlerCancelledError::Inner(Cancelled::Local)) => Task::Response(Response { + id: req.id, + result: None, + error: Some(ResponseError { + code: ErrorCode::RequestCanceled as i32, + message: "canceled by client".to_owned(), + data: None, + }), + }), Err(_cancelled) => { let error = on_cancelled(); Task::Response(Response { id: req.id, result: None, error: Some(error) })