diff --git a/Cargo.lock b/Cargo.lock index e3384ec5e1..2ec41817dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3445,7 +3445,7 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "salsa" version = "0.21.0" -source = "git+https://github.com/salsa-rs/salsa.git?rev=af811a34cef26932859b09bbefe50fbd8e8db06a#af811a34cef26932859b09bbefe50fbd8e8db06a" +source = "git+https://github.com/salsa-rs/salsa.git?rev=79afd59ed5a5edb4dac63cf5b6cf4a6aa9514bdf#79afd59ed5a5edb4dac63cf5b6cf4a6aa9514bdf" dependencies = [ "boxcar", "compact_str", @@ -3468,12 +3468,12 @@ dependencies = [ [[package]] name = "salsa-macro-rules" version = "0.21.0" -source = "git+https://github.com/salsa-rs/salsa.git?rev=af811a34cef26932859b09bbefe50fbd8e8db06a#af811a34cef26932859b09bbefe50fbd8e8db06a" +source = "git+https://github.com/salsa-rs/salsa.git?rev=79afd59ed5a5edb4dac63cf5b6cf4a6aa9514bdf#79afd59ed5a5edb4dac63cf5b6cf4a6aa9514bdf" [[package]] name = "salsa-macros" version = "0.21.0" -source = "git+https://github.com/salsa-rs/salsa.git?rev=af811a34cef26932859b09bbefe50fbd8e8db06a#af811a34cef26932859b09bbefe50fbd8e8db06a" +source = "git+https://github.com/salsa-rs/salsa.git?rev=79afd59ed5a5edb4dac63cf5b6cf4a6aa9514bdf#79afd59ed5a5edb4dac63cf5b6cf4a6aa9514bdf" dependencies = [ "heck", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 4893c4cad6..57934aed25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -124,7 +124,7 @@ rayon = { version = "1.10.0" } regex = { version = "1.10.2" } rustc-hash = { version = "2.0.0" } # When updating salsa, make sure to also update the revision in `fuzz/Cargo.toml` -salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "af811a34cef26932859b09bbefe50fbd8e8db06a" } +salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "79afd59ed5a5edb4dac63cf5b6cf4a6aa9514bdf" } schemars = { version = "0.8.16" } seahash = { version = "4.1.0" } serde = { version = "1.0.197", features = ["derive"] } diff --git a/crates/red_knot_project/src/lib.rs b/crates/red_knot_project/src/lib.rs index 25897e6d72..cf953f2b26 100644 --- a/crates/red_knot_project/src/lib.rs +++ b/crates/red_knot_project/src/lib.rs @@ -20,6 +20,7 @@ use ruff_db::system::{SystemPath, SystemPathBuf}; use rustc_hash::FxHashSet; use salsa::Durability; use salsa::Setter; +use std::backtrace::BacktraceStatus; use std::panic::{AssertUnwindSafe, UnwindSafe}; use std::sync::Arc; use thiserror::Error; @@ -626,10 +627,27 @@ where )); if let Some(backtrace) = error.backtrace { - diagnostic.sub(SubDiagnostic::new( - Severity::Info, - format!("Backtrace:\n{backtrace}"), - )); + match backtrace.status() { + BacktraceStatus::Disabled => { + diagnostic.sub(SubDiagnostic::new( + Severity::Info, + "run with `RUST_BACKTRACE=1` environment variable to show the full backtrace information", + )); + } + BacktraceStatus::Captured => { + diagnostic.sub(SubDiagnostic::new( + Severity::Info, + format!("Backtrace:\n{backtrace}"), + )); + } + _ => {} + } + } + + if let Some(backtrace) = error.salsa_backtrace { + salsa::attach(db, || { + diagnostic.sub(SubDiagnostic::new(Severity::Info, backtrace.to_string())); + }); } Err(diagnostic) diff --git a/crates/red_knot_python_semantic/src/types/infer.rs b/crates/red_knot_python_semantic/src/types/infer.rs index db5b2a5319..6016308878 100644 --- a/crates/red_knot_python_semantic/src/types/infer.rs +++ b/crates/red_knot_python_semantic/src/types/infer.rs @@ -8483,7 +8483,7 @@ mod tests { db.clear_salsa_events(); assert_file_diagnostics(&db, "src/a.py", &[]); let events = db.take_salsa_events(); - let cycles = salsa::plumbing::attach(&db, || { + let cycles = salsa::attach(&db, || { events .iter() .filter_map(|event| { diff --git a/crates/red_knot_test/src/lib.rs b/crates/red_knot_test/src/lib.rs index f57c559b87..66772c113c 100644 --- a/crates/red_knot_test/src/lib.rs +++ b/crates/red_knot_test/src/lib.rs @@ -18,6 +18,7 @@ use ruff_db::parsed::parsed_module; use ruff_db::system::{DbWithWritableSystem as _, SystemPath, SystemPathBuf}; use ruff_db::testing::{setup_logging, setup_logging_with_filter}; use ruff_source_file::{LineIndex, OneIndexed}; +use std::backtrace::BacktraceStatus; use std::fmt::Write; mod assertion; @@ -331,10 +332,24 @@ fn run_test( None => messages.push("Box".to_string()), } if let Some(backtrace) = info.backtrace { - if std::env::var("RUST_BACKTRACE").is_ok() { - messages.extend(backtrace.to_string().split('\n').map(String::from)); + match backtrace.status() { + BacktraceStatus::Disabled => { + let msg = "run with `RUST_BACKTRACE=1` environment variable to display a backtrace"; + messages.push(msg.to_string()); + } + BacktraceStatus::Captured => { + messages.extend(backtrace.to_string().split('\n').map(String::from)); + } + _ => {} } } + + if let Some(backtrace) = info.salsa_backtrace { + salsa::attach(db, || { + messages.extend(backtrace.to_string().split('\n').map(String::from)); + }); + } + by_line.push(OneIndexed::from_zero_indexed(0), messages); return Some(FileFailures { backtick_offsets: test_file.backtick_offsets, diff --git a/crates/ruff/src/commands/format.rs b/crates/ruff/src/commands/format.rs index 66648fc42a..6b1f5206f4 100644 --- a/crates/ruff/src/commands/format.rs +++ b/crates/ruff/src/commands/format.rs @@ -160,7 +160,7 @@ pub(crate) fn format( }), Err(error) => Err(FormatCommandError::Panic( Some(resolved_file.path().to_path_buf()), - error, + Box::new(error), )), }, ) @@ -635,7 +635,7 @@ impl<'a> FormatResults<'a> { pub(crate) enum FormatCommandError { Ignore(#[from] ignore::Error), Parse(#[from] DisplayParseError), - Panic(Option, PanicError), + Panic(Option, Box), Read(Option, SourceError), Format(Option, FormatModuleError), Write(Option, SourceError), diff --git a/crates/ruff_db/src/panic.rs b/crates/ruff_db/src/panic.rs index 3deda2d741..67ebf940dc 100644 --- a/crates/ruff_db/src/panic.rs +++ b/crates/ruff_db/src/panic.rs @@ -1,3 +1,4 @@ +use std::backtrace::BacktraceStatus; use std::cell::Cell; use std::panic::Location; use std::sync::OnceLock; @@ -7,6 +8,7 @@ pub struct PanicError { pub location: Option, pub payload: Payload, pub backtrace: Option, + pub salsa_backtrace: Option, } #[derive(Debug)] @@ -34,15 +36,35 @@ impl std::fmt::Display for PanicError { write!(f, ":\n{payload}")?; } if let Some(backtrace) = &self.backtrace { - writeln!(f, "\nBacktrace: {backtrace}")?; + match backtrace.status() { + BacktraceStatus::Disabled => { + writeln!( + f, + "\nrun with `RUST_BACKTRACE=1` environment variable to display a backtrace" + )?; + } + BacktraceStatus::Captured => { + writeln!(f, "\nBacktrace: {backtrace}")?; + } + _ => {} + } } Ok(()) } } +#[derive(Default)] +struct CapturedPanicInfo { + backtrace: Option, + location: Option, + salsa_backtrace: Option, +} + thread_local! { static CAPTURE_PANIC_INFO: Cell = const { Cell::new(false) }; - static LAST_BACKTRACE: Cell<(Option, Option)> = const { Cell::new((None, None)) }; + static LAST_BACKTRACE: Cell = const { + Cell::new(CapturedPanicInfo { backtrace: None, location: None, salsa_backtrace: None }) + }; } fn install_hook() { @@ -56,9 +78,13 @@ fn install_hook() { } let location = info.location().map(Location::to_string); - let backtrace = Some(std::backtrace::Backtrace::force_capture()); + let backtrace = Some(std::backtrace::Backtrace::capture()); - LAST_BACKTRACE.set((backtrace, location)); + LAST_BACKTRACE.set(CapturedPanicInfo { + backtrace, + location, + salsa_backtrace: salsa::Backtrace::capture(), + }); })); }); } @@ -92,12 +118,17 @@ where // Because of that, always take the payload from `catch_unwind` because it may have been transformed // by an inner `std::panic::catch_unwind` handlers and only use the information // from the custom handler to enrich the error with the backtrace and location. - let (backtrace, location) = LAST_BACKTRACE.with(Cell::take); + let CapturedPanicInfo { + location, + backtrace, + salsa_backtrace, + } = LAST_BACKTRACE.with(Cell::take); PanicError { location, payload: Payload(payload), backtrace, + salsa_backtrace, } }); CAPTURE_PANIC_INFO.set(prev_should_capture); diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 315805460c..c8a4a9c7a4 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -29,7 +29,7 @@ ruff_python_formatter = { path = "../crates/ruff_python_formatter" } ruff_text_size = { path = "../crates/ruff_text_size" } libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer", default-features = false } -salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "af811a34cef26932859b09bbefe50fbd8e8db06a" } +salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "79afd59ed5a5edb4dac63cf5b6cf4a6aa9514bdf" } similar = { version = "2.5.0" } tracing = { version = "0.1.40" }