Skip to content

Commit 2de8313

Browse files
committed
[ty] Run background tasks with panic handler
1 parent 82cd88d commit 2de8313

File tree

9 files changed

+124
-70
lines changed

9 files changed

+124
-70
lines changed

crates/ruff_benchmark/benches/ty.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ fn benchmark_incremental(criterion: &mut Criterion) {
131131
fn setup() -> Case {
132132
let case = setup_tomllib_case();
133133

134-
let result: Vec<_> = case.db.check().unwrap();
134+
let result: Vec<_> = case.db.check();
135135

136136
assert_diagnostics(&case.db, &result, EXPECTED_TOMLLIB_DIAGNOSTICS);
137137

@@ -159,7 +159,7 @@ fn benchmark_incremental(criterion: &mut Criterion) {
159159
None,
160160
);
161161

162-
let result = db.check().unwrap();
162+
let result = db.check();
163163

164164
assert_eq!(result.len(), EXPECTED_TOMLLIB_DIAGNOSTICS.len());
165165
}
@@ -179,7 +179,7 @@ fn benchmark_cold(criterion: &mut Criterion) {
179179
setup_tomllib_case,
180180
|case| {
181181
let Case { db, .. } = case;
182-
let result: Vec<_> = db.check().unwrap();
182+
let result: Vec<_> = db.check();
183183

184184
assert_diagnostics(db, &result, EXPECTED_TOMLLIB_DIAGNOSTICS);
185185
},
@@ -293,7 +293,7 @@ fn benchmark_many_string_assignments(criterion: &mut Criterion) {
293293
},
294294
|case| {
295295
let Case { db, .. } = case;
296-
let result = db.check().unwrap();
296+
let result = db.check();
297297
assert_eq!(result.len(), 0);
298298
},
299299
BatchSize::SmallInput,
@@ -339,7 +339,7 @@ fn benchmark_many_tuple_assignments(criterion: &mut Criterion) {
339339
},
340340
|case| {
341341
let Case { db, .. } = case;
342-
let result = db.check().unwrap();
342+
let result = db.check();
343343
assert_eq!(result.len(), 0);
344344
},
345345
BatchSize::SmallInput,

crates/ruff_db/src/panic.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::any::Any;
12
use std::backtrace::BacktraceStatus;
23
use std::cell::Cell;
34
use std::panic::Location;
@@ -24,17 +25,25 @@ impl Payload {
2425
None
2526
}
2627
}
28+
29+
pub fn downcast_ref<R: Any>(&self) -> Option<&R> {
30+
self.0.downcast_ref::<R>()
31+
}
2732
}
2833

