Skip to content

Commit 4ecab09

Browse files
bors[bot]matklad
andauthored
Merge #6093
6093: Add panic_context module for better panic messages r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
2 parents e315fd9 + d3a2b21 commit 4ecab09

File tree

3 files changed

+55
-2
lines changed

3 files changed

+55
-2
lines changed

crates/rust-analyzer/src/dispatch.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! A visitor for downcasting arbitrary request (JSON) into a specific type.
2-
use std::panic;
2+
use std::{fmt, panic};
33

44
use serde::{de::DeserializeOwned, Serialize};
55

@@ -49,7 +49,7 @@ impl<'a> RequestDispatcher<'a> {
4949
) -> Result<&mut Self>
5050
where
5151
R: lsp_types::request::Request + 'static,
52-
R::Params: DeserializeOwned + Send + 'static,
52+
R::Params: DeserializeOwned + Send + fmt::Debug + 'static,
5353
R::Result: Serialize + 'static,
5454
{
5555
let (id, params) = match self.parse::<R>() {
@@ -61,7 +61,10 @@ impl<'a> RequestDispatcher<'a> {
6161

6262
self.global_state.task_pool.handle.spawn({
6363
let world = self.global_state.snapshot();
64+
6465
move || {
66+
let _ctx =
67+
stdx::panic_context::enter(format!("request: {} {:#?}", R::METHOD, params));
6568
let result = f(world, params);
6669
Task::Response(result_to_response::<R>(id, result))
6770
}

crates/stdx/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::{
55
};
66

77
mod macros;
8+
pub mod panic_context;
89

910
#[inline(always)]
1011
pub fn is_ci() -> bool {

crates/stdx/src/panic_context.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//! A micro-crate to enhance panic messages with context info.
2+
//!
3+
//! FIXME: upstream to https://github.com/kriomant/panic-context ?
4+
5+
use std::{cell::RefCell, panic, sync::Once};
6+
7+
pub fn enter(context: String) -> impl Drop {
8+
static ONCE: Once = Once::new();
9+
ONCE.call_once(PanicContext::init);
10+
11+
with_ctx(|ctx| ctx.push(context));
12+
PanicContext { _priv: () }
13+
}
14+
15+
#[must_use]
16+
struct PanicContext {
17+
_priv: (),
18+
}
19+
20+
impl PanicContext {
21+
fn init() {
22+
let default_hook = panic::take_hook();
23+
let hook = move |panic_info: &panic::PanicInfo<'_>| {
24+
with_ctx(|ctx| {
25+
if !ctx.is_empty() {
26+
eprintln!("Panic context:");
27+
for frame in ctx.iter() {
28+
eprintln!("> {}\n", frame)
29+
}
30+
}
31+
default_hook(panic_info)
32+
})
33+
};
34+
panic::set_hook(Box::new(hook))
35+
}
36+
}
37+
38+
impl Drop for PanicContext {
39+
fn drop(&mut self) {
40+
with_ctx(|ctx| assert!(ctx.pop().is_some()))
41+
}
42+
}
43+
44+
fn with_ctx(f: impl FnOnce(&mut Vec<String>)) {
45+
thread_local! {
46+
static CTX: RefCell<Vec<String>> = RefCell::new(Vec::new());
47+
}
48+
CTX.with(|ctx| f(&mut *ctx.borrow_mut()))
49+
}

0 commit comments

Comments
 (0)