Skip to content

Commit 77c836e

Browse files
committed
Auto merge of #108938 - chenyukang:yukang/fix-107910-shorten-ice, r=cjgillot
Shorten backtraces for queries in ICEs r? `@jyn514` Fixes #107910
2 parents 77fb0cd + c3394b3 commit 77c836e

10 files changed

+259
-40
lines changed

compiler/rustc_query_impl/src/plumbing.rs

+58-35
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,21 +510,25 @@ 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_incr(
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_incr(
525+
queries::$name::config(tcx),
526+
QueryCtxt::new(tcx),
527+
span,
528+
key,
529+
mode
530+
)
531+
}
516532
}
517533
)*
518534
}
@@ -521,32 +537,34 @@ macro_rules! define_queries {
521537
use super::*;
522538

523539
$(
524-
#[inline(always)]
525-
#[tracing::instrument(level = "trace", skip(tcx))]
526-
pub(super) fn $name<'tcx>(
527-
tcx: TyCtxt<'tcx>,
528-
span: Span,
529-
key: query_keys::$name<'tcx>,
530-
__mode: QueryMode,
531-
) -> Option<Erase<query_values::$name<'tcx>>> {
532-
Some(get_query_non_incr(
533-
queries::$name::config(tcx),
534-
QueryCtxt::new(tcx),
535-
span,
536-
key,
537-
))
540+
pub mod $name {
541+
use super::*;
542+
#[inline(never)]
543+
pub fn __rust_end_short_backtrace<'tcx>(
544+
tcx: TyCtxt<'tcx>,
545+
span: Span,
546+
key: query_keys::$name<'tcx>,
547+
__mode: QueryMode,
548+
) -> Option<Erase<query_values::$name<'tcx>>> {
549+
Some(get_query_non_incr(
550+
queries::$name::config(tcx),
551+
QueryCtxt::new(tcx),
552+
span,
553+
key,
554+
))
555+
}
538556
}
539557
)*
540558
}
541559

