Skip to content

Commit 5c41569

Browse files
committed
Fix #107910, Shorten backtraces in ICEs
1 parent 18bfe5d commit 5c41569

File tree

7 files changed

+154
-25
lines changed

7 files changed

+154
-25
lines changed

compiler/rustc_query_impl/src/plumbing.rs

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,18 @@ macro_rules! expand_if_cached {
488488
};
489489
}
490490

491+
/// Don't show the backtrace for query system by default
492+
/// use `RUST_BACKTRACE=full` to show all the backtraces
493+
#[inline(never)]
494+
pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
495+
where
496+
F: FnOnce() -> T,
497+
{
498+
let result = f();
499+
std::hint::black_box(());
500+
result
501+
}
502+
491503
// NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
492504
// invoked by `rustc_query_append`.
493505
macro_rules! define_queries {
@@ -498,28 +510,32 @@ macro_rules! define_queries {
498510
use super::*;
499511

500512
$(
501-
#[inline(always)]
502-
#[tracing::instrument(level = "trace", skip(tcx))]
503-
pub(super) fn $name<'tcx>(
504-
tcx: TyCtxt<'tcx>,
505-
span: Span,
506-
key: query_keys::$name<'tcx>,
507-
mode: QueryMode,
508-
) -> Option<Erase<query_values::$name<'tcx>>> {
509-
get_query(
510-
queries::$name::config(tcx),
511-
QueryCtxt::new(tcx),
512-
span,
513-
key,
514-
mode
515-
)
513+
// Adding `__rust_end_short_backtrace` marker to backtraces so that we emit the frames
514+
// when `RUST_BACKTRACE=1`, add a new mod with `$name` here is to allow duplicate naming
515+
pub mod $name {
516+
use super::*;
517+
#[inline(never)]
518+
pub fn __rust_end_short_backtrace<'tcx>(
519+
tcx: TyCtxt<'tcx>,
520+
span: Span,
521+
key: query_keys::$name<'tcx>,
522+
mode: QueryMode,
523+
) -> Option<Erase<query_values::$name<'tcx>>> {
524+
get_query(
525+
queries::$name::config(tcx),
526+
QueryCtxt::new(tcx),
527+
span,
528+
key,
529+
mode
530+
)
531+
}
516532
}
517533
)*
518534
}
519535

520536
pub(crate) fn engine() -> QueryEngine {
521537
QueryEngine {
522-
$($name: get_query::$name,)*
538+
$($name: get_query::$name::__rust_end_short_backtrace,)*
523539
}
524540
}
525541