2934
impl std::fmt::Display for PanicError {
3035
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31-
writeln!(f, "panicked at")?;
36+
write!(f, "panicked at")?;
3237
if let Some(location) = &self.location {
3338
write!(f, " {location}")?;
3439
}
3540
if let Some(payload) = self.payload.as_str() {
3641
write!(f, ":\n{payload}")?;
3742
}
43+
if let Some(query_trace) = self.salsa_backtrace.as_ref() {
44+
let _ = writeln!(f, "{query_trace}");
45+
}
46+
3847
if let Some(backtrace) = &self.backtrace {
3948
match backtrace.status() {
4049
BacktraceStatus::Disabled => {
@@ -49,6 +58,7 @@ impl std::fmt::Display for PanicError {
4958
_ => {}
5059
}
5160
}
61+
5262
Ok(())
5363
}
5464
}

crates/ty/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,12 +243,14 @@ impl MainLoop {
243243
MainLoopMessage::CheckWorkspace => {
244244
let db = db.clone();
245245
let sender = self.sender.clone();
246-
let mut reporter = R::default();
247246

248247
// Spawn a new task that checks the project. This needs to be done in a separate thread
249248
// to prevent blocking the main loop here.
250249
rayon::spawn(move || {
251-
match db.check_with_reporter(&mut reporter) {
250+
match salsa::Cancelled::catch(|| {
251+
let mut reporter = R::default();
252+
db.check_with_reporter(&mut reporter)
253+
}) {
252254
Ok(result) => {
253255
// Send the result back to the main loop for printing.
254256
sender

crates/ty/tests/file_watching.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,7 @@ print(sys.last_exc, os.getegid())
11351135
Ok(())
11361136
})?;
11371137

1138-
let diagnostics = case.db.check().context("Failed to check project.")?;
1138+
let diagnostics = case.db.check();
11391139

11401140
assert_eq!(diagnostics.len(), 2);
11411141
assert_eq!(
@@ -1160,7 +1160,7 @@ print(sys.last_exc, os.getegid())
11601160
})
11611161
.expect("Search path settings to be valid");
11621162

1163-
let diagnostics = case.db.check().context("Failed to check project.")?;
1163+
let diagnostics = case.db.check();
11641164
assert!(diagnostics.is_empty());
11651165

11661166
Ok(())
@@ -1763,10 +1763,7 @@ fn changes_to_user_configuration() -> anyhow::Result<()> {
17631763
let foo = case
17641764
.system_file(case.project_path("foo.py"))
17651765
.expect("foo.py to exist");
1766-
let diagnostics = case
1767-
.db()
1768-
.check_file(foo)
1769-
.context("Failed to check project.")?;
1766+
let diagnostics = case.db().check_file(foo);
17701767

17711768
assert!(
17721769
diagnostics.is_empty(),
@@ -1786,10 +1783,7 @@ fn changes_to_user_configuration() -> anyhow::Result<()> {
17861783

17871784
case.apply_changes(changes);
17881785

1789-
let diagnostics = case
1790-
.db()
1791-
.check_file(foo)
1792-
.context("Failed to check project.")?;
1786+
let diagnostics = case.db().check_file(foo);
17931787

17941788
assert!(
17951789
diagnostics.len() == 1,

crates/ty_project/src/db.rs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use ruff_db::files::{File, Files};
88
use ruff_db::system::System;
99
use ruff_db::vendored::VendoredFileSystem;
1010
use ruff_db::{Db as SourceDb, Upcast};
11+
use salsa::Event;
1112
use salsa::plumbing::ZalsaDatabase;
12-
use salsa::{Cancelled, Event};
1313
use ty_ide::Db as IdeDb;
1414
use ty_python_semantic::lint::{LintRegistry, RuleSelection};
1515
use ty_python_semantic::{Db as SemanticDb, Program};
@@ -76,24 +76,21 @@ impl ProjectDatabase {
7676
}
7777

7878
/// Checks all open files in the project and its dependencies.
79-
pub fn check(&self) -> Result<Vec<Diagnostic>, Cancelled> {
79+
pub fn check(&self) -> Vec<Diagnostic> {
8080
let mut reporter = DummyReporter;
8181
let reporter = AssertUnwindSafe(&mut reporter as &mut dyn Reporter);
82-
self.with_db(|db| db.project().check(db, reporter))
82+
self.project().check(self, reporter)
8383
}
8484

8585
/// Checks all open files in the project and its dependencies, using the given reporter.
86-
pub fn check_with_reporter(
87-
&self,
88-
reporter: &mut dyn Reporter,
89-
) -> Result<Vec<Diagnostic>, Cancelled> {
86+
pub fn check_with_reporter(&self, reporter: &mut dyn Reporter) -> Vec<Diagnostic> {
9087
let reporter = AssertUnwindSafe(reporter);
91-
self.with_db(|db| db.project().check(db, reporter))
88+
self.project().check(self, reporter)
9289
}
9390

9491
#[tracing::instrument(level = "debug", skip(self))]
95-
pub fn check_file(&self, file: File) -> Result<Vec<Diagnostic>, Cancelled> {
96-
self.with_db(|db| self.project().check_file(db, file))
92+
pub fn check_file(&self, file: File) -> Vec<Diagnostic> {
93+
self.project().check_file(self, file)
9794
}
9895

9996
/// Returns a mutable reference to the system.
@@ -107,13 +104,6 @@ impl ProjectDatabase {
107104
Arc::get_mut(&mut self.system)
108105
.expect("ref count should be 1 because `zalsa_mut` drops all other DB references.")
109106
}
110-
111-
pub(crate) fn with_db<F, T>(&self, f: F) -> Result<T, Cancelled>
112-
where
113-
F: FnOnce(&ProjectDatabase) -> T + std::panic::UnwindSafe,
114-
{
115-
Cancelled::catch(|| f(self))
116-
}
117107
}
118108

119109
impl Upcast<dyn SemanticDb> for ProjectDatabase {

crates/ty_server/src/server.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
//! Scheduling, I/O, and API endpoints.
22
3-
use std::num::NonZeroUsize;
4-
// The new PanicInfoHook name requires MSRV >= 1.82
5-
#[expect(deprecated)]
6-
use std::panic::PanicInfo;
7-
83
use lsp_server::Message;
94
use lsp_types::{
105
ClientCapabilities, DiagnosticOptions, DiagnosticServerCapabilities,
@@ -13,6 +8,8 @@ use lsp_types::{
138
TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions,
149
TypeDefinitionProviderCapability, Url,
1510
};
11+
use std::num::NonZeroUsize;
12+
use std::panic::PanicHookInfo;
1613

1714
use self::connection::{Connection, ConnectionInitializer};
1815
use self::schedule::event_loop_thread;
@@ -125,9 +122,7 @@ impl Server {
125122
}
126123

127124
pub(crate) fn run(self) -> crate::Result<()> {
128-
// The new PanicInfoHook name requires MSRV >= 1.82
129-
#[expect(deprecated)]
130-
type PanicHook = Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>;
125+
type PanicHook = Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send>;
131126
struct RestorePanicHook {
132127
hook: Option<PanicHook>,
133128
}

0 commit comments

Comments
 (0)