542560
pub(crate) fn engine(incremental: bool) -> QueryEngine {
543561
if incremental {
544562
QueryEngine {
545-
$($name: get_query_incr::$name,)*
563+
$($name: get_query_incr::$name::__rust_end_short_backtrace,)*
546564
}
547565
} else {
548566
QueryEngine {
549-
$($name: get_query_non_incr::$name,)*
567+
$($name: get_query_non_incr::$name::__rust_end_short_backtrace,)*
550568
}
551569
}
552570
}
@@ -578,10 +596,15 @@ macro_rules! define_queries {
578596
query_cache: offset_of!(QueryCaches<'tcx> => $name),
579597
cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key),
580598
execute_query: |tcx, key| erase(tcx.$name(key)),
581-
compute: |tcx, key| query_provided_to_value::$name(
582-
tcx,
583-
call_provider!([$($modifiers)*][tcx, $name, key])
584-
),
599+
compute: |tcx, key| {
600+
use crate::plumbing::__rust_begin_short_backtrace;
601+
__rust_begin_short_backtrace(||
602+
query_provided_to_value::$name(
603+
tcx,
604+
call_provider!([$($modifiers)*][tcx, $name, key])
605+
)
606+
)
607+
},
585608
can_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] true false),
586609
try_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] {
587610
|tcx, key, prev_index, index| {

library/std/src/sys_common/backtrace.rs

+6-5
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

+9
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

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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+
begin_count=$(cat $TMPDIR/rust-test-2.log | grep __rust_begin_short_backtrace | wc -l)
12+
end_count=$(cat $TMPDIR/rust-test-2.log | grep __rust_end_short_backtrace | wc -l)
13+
14+
cat $TMPDIR/rust-test-1.log
15+
echo "====================="
16+
cat $TMPDIR/rust-test-2.log
17+
echo "====================="
18+
19+
echo "short backtrace: $short"
20+
echo "full backtrace: $full"
21+
echo "begin_count: $begin_count"
22+
echo "end_count : $end_count"
23+
echo "rustc_query_count: $rustc_query_count"
24+
echo "rustc_query_count_full: $rustc_query_count_full"
25+
26+
## backtraces to vary a bit depending on platform and configuration options,
27+
## here we make sure that the short backtrace of rustc_query is shorter than the full,
28+
## and marks are in pairs.
29+
if [ $short -lt $full ] &&
30+
[ $begin_count -eq $end_count ] &&
31+
[ $(($rustc_query_count + 10)) -lt $rustc_query_count_full ] &&
32+
[ $rustc_query_count_full -gt 10 ]; then
33+
exit 0
34+
else
35+
exit 1
36+
fi

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

+7
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+
}

tests/ui/panics/default-backtrace-ice.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ LL | fn main() { missing_ident; }
88
stack backtrace:
99
(end_short_backtrace)
1010
(begin_short_backtrace)
11+
(end_short_backtrace)
12+
(begin_short_backtrace)
1113

1214
error: the compiler unexpectedly panicked. this is a bug.
1315

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// compile-flags:-Cstrip=none
2+
// run-fail
3+
// check-run-results
4+
// exec-env:RUST_BACKTRACE=1
5+
// ignore-android FIXME #17520
6+
// ignore-wasm no panic support
7+
// ignore-openbsd no support for libbacktrace without filename
8+
// ignore-emscripten no panic
9+
// ignore-sgx Backtraces not symbolized
10+
// ignore-fuchsia Backtraces not symbolized
11+
// ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable.
12+
13+
/// This test case make sure that we can have multiple pairs of `__rust_{begin,end}_short_backtrace`
14+
15+
#[inline(never)]
16+
fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
17+
let result = f();
18+
std::hint::black_box(result)
19+
}
20+
21+
#[inline(never)]
22+
fn __rust_end_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
23+
let result = f();
24+
std::hint::black_box(result)
25+
}
26+
27+
fn first() {
28+
__rust_end_short_backtrace(|| second());
29+
}
30+
31+
fn second() {
32+
third(); // won't show up
33+
}
34+
35+
fn third() {
36+
fourth(); // won't show up
37+
}
38+
39+
fn fourth() {
40+
__rust_begin_short_backtrace(|| fifth());
41+
}
42+
43+
fn fifth() {
44+
__rust_end_short_backtrace(|| sixth());
45+
}
46+
47+
fn sixth() {
48+
seven(); // won't show up
49+
}
50+
51+
fn seven() {
52+
__rust_begin_short_backtrace(|| eight());
53+
}
54+
55+
fn eight() {
56+
panic!("debug!!!");
57+
}
58+
59+
fn main() {
60+
first();
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
thread 'main' panicked at 'debug!!!', $DIR/short-ice-remove-middle-frames-2.rs:56:5
2+
stack backtrace:
3+
0: std::panicking::begin_panic
4+
1: short_ice_remove_middle_frames_2::eight
5+
2: short_ice_remove_middle_frames_2::seven::{{closure}}
6+
3: short_ice_remove_middle_frames_2::fifth
7+
4: short_ice_remove_middle_frames_2::fourth::{{closure}}
8+
5: short_ice_remove_middle_frames_2::first
9+
6: short_ice_remove_middle_frames_2::main
10+
7: core::ops::function::FnOnce::call_once
11+
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// compile-flags:-Cstrip=none
2+
// run-fail
3+
// check-run-results
4+
// exec-env:RUST_BACKTRACE=1
5+
// ignore-android FIXME #17520
6+
// ignore-wasm no panic support
7+
// ignore-openbsd no support for libbacktrace without filename
8+
// ignore-emscripten no panic
9+
// ignore-sgx Backtraces not symbolized
10+
// ignore-fuchsia Backtraces not symbolized
11+
// ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable.
12+
13+
14+
#[inline(never)]
15+
fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
16+
let result = f();
17+
std::hint::black_box(result)
18+
}
19+
20+
#[inline(never)]
21+
fn __rust_end_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
22+
let result = f();
23+
std::hint::black_box(result)
24+
}
25+
26+
fn first() {
27+
__rust_end_short_backtrace(|| second());
28+
// do not take effect since we already has a inner call of __rust_end_short_backtrace
29+
}
30+
31+
fn second() {
32+
__rust_end_short_backtrace(|| third());
33+
}
34+
35+
fn third() {
36+
fourth(); // won't show up in backtrace
37+
}
38+
39+
fn fourth() {
40+
fifth(); // won't show up in backtrace
41+
}
42+
43+
fn fifth() {
44+
__rust_begin_short_backtrace(|| sixth());
45+
}
46+
47+
fn sixth() {
48+
seven();
49+
}
50+
51+
fn seven() {
52+
panic!("debug!!!");
53+
}
54+
55+
fn main() {
56+
first();
57+
}
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:52: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)