@@ -550,10 +566,15 @@ macro_rules! define_queries {
550566
query_cache: offset_of!(QueryCaches<'tcx> => $name),
551567
cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key),
552568
execute_query: |tcx, key| erase(tcx.$name(key)),
553-
compute: |tcx, key| query_provided_to_value::$name(
554-
tcx,
555-
call_provider!([$($modifiers)*][tcx, $name, key])
556-
),
569+
compute: |tcx, key| {
570+
use crate::plumbing::__rust_begin_short_backtrace;
571+
__rust_begin_short_backtrace(||
572+
query_provided_to_value::$name(
573+
tcx,
574+
call_provider!([$($modifiers)*][tcx, $name, key])
575+
)
576+
)
577+
},
557578
can_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] true false),
558579
try_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] {
559580
|tcx, key, prev_index, index| {

library/std/src/sys_common/backtrace.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,17 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
6868
}
6969

7070
let mut hit = false;
71-
let mut stop = false;
7271
backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
7372
hit = true;
73+
74+
// Any frames between `__rust_begin_short_backtrace` and `__rust_end_short_backtrace`
75+
// are omitted from the backtrace in short mode, `__rust_end_short_backtrace` will be
76+
// called before the panic hook, so we won't ignore any frames if there is no
77+
// invoke of `__rust_begin_short_backtrace`.
7478
if print_fmt == PrintFmt::Short {
7579
if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
7680
if start && sym.contains("__rust_begin_short_backtrace") {
77-
stop = true;
81+
start = false;
7882
return;
7983
}
8084
if sym.contains("__rust_end_short_backtrace") {
@@ -88,9 +92,6 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
8892
res = bt_fmt.frame().symbol(frame, symbol);
8993
}
9094
});
91-
if stop {
92-
return false;
93-
}
9495
#[cfg(target_os = "nto")]
9596
if libc::__my_thread_exit as *mut libc::c_void == frame.ip() {
9697
if !hit && start {

tests/run-make/short-ice/Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
include ../tools.mk
2+
3+
# ignore-windows
4+
5+
export RUSTC := $(RUSTC_ORIGINAL)
6+
export TMPDIR := $(TMPDIR)
7+
8+
all:
9+
bash check.sh

tests/run-make/short-ice/check.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/bin/sh
2+
3+
RUST_BACKTRACE=1 $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-1.log 2>&1
4+
RUST_BACKTRACE=full $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-2.log 2>&1
5+
6+
short=$(cat $TMPDIR/rust-test-1.log | wc -l)
7+
full=$(cat $TMPDIR/rust-test-2.log | wc -l)
8+
rustc_query_count=$(cat $TMPDIR/rust-test-1.log | grep rustc_query_ | wc -l)
9+
rustc_query_count_full=$(cat $TMPDIR/rust-test-2.log | grep rustc_query_ | wc -l)
10+
11+
cat $TMPDIR/rust-test-1.log
12+
echo "====================="
13+
cat $TMPDIR/rust-test-2.log
14+
15+
echo "short backtrace: $short"
16+
echo "full backtrace: $full"
17+
echo "rustc_query_count: $rustc_query_count"
18+
echo "rustc_query_count_full: $rustc_query_count_full"
19+
20+
## check `rustc_query_count` to avoid to missing `__rust_end_short_backtrace`
21+
## 1 <= $rustc_query_count < $rustc_query_count_full
22+
## $rustc_query_count_full > 10
23+
if [ $full -gt $short ] &&
24+
[ $rustc_query_count -gt 1 ] &&
25+
[ $rustc_query_count -lt $rustc_query_count_full ] &&
26+
[ $rustc_query_count_full -gt 10 ]; then
27+
exit 0
28+
else
29+
exit 1
30+
fi

tests/run-make/short-ice/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn func(s: &str) {
2+
println!("{}", s);
3+
}
4+
5+
fn main() {
6+
func(1);
7+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// compile-flags:-Cstrip=none
2+
// run-fail
3+
// check-run-results
4+
// exec-env:RUST_BACKTRACE=1
5+
6+
#[inline(never)]
7+
fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
8+
let result = f();
9+
std::hint::black_box(result)
10+
}
11+
12+
#[inline(never)]
13+
fn __rust_end_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
14+
let result = f();
15+
std::hint::black_box(result)
16+
}
17+
18+
fn first() {
19+
__rust_end_short_backtrace(|| second());
20+
// do not take effect since we already has a inner call of __rust_end_short_backtrace
21+
}
22+
23+
fn second() {
24+
__rust_end_short_backtrace(|| third());
25+
}
26+
27+
fn third() {
28+
fourth(); // won't show up in backtrace
29+
}
30+
31+
fn fourth() {
32+
fifth(); // won't show up in backtrace
33+
}
34+
35+
fn fifth() {
36+
__rust_begin_short_backtrace(|| sixth());
37+
}
38+
39+
fn sixth() {
40+
seven();
41+
}
42+
43+
fn seven() {
44+
panic!("debug!!!");
45+
}
46+
47+
fn main() {
48+
first();
49+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
thread 'main' panicked at 'debug!!!', $DIR/short-ice-remove-middle-frames.rs:44:5
2+
stack backtrace:
3+
0: std::panicking::begin_panic
4+
1: short_ice_remove_middle_frames::seven
5+
2: short_ice_remove_middle_frames::sixth
6+
3: short_ice_remove_middle_frames::fifth::{{closure}}
7+
4: short_ice_remove_middle_frames::second
8+
5: short_ice_remove_middle_frames::first::{{closure}}
9+
6: short_ice_remove_middle_frames::first
10+
7: short_ice_remove_middle_frames::main
11+
8: core::ops::function::FnOnce::call_once
12+
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

0 commit comments

Comments
 (0)