Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--Cargo.lock12
-rw-r--r--Cargo.toml2
-rw-r--r--crates/base-db/src/lib.rs58
-rw-r--r--crates/rust-analyzer/src/cli/rustc_tests.rs3
-rw-r--r--crates/rust-analyzer/src/diagnostics.rs4
-rw-r--r--crates/rust-analyzer/src/handlers/dispatch.rs18
-rw-r--r--crates/span/src/hygiene.rs9
-rw-r--r--xtask/src/util.rs2
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<String>)) {
+ thread_local! {
+ static CTX: RefCell<Vec<String>> = 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<lsp_types::Diagnostic>)> {
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::<R>(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::<R>(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: &Db) -> &zalsa_struct_::IngredientImpl<Self>
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"),
},
}
}