Fix #107910, Shorten backtraces in ICEs
This commit is contained in:
parent
c2ccc855e7
commit
c3394b3eaa
@ -488,6 +488,18 @@ macro_rules! expand_if_cached {
|
||||
};
|
||||
}
|
||||
|
||||
/// Don't show the backtrace for query system by default
|
||||
/// use `RUST_BACKTRACE=full` to show all the backtraces
|
||||
#[inline(never)]
|
||||
pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
let result = f();
|
||||
std::hint::black_box(());
|
||||
result
|
||||
}
|
||||
|
||||
// NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
|
||||
// invoked by `rustc_query_append`.
|
||||
macro_rules! define_queries {
|
||||
@ -498,9 +510,12 @@ mod get_query_incr {
|
||||
use super::*;
|
||||
|
||||
$(
|
||||
#[inline(always)]
|
||||
#[tracing::instrument(level = "trace", skip(tcx))]
|
||||
pub(super) fn $name<'tcx>(
|
||||
// Adding `__rust_end_short_backtrace` marker to backtraces so that we emit the frames
|
||||
// when `RUST_BACKTRACE=1`, add a new mod with `$name` here is to allow duplicate naming
|
||||
pub mod $name {
|
||||
use super::*;
|
||||
#[inline(never)]
|
||||
pub fn __rust_end_short_backtrace<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
span: Span,
|
||||
key: query_keys::$name<'tcx>,
|
||||
@ -514,6 +529,7 @@ pub(super) fn $name<'tcx>(
|
||||
mode
|
||||
)
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
@ -521,9 +537,10 @@ mod get_query_non_incr {
|
||||
use super::*;
|
||||
|
||||
$(
|
||||
#[inline(always)]
|
||||
#[tracing::instrument(level = "trace", skip(tcx))]
|
||||
pub(super) fn $name<'tcx>(
|
||||
pub mod $name {
|
||||
use super::*;
|
||||
#[inline(never)]
|
||||
pub fn __rust_end_short_backtrace<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
span: Span,
|
||||
key: query_keys::$name<'tcx>,
|
||||
@ -536,17 +553,18 @@ pub(super) fn $name<'tcx>(
|
||||
key,
|
||||
))
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
pub(crate) fn engine(incremental: bool) -> QueryEngine {
|
||||
if incremental {
|
||||
QueryEngine {
|
||||
$($name: get_query_incr::$name,)*
|
||||
$($name: get_query_incr::$name::__rust_end_short_backtrace,)*
|
||||
}
|
||||
} else {
|
||||
QueryEngine {
|
||||
$($name: get_query_non_incr::$name,)*
|
||||
$($name: get_query_non_incr::$name::__rust_end_short_backtrace,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -578,10 +596,15 @@ pub(super) fn $name<'tcx>() -> DynamicQuery<'tcx, query_storage::$name<'tcx>> {
|
||||
query_cache: offset_of!(QueryCaches<'tcx> => $name),
|
||||
cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key),
|
||||
execute_query: |tcx, key| erase(tcx.$name(key)),
|
||||
compute: |tcx, key| query_provided_to_value::$name(
|
||||
compute: |tcx, key| {
|
||||
use crate::plumbing::__rust_begin_short_backtrace;
|
||||
__rust_begin_short_backtrace(||
|
||||
query_provided_to_value::$name(
|
||||
tcx,
|
||||
call_provider!([$($modifiers)*][tcx, $name, key])
|
||||
),
|
||||
)
|
||||
)
|
||||
},
|
||||
can_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] true false),
|
||||
try_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] {
|
||||
|tcx, key, prev_index, index| {
|
||||
|
@ -68,13 +68,17 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
|
||||
}
|
||||
|
||||
let mut hit = false;
|
||||
let mut stop = false;
|
||||
backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
|
||||
hit = true;
|
||||
|
||||
// Any frames between `__rust_begin_short_backtrace` and `__rust_end_short_backtrace`
|
||||
// are omitted from the backtrace in short mode, `__rust_end_short_backtrace` will be
|
||||
// called before the panic hook, so we won't ignore any frames if there is no
|
||||
// invoke of `__rust_begin_short_backtrace`.
|
||||
if print_fmt == PrintFmt::Short {
|
||||
if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
|
||||
if start && sym.contains("__rust_begin_short_backtrace") {
|
||||
stop = true;
|
||||
start = false;
|
||||
return;
|
||||
}
|
||||
if sym.contains("__rust_end_short_backtrace") {
|
||||
@ -88,9 +92,6 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
|
||||
res = bt_fmt.frame().symbol(frame, symbol);
|
||||
}
|
||||
});
|
||||
if stop {
|
||||
return false;
|
||||
}
|
||||
#[cfg(target_os = "nto")]
|
||||
if libc::__my_thread_exit as *mut libc::c_void == frame.ip() {
|
||||
if !hit && start {
|
||||
|
9
tests/run-make/short-ice/Makefile
Normal file
9
tests/run-make/short-ice/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
include ../tools.mk
|
||||
|
||||
# ignore-windows
|
||||
|
||||
export RUSTC := $(RUSTC_ORIGINAL)
|
||||
export TMPDIR := $(TMPDIR)
|
||||
|
||||
all:
|
||||
bash check.sh
|
36
tests/run-make/short-ice/check.sh
Normal file
36
tests/run-make/short-ice/check.sh
Normal file
@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
|
||||
RUST_BACKTRACE=1 $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-1.log 2>&1
|
||||
RUST_BACKTRACE=full $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-2.log 2>&1
|
||||
|
||||
short=$(cat $TMPDIR/rust-test-1.log | wc -l)
|
||||
full=$(cat $TMPDIR/rust-test-2.log | wc -l)
|
||||
rustc_query_count=$(cat $TMPDIR/rust-test-1.log | grep rustc_query_ | wc -l)
|
||||
rustc_query_count_full=$(cat $TMPDIR/rust-test-2.log | grep rustc_query_ | wc -l)
|
||||
|
||||
begin_count=$(cat $TMPDIR/rust-test-2.log | grep __rust_begin_short_backtrace | wc -l)
|
||||
end_count=$(cat $TMPDIR/rust-test-2.log | grep __rust_end_short_backtrace | wc -l)
|
||||
|
||||
cat $TMPDIR/rust-test-1.log
|
||||
echo "====================="
|
||||
cat $TMPDIR/rust-test-2.log
|
||||
echo "====================="
|
||||
|
||||
echo "short backtrace: $short"
|
||||
echo "full backtrace: $full"
|
||||
echo "begin_count: $begin_count"
|
||||
echo "end_count : $end_count"
|
||||
echo "rustc_query_count: $rustc_query_count"
|
||||
echo "rustc_query_count_full: $rustc_query_count_full"
|
||||
|
||||
## backtraces to vary a bit depending on platform and configuration options,
|
||||
## here we make sure that the short backtrace of rustc_query is shorter than the full,
|
||||
## and marks are in pairs.
|
||||
if [ $short -lt $full ] &&
|
||||
[ $begin_count -eq $end_count ] &&
|
||||
[ $(($rustc_query_count + 10)) -lt $rustc_query_count_full ] &&
|
||||
[ $rustc_query_count_full -gt 10 ]; then
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
7
tests/run-make/short-ice/src/lib.rs
Normal file
7
tests/run-make/short-ice/src/lib.rs
Normal file
@ -0,0 +1,7 @@
|
||||
fn func(s: &str) {
|
||||
println!("{}", s);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
func(1);
|
||||
}
|
@ -8,6 +8,8 @@ LL | fn main() { missing_ident; }
|
||||
stack backtrace:
|
||||
(end_short_backtrace)
|
||||
(begin_short_backtrace)
|
||||
(end_short_backtrace)
|
||||
(begin_short_backtrace)
|
||||
|
||||
error: the compiler unexpectedly panicked. this is a bug.
|
||||
|
||||
|
61
tests/ui/panics/short-ice-remove-middle-frames-2.rs
Normal file
61
tests/ui/panics/short-ice-remove-middle-frames-2.rs
Normal file
@ -0,0 +1,61 @@
|
||||
// compile-flags:-Cstrip=none
|
||||
// run-fail
|
||||
// check-run-results
|
||||
// exec-env:RUST_BACKTRACE=1
|
||||
// ignore-android FIXME #17520
|
||||
// ignore-wasm no panic support
|
||||
// ignore-openbsd no support for libbacktrace without filename
|
||||
// ignore-emscripten no panic
|
||||
// ignore-sgx Backtraces not symbolized
|
||||
// ignore-fuchsia Backtraces not symbolized
|
||||
// ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable.
|
||||
|
||||
/// This test case make sure that we can have multiple pairs of `__rust_{begin,end}_short_backtrace`
|
||||
|
||||
#[inline(never)]
|
||||
fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
|
||||
let result = f();
|
||||
std::hint::black_box(result)
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn __rust_end_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
|
||||
let result = f();
|
||||
std::hint::black_box(result)
|
||||
}
|
||||
|
||||
fn first() {
|
||||
__rust_end_short_backtrace(|| second());
|
||||
}
|
||||
|
||||
fn second() {
|
||||
third(); // won't show up
|
||||
}
|
||||
|
||||
fn third() {
|
||||
fourth(); // won't show up
|
||||
}
|
||||
|
||||
fn fourth() {
|
||||
__rust_begin_short_backtrace(|| fifth());
|
||||
}
|
||||
|
||||
fn fifth() {
|
||||
__rust_end_short_backtrace(|| sixth());
|
||||
}
|
||||
|
||||
fn sixth() {
|
||||
seven(); // won't show up
|
||||
}
|
||||
|
||||
fn seven() {
|
||||
__rust_begin_short_backtrace(|| eight());
|
||||
}
|
||||
|
||||
fn eight() {
|
||||
panic!("debug!!!");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
first();
|
||||
}
|
11
tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr
Normal file
11
tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
thread 'main' panicked at 'debug!!!', $DIR/short-ice-remove-middle-frames-2.rs:56:5
|
||||
stack backtrace:
|
||||
0: std::panicking::begin_panic
|
||||
1: short_ice_remove_middle_frames_2::eight
|
||||
2: short_ice_remove_middle_frames_2::seven::{{closure}}
|
||||
3: short_ice_remove_middle_frames_2::fifth
|
||||
4: short_ice_remove_middle_frames_2::fourth::{{closure}}
|
||||
5: short_ice_remove_middle_frames_2::first
|
||||
6: short_ice_remove_middle_frames_2::main
|
||||
7: core::ops::function::FnOnce::call_once
|
||||
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
|
57
tests/ui/panics/short-ice-remove-middle-frames.rs
Normal file
57
tests/ui/panics/short-ice-remove-middle-frames.rs
Normal file
@ -0,0 +1,57 @@
|
||||
// compile-flags:-Cstrip=none
|
||||
// run-fail
|
||||
// check-run-results
|
||||
// exec-env:RUST_BACKTRACE=1
|
||||
// ignore-android FIXME #17520
|
||||
// ignore-wasm no panic support
|
||||
// ignore-openbsd no support for libbacktrace without filename
|
||||
// ignore-emscripten no panic
|
||||
// ignore-sgx Backtraces not symbolized
|
||||
// ignore-fuchsia Backtraces not symbolized
|
||||
// ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable.
|
||||
|
||||
|
||||
#[inline(never)]
|
||||
fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
|
||||
let result = f();
|
||||
std::hint::black_box(result)
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn __rust_end_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
|
||||
let result = f();
|
||||
std::hint::black_box(result)
|
||||
}
|
||||
|
||||
fn first() {
|
||||
__rust_end_short_backtrace(|| second());
|
||||
// do not take effect since we already has a inner call of __rust_end_short_backtrace
|
||||
}
|
||||
|
||||
fn second() {
|
||||
__rust_end_short_backtrace(|| third());
|
||||
}
|
||||
|
||||
fn third() {
|
||||
fourth(); // won't show up in backtrace
|
||||
}
|
||||
|
||||
fn fourth() {
|
||||
fifth(); // won't show up in backtrace
|
||||
}
|
||||
|
||||
fn fifth() {
|
||||
__rust_begin_short_backtrace(|| sixth());
|
||||
}
|
||||
|
||||
fn sixth() {
|
||||
seven();
|
||||
}
|
||||
|
||||
fn seven() {
|
||||
panic!("debug!!!");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
first();
|
||||
}
|
12
tests/ui/panics/short-ice-remove-middle-frames.run.stderr
Normal file
12
tests/ui/panics/short-ice-remove-middle-frames.run.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
thread 'main' panicked at 'debug!!!', $DIR/short-ice-remove-middle-frames.rs:52:5
|
||||
stack backtrace:
|
||||
0: std::panicking::begin_panic
|
||||
1: short_ice_remove_middle_frames::seven
|
||||
2: short_ice_remove_middle_frames::sixth
|
||||
3: short_ice_remove_middle_frames::fifth::{{closure}}
|
||||
4: short_ice_remove_middle_frames::second
|
||||
5: short_ice_remove_middle_frames::first::{{closure}}
|
||||
6: short_ice_remove_middle_frames::first
|
||||
7: short_ice_remove_middle_frames::main
|
||||
8: core::ops::function::FnOnce::call_once
|
||||
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
|
Loading…
Reference in New Issue
Block a user