From 9fa647c129d11efbf785e743ed0a1b06d9ff046b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 29 Apr 2025 19:25:11 +0200 Subject: [PATCH] Update salsa --- Cargo.lock | 12 ++-- Cargo.toml | 2 +- crates/base-db/src/lib.rs | 58 +++++++++++++++++-- crates/rust-analyzer/src/cli/rustc_tests.rs | 3 +- crates/rust-analyzer/src/diagnostics.rs | 4 +- crates/rust-analyzer/src/handlers/dispatch.rs | 18 +++--- crates/span/src/hygiene.rs | 9 +-- xtask/src/util.rs | 2 +- 8 files changed, 75 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9f6b80c637..1542084d72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2033,9 +2033,9 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "salsa" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be22155f8d9732518b2db2bf379fe6f0b2375e76b08b7c8fe6c1b887d548c24" +checksum = "4deeb38b4c80ac90a8d4796f83da941b0d76c23783550d15d37eb43ccddcb5bc" dependencies = [ "boxcar", "crossbeam-queue", @@ -2056,15 +2056,15 @@ dependencies = [ [[package]] name = "salsa-macro-rules" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55a7ef0a84e336f7c5f0332d81727f5629fe042d2aa556c75307afebc9f78a5" +checksum = "a4e6166fa2802d86a77dbcae1bfe75f0ac46fdf952660c233ed64855a53dd603" [[package]] name = "salsa-macros" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d0e88a9c0c0d231a63f83dcd1a2c5e5d11044fac4b65bc9ad3b68ab48b0a0ab" +checksum = "bf358e645a835d9901ee4d812d9812266e046ee92a28d2e37a73b7169a6503b7" dependencies = [ "heck", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 6fa171702d..191820d4e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -131,7 +131,7 @@ process-wrap = { version = "8.2.0", features = ["std"] } pulldown-cmark-to-cmark = "10.0.4" pulldown-cmark = { version = "0.9.6", default-features = false } rayon = "1.10.0" -salsa = "0.20.0" +salsa = "0.21.0" semver = "1.0.26" serde = { version = "1.0.219" } serde_derive = { version = "1.0.219" } diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index 1d73ba804a..9275a58687 100644 --- a/crates/base-db/src/lib.rs +++ b/crates/base-db/src/lib.rs @@ -3,7 +3,7 @@ mod change; mod input; -use std::hash::BuildHasherDefault; +use std::{cell::RefCell, hash::BuildHasherDefault, panic, sync::Once}; pub use crate::{ change::FileChange, @@ -60,7 +60,7 @@ impl Files { match self.files.get(&file_id) { Some(text) => *text, None => { - panic!("Unable to fetch file text for `vfs::FileId`: {:?}; this is a bug", file_id) + panic!("Unable to fetch file text for `vfs::FileId`: {file_id:?}; this is a bug") } } } @@ -101,8 +101,7 @@ impl Files { let source_root = match self.source_roots.get(&source_root_id) { Some(source_root) => source_root, None => panic!( - "Unable to fetch `SourceRootInput` with `SourceRootId` ({:?}); this is a bug", - source_root_id + "Unable to fetch `SourceRootInput` with `SourceRootId` ({source_root_id:?}); this is a bug" ), }; @@ -132,8 +131,7 @@ impl Files { let file_source_root = match self.file_source_roots.get(&id) { Some(file_source_root) => file_source_root, None => panic!( - "Unable to get `FileSourceRootInput` with `vfs::FileId` ({:?}); this is a bug", - id + "Unable to get `FileSourceRootInput` with `vfs::FileId` ({id:?}); this is a bug", ), }; *file_source_root @@ -384,3 +382,51 @@ fn relevant_crates(db: &dyn RootQueryDb, file_id: FileId) -> Arc<[Crate]> { let source_root = db.file_source_root(file_id); db.source_root_crates(source_root.source_root_id(db)) } + +#[must_use] +pub struct DbPanicContext { + // prevent arbitrary construction + _priv: (), +} + +impl Drop for DbPanicContext { + fn drop(&mut self) { + Self::with_ctx(|ctx| assert!(ctx.pop().is_some())); + } +} + +impl DbPanicContext { + pub fn enter(frame: String) -> DbPanicContext { + #[expect(clippy::print_stderr, reason = "already panicking anyway")] + fn set_hook() { + let default_hook = panic::take_hook(); + panic::set_hook(Box::new(move |panic_info| { + DbPanicContext::with_ctx(|ctx| { + if !ctx.is_empty() { + eprintln!("Panic context:"); + for frame in ctx.iter() { + eprintln!("> {frame}\n"); + } + } + }); + if let Some(backtrace) = salsa::Backtrace::capture() { + eprintln!("{backtrace}"); + } + default_hook(panic_info); + })); + } + + static SET_HOOK: Once = Once::new(); + SET_HOOK.call_once(set_hook); + + Self::with_ctx(|ctx| ctx.push(frame)); + DbPanicContext { _priv: () } + } + + fn with_ctx(f: impl FnOnce(&mut Vec)) { + thread_local! { + static CTX: RefCell> = const { RefCell::new(Vec::new()) }; + } + CTX.with(|ctx| f(&mut ctx.borrow_mut())); + } +} diff --git a/crates/rust-analyzer/src/cli/rustc_tests.rs b/crates/rust-analyzer/src/cli/rustc_tests.rs index c042c26bd1..e3b372c914 100644 --- a/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -7,6 +7,7 @@ use std::{cell::RefCell, fs::read_to_string, panic::AssertUnwindSafe, path::Path use hir::{ChangeWithProcMacros, Crate}; use ide::{AnalysisHost, DiagnosticCode, DiagnosticsConfig}; +use ide_db::base_db; use itertools::Either; use paths::Utf8PathBuf; use profile::StopWatch; @@ -310,7 +311,7 @@ impl flags::RustcTests { let tester = AssertUnwindSafe(&mut tester); let p = p.clone(); move || { - let _guard = stdx::panic_context::enter(p.display().to_string()); + let _guard = base_db::DbPanicContext::enter(p.display().to_string()); { tester }.0.test(p); } }) { diff --git a/crates/rust-analyzer/src/diagnostics.rs b/crates/rust-analyzer/src/diagnostics.rs index 9b1463b112..438a2a0ba1 100644 --- a/crates/rust-analyzer/src/diagnostics.rs +++ b/crates/rust-analyzer/src/diagnostics.rs @@ -5,7 +5,7 @@ use std::mem; use cargo_metadata::PackageId; use ide::FileId; -use ide_db::FxHashMap; +use ide_db::{FxHashMap, base_db::DbPanicContext}; use itertools::Itertools; use rustc_hash::FxHashSet; use stdx::iter_eq_by; @@ -215,7 +215,7 @@ pub(crate) fn fetch_native_diagnostics( kind: NativeDiagnosticsFetchKind, ) -> Vec<(FileId, Vec)> { let _p = tracing::info_span!("fetch_native_diagnostics").entered(); - let _ctx = stdx::panic_context::enter("fetch_native_diagnostics".to_owned()); + let _ctx = DbPanicContext::enter("fetch_native_diagnostics".to_owned()); // the diagnostics produced may point to different files not requested by the concrete request, // put those into here and filter later diff --git a/crates/rust-analyzer/src/handlers/dispatch.rs b/crates/rust-analyzer/src/handlers/dispatch.rs index 3b76edf528..f04ada3889 100644 --- a/crates/rust-analyzer/src/handlers/dispatch.rs +++ b/crates/rust-analyzer/src/handlers/dispatch.rs @@ -4,7 +4,10 @@ use std::{ panic, thread, }; -use ide_db::base_db::salsa::{self, Cancelled}; +use ide_db::base_db::{ + DbPanicContext, + salsa::{self, Cancelled}, +}; use lsp_server::{ExtractError, Response, ResponseError}; use serde::{Serialize, de::DeserializeOwned}; use stdx::thread::ThreadIntent; @@ -56,7 +59,7 @@ impl RequestDispatcher<'_> { tracing::info_span!("request", method = ?req.method, "request_id" = ?req.id).entered(); tracing::debug!(?params); let result = { - let _pctx = stdx::panic_context::enter(panic_context); + let _pctx = DbPanicContext::enter(panic_context); f(self.global_state, params) }; if let Ok(response) = result_to_response::(req.id, result) { @@ -86,7 +89,7 @@ impl RequestDispatcher<'_> { let global_state_snapshot = self.global_state.snapshot(); let result = panic::catch_unwind(move || { - let _pctx = stdx::panic_context::enter(panic_context); + let _pctx = DbPanicContext::enter(panic_context); f(global_state_snapshot, params) }); @@ -257,7 +260,7 @@ impl RequestDispatcher<'_> { } .spawn(intent, move || { let result = panic::catch_unwind(move || { - let _pctx = stdx::panic_context::enter(panic_context); + let _pctx = DbPanicContext::enter(panic_context); f(world, params) }); match thread_result_to_response::(req.id.clone(), result) { @@ -421,11 +424,8 @@ impl NotificationDispatcher<'_> { tracing::debug!(?params); - let _pctx = stdx::panic_context::enter(format!( - "\nversion: {}\nnotification: {}", - version(), - N::METHOD - )); + let _pctx = + DbPanicContext::enter(format!("\nversion: {}\nnotification: {}", version(), N::METHOD)); if let Err(e) = f(self.global_state, params) { tracing::error!(handler = %N::METHOD, error = %e, "notification handler failed"); } diff --git a/crates/span/src/hygiene.rs b/crates/span/src/hygiene.rs index d1e75d97d7..7bb88ac365 100644 --- a/crates/span/src/hygiene.rs +++ b/crates/span/src/hygiene.rs @@ -94,16 +94,11 @@ const _: () = { } } impl zalsa_struct_::Configuration for SyntaxContext { + const LOCATION: salsa::plumbing::Location = + salsa::plumbing::Location { file: file!(), line: line!() }; const DEBUG_NAME: &'static str = "SyntaxContextData"; type Fields<'a> = SyntaxContextData; type Struct<'a> = SyntaxContext; - fn struct_from_id<'db>(id: salsa::Id) -> Self::Struct<'db> { - SyntaxContext::from_salsa_id(id) - } - fn deref_struct(s: Self::Struct<'_>) -> salsa::Id { - s.as_salsa_id() - .expect("`SyntaxContext::deref_structs()` called on a root `SyntaxContext`") - } } impl SyntaxContext { pub fn ingredient(db: &Db) -> &zalsa_struct_::IngredientImpl diff --git a/xtask/src/util.rs b/xtask/src/util.rs index a740ad6afd..e5404d5717 100644 --- a/xtask/src/util.rs +++ b/xtask/src/util.rs @@ -37,7 +37,7 @@ pub(crate) fn detect_target(sh: &Shell) -> String { Ok(target) => target, _ => match cmd!(sh, "rustc --print=host-tuple").read() { Ok(target) => target, - Err(e) => panic!("Failed to detect target: {}\nPlease set RA_TARGET explicitly", e), + Err(e) => panic!("Failed to detect target: {e}\nPlease set RA_TARGET explicitly"), }, } }