Add -Z proc-macro-backtrace
to allow showing proc-macro panics
Fixes #75050 Previously, we would unconditionally suppress the panic hook during proc-macro execution. This commit adds a new flag -Z proc-macro-backtrace, which allows running the panic hook for easier debugging.
This commit is contained in:
parent
36b0d7e257
commit
d9208665b5
10 changed files with 99 additions and 27 deletions
|
@ -1788,6 +1788,7 @@ pub struct ExpansionConfig<'feat> {
|
|||
pub should_test: bool, // If false, strip `#[test]` nodes
|
||||
pub keep_macs: bool,
|
||||
pub span_debug: bool, // If true, use verbose debugging for `proc_macro::Span`
|
||||
pub proc_macro_backtrace: bool, // If true, show backtraces for proc-macro panics
|
||||
}
|
||||
|
||||
impl<'feat> ExpansionConfig<'feat> {
|
||||
|
@ -1800,6 +1801,7 @@ impl<'feat> ExpansionConfig<'feat> {
|
|||
should_test: false,
|
||||
keep_macs: false,
|
||||
span_debug: false,
|
||||
proc_macro_backtrace: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ impl base::ProcMacro for BangProcMacro {
|
|||
input: TokenStream,
|
||||
) -> Result<TokenStream, ErrorReported> {
|
||||
let server = proc_macro_server::Rustc::new(ecx);
|
||||
self.client.run(&EXEC_STRATEGY, server, input).map_err(|e| {
|
||||
self.client.run(&EXEC_STRATEGY, server, input, ecx.ecfg.proc_macro_backtrace).map_err(|e| {
|
||||
let mut err = ecx.struct_span_err(span, "proc macro panicked");
|
||||
if let Some(s) = e.as_str() {
|
||||
err.help(&format!("message: {}", s));
|
||||
|
@ -48,7 +48,9 @@ impl base::AttrProcMacro for AttrProcMacro {
|
|||
annotated: TokenStream,
|
||||
) -> Result<TokenStream, ErrorReported> {
|
||||
let server = proc_macro_server::Rustc::new(ecx);
|
||||
self.client.run(&EXEC_STRATEGY, server, annotation, annotated).map_err(|e| {
|
||||
self.client
|
||||
.run(&EXEC_STRATEGY, server, annotation, annotated, ecx.ecfg.proc_macro_backtrace)
|
||||
.map_err(|e| {
|
||||
let mut err = ecx.struct_span_err(span, "custom attribute panicked");
|
||||
if let Some(s) = e.as_str() {
|
||||
err.help(&format!("message: {}", s));
|
||||
|
@ -111,7 +113,8 @@ impl MultiItemModifier for ProcMacroDerive {
|
|||
};
|
||||
|
||||
let server = proc_macro_server::Rustc::new(ecx);
|
||||
let stream = match self.client.run(&EXEC_STRATEGY, server, input) {
|
||||
let stream =
|
||||
match self.client.run(&EXEC_STRATEGY, server, input, ecx.ecfg.proc_macro_backtrace) {
|
||||
Ok(stream) => stream,
|
||||
Err(e) => {
|
||||
let mut err = ecx.struct_span_err(span, "proc-macro derive panicked");
|
||||
|
|
|
@ -291,6 +291,7 @@ fn configure_and_expand_inner<'a>(
|
|||
trace_mac: sess.opts.debugging_opts.trace_macros,
|
||||
should_test: sess.opts.test,
|
||||
span_debug: sess.opts.debugging_opts.span_debug,
|
||||
proc_macro_backtrace: sess.opts.debugging_opts.proc_macro_backtrace,
|
||||
..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string())
|
||||
};
|
||||
|
||||
|
|
|
@ -502,6 +502,7 @@ fn test_debugging_options_tracking_hash() {
|
|||
untracked!(print_llvm_passes, true);
|
||||
untracked!(print_mono_items, Some(String::from("abc")));
|
||||
untracked!(print_type_sizes, true);
|
||||
untracked!(proc_macro_backtrace, true);
|
||||
untracked!(query_dep_graph, true);
|
||||
untracked!(query_stats, true);
|
||||
untracked!(save_analysis, true);
|
||||
|
|
|
@ -967,6 +967,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
"print the result of the monomorphization collection pass"),
|
||||
print_type_sizes: bool = (false, parse_bool, [UNTRACKED],
|
||||
"print layout information for each type encountered (default: no)"),
|
||||
proc_macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
|
||||
"show backtraces for panics during proc-macro execution (default: no)"),
|
||||
profile: bool = (false, parse_bool, [TRACKED],
|
||||
"insert profiling code (default: no)"),
|
||||
profile_emit: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
|
||||
|
|
|
@ -311,11 +311,13 @@ impl Bridge<'_> {
|
|||
HIDE_PANICS_DURING_EXPANSION.call_once(|| {
|
||||
let prev = panic::take_hook();
|
||||
panic::set_hook(Box::new(move |info| {
|
||||
let hide = BridgeState::with(|state| match state {
|
||||
BridgeState::NotConnected => false,
|
||||
BridgeState::Connected(_) | BridgeState::InUse => true,
|
||||
let show = BridgeState::with(|state| match state {
|
||||
BridgeState::NotConnected => true,
|
||||
// Something weird is going on, so don't suppress any backtraces
|
||||
BridgeState::InUse => true,
|
||||
BridgeState::Connected(bridge) => bridge.force_show_panics,
|
||||
});
|
||||
if !hide {
|
||||
if show {
|
||||
prev(info)
|
||||
}
|
||||
}));
|
||||
|
|
|
@ -220,6 +220,9 @@ pub struct Bridge<'a> {
|
|||
|
||||
/// Server-side function that the client uses to make requests.
|
||||
dispatch: closure::Closure<'a, Buffer<u8>, Buffer<u8>>,
|
||||
|
||||
/// If 'true', always invoke the default panic hook
|
||||
force_show_panics: bool,
|
||||
}
|
||||
|
||||
impl<'a> !Sync for Bridge<'a> {}
|
||||
|
|
|
@ -135,6 +135,7 @@ pub trait ExecutionStrategy {
|
|||
input: Buffer<u8>,
|
||||
run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
|
||||
client_data: D,
|
||||
force_show_panics: bool,
|
||||
) -> Buffer<u8>;
|
||||
}
|
||||
|
||||
|
@ -147,10 +148,14 @@ impl ExecutionStrategy for SameThread {
|
|||
input: Buffer<u8>,
|
||||
run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
|
||||
client_data: D,
|
||||
force_show_panics: bool,
|
||||
) -> Buffer<u8> {
|
||||
let mut dispatch = |b| dispatcher.dispatch(b);
|
||||
|
||||
run_client(Bridge { cached_buffer: input, dispatch: (&mut dispatch).into() }, client_data)
|
||||
run_client(
|
||||
Bridge { cached_buffer: input, dispatch: (&mut dispatch).into(), force_show_panics },
|
||||
client_data,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,6 +171,7 @@ impl ExecutionStrategy for CrossThread1 {
|
|||
input: Buffer<u8>,
|
||||
run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
|
||||
client_data: D,
|
||||
force_show_panics: bool,
|
||||
) -> Buffer<u8> {
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
|
@ -179,7 +185,11 @@ impl ExecutionStrategy for CrossThread1 {
|
|||
};
|
||||
|
||||
run_client(
|
||||
Bridge { cached_buffer: input, dispatch: (&mut dispatch).into() },
|
||||
Bridge {
|
||||
cached_buffer: input,
|
||||
dispatch: (&mut dispatch).into(),
|
||||
force_show_panics,
|
||||
},
|
||||
client_data,
|
||||
)
|
||||
});
|
||||
|
@ -201,6 +211,7 @@ impl ExecutionStrategy for CrossThread2 {
|
|||
input: Buffer<u8>,
|
||||
run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
|
||||
client_data: D,
|
||||
force_show_panics: bool,
|
||||
) -> Buffer<u8> {
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
|
@ -226,7 +237,11 @@ impl ExecutionStrategy for CrossThread2 {
|
|||
};
|
||||
|
||||
let r = run_client(
|
||||
Bridge { cached_buffer: input, dispatch: (&mut dispatch).into() },
|
||||
Bridge {
|
||||
cached_buffer: input,
|
||||
dispatch: (&mut dispatch).into(),
|
||||
force_show_panics,
|
||||
},
|
||||
client_data,
|
||||
);
|
||||
|
||||
|
@ -265,6 +280,7 @@ fn run_server<
|
|||
input: I,
|
||||
run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
|
||||
client_data: D,
|
||||
force_show_panics: bool,
|
||||
) -> Result<O, PanicMessage> {
|
||||
let mut dispatcher =
|
||||
Dispatcher { handle_store: HandleStore::new(handle_counters), server: MarkedTypes(server) };
|
||||
|
@ -272,7 +288,13 @@ fn run_server<
|
|||
let mut b = Buffer::new();
|
||||
input.encode(&mut b, &mut dispatcher.handle_store);
|
||||
|
||||
b = strategy.run_bridge_and_client(&mut dispatcher, b, run_client, client_data);
|
||||
b = strategy.run_bridge_and_client(
|
||||
&mut dispatcher,
|
||||
b,
|
||||
run_client,
|
||||
client_data,
|
||||
force_show_panics,
|
||||
);
|
||||
|
||||
Result::decode(&mut &b[..], &mut dispatcher.handle_store)
|
||||
}
|
||||
|
@ -283,6 +305,7 @@ impl client::Client<fn(crate::TokenStream) -> crate::TokenStream> {
|
|||
strategy: &impl ExecutionStrategy,
|
||||
server: S,
|
||||
input: S::TokenStream,
|
||||
force_show_panics: bool,
|
||||
) -> Result<S::TokenStream, PanicMessage> {
|
||||
let client::Client { get_handle_counters, run, f } = *self;
|
||||
run_server(
|
||||
|
@ -292,6 +315,7 @@ impl client::Client<fn(crate::TokenStream) -> crate::TokenStream> {
|
|||
<MarkedTypes<S> as Types>::TokenStream::mark(input),
|
||||
run,
|
||||
f,
|
||||
force_show_panics,
|
||||
)
|
||||
.map(<MarkedTypes<S> as Types>::TokenStream::unmark)
|
||||
}
|
||||
|
@ -304,6 +328,7 @@ impl client::Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenSt
|
|||
server: S,
|
||||
input: S::TokenStream,
|
||||
input2: S::TokenStream,
|
||||
force_show_panics: bool,
|
||||
) -> Result<S::TokenStream, PanicMessage> {
|
||||
let client::Client { get_handle_counters, run, f } = *self;
|
||||
run_server(
|
||||
|
@ -316,6 +341,7 @@ impl client::Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenSt
|
|||
),
|
||||
run,
|
||||
f,
|
||||
force_show_panics,
|
||||
)
|
||||
.map(<MarkedTypes<S> as Types>::TokenStream::unmark)
|
||||
}
|
||||
|
|
21
src/test/ui/proc-macro/load-panic-backtrace.rs
Normal file
21
src/test/ui/proc-macro/load-panic-backtrace.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
// aux-build:test-macros.rs
|
||||
// compile-flags: -Z proc-macro-backtrace
|
||||
// rustc-env:RUST_BACKTRACE=0
|
||||
|
||||
// FIXME https://github.com/rust-lang/rust/issues/59998
|
||||
// normalize-stderr-test "thread '.*' panicked " -> ""
|
||||
// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
|
||||
// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> ""
|
||||
// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> ""
|
||||
// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
|
||||
// normalize-stderr-test "note: compiler flags.*\n\n" -> ""
|
||||
// normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
|
||||
|
||||
#[macro_use]
|
||||
extern crate test_macros;
|
||||
|
||||
#[derive(Panic)]
|
||||
//~^ ERROR: proc-macro derive panicked
|
||||
struct Foo;
|
||||
|
||||
fn main() {}
|
11
src/test/ui/proc-macro/load-panic-backtrace.stderr
Normal file
11
src/test/ui/proc-macro/load-panic-backtrace.stderr
Normal file
|
@ -0,0 +1,11 @@
|
|||
at 'panic-derive', $DIR/auxiliary/test-macros.rs:43:5
|
||||
error: proc-macro derive panicked
|
||||
--> $DIR/load-panic-backtrace.rs:17:10
|
||||
|
|
||||
LL | #[derive(Panic)]
|
||||
| ^^^^^
|
||||
|
|
||||
= help: message: panic-derive
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Add table
Reference in a new issue