Skip to content

Commit 93fccdb

Browse files
committed
Auto merge of #151739 - Zalathar:short-backtrace, r=fee1-dead
Use fewer intermediate functions for short backtraces in queries If we make sure that `compute_fn` in the query's vtable is actually named `__rust_begin_short_backtrace`, we can avoid the need for some additional intermediate functions and stack frames. This is similar to how the `get_query_incr` and `get_query_non_incr` functions are actually named `__rust_end_short_backtrace`. --- Before/after comparison: #151739 (comment) --- - Earlier draft of this PR: #151719 - Introduction of this backtrace-trimming: #108938
2 parents db3e99b + eaff0cb commit 93fccdb

File tree

5 files changed

+68
-55
lines changed

5 files changed

+68
-55
lines changed

compiler/rustc_middle/src/query/plumbing.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
4545
pub query_cache: usize,
4646
pub will_cache_on_disk_for_key_fn: Option<WillCacheOnDiskForKeyFn<'tcx, C::Key>>,
4747
pub execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value,
48-
pub compute: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value,
48+
pub compute_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value,
4949
pub try_load_from_disk_fn: Option<TryLoadFromDiskFn<'tcx, C::Key, C::Value>>,
5050
pub is_loadable_from_disk_fn: Option<IsLoadableFromDiskFn<'tcx, C::Key>>,
5151
pub hash_result: HashResult<C::Value>,

compiler/rustc_query_impl/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use rustc_query_system::query::{
2929
};
3030
use rustc_span::{ErrorGuaranteed, Span};
3131

32-
use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green};
32+
use crate::plumbing::{encode_all_query_results, try_mark_green};
3333
use crate::profiling_support::QueryKeyStringCache;
3434

3535
#[macro_use]
@@ -123,7 +123,7 @@ where
123123

124124
#[inline(always)]
125125
fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value {
126-
(self.vtable.compute)(qcx.tcx, key)
126+
(self.vtable.compute_fn)(qcx.tcx, key)
127127
}
128128

129129
#[inline(always)]

compiler/rustc_query_impl/src/plumbing.rs

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -566,18 +566,6 @@ macro_rules! expand_if_cached {
566566
};
567567
}
568568

569-
/// Don't show the backtrace for query system by default
570-
/// use `RUST_BACKTRACE=full` to show all the backtraces
571-
#[inline(never)]
572-
pub(crate) fn __rust_begin_short_backtrace<F, T>(f: F) -> T
573-
where
574-
F: FnOnce() -> T,
575-
{
576-
let result = f();
577-
std::hint::black_box(());
578-
result
579-
}
580-
581569
// NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
582570
// invoked by `rustc_with_all_queries`.
583571
macro_rules! define_queries {
@@ -636,6 +624,32 @@ macro_rules! define_queries {
636624
}
637625
}
638626

627+
/// Defines a `compute` function for this query, to be used as a
628+
/// function pointer in the query's vtable.
629+
mod compute_fn {
630+
use super::*;
631+
use ::rustc_middle::queries::$name::{Key, Value, provided_to_erased};
632+
633+
/// This function would be named `compute`, but we also want it
634+
/// to mark the boundaries of an omitted region in backtraces.
635+
#[inline(never)]
636+
pub(crate) fn __rust_begin_short_backtrace<'tcx>(
637+
tcx: TyCtxt<'tcx>,
638+
key: Key<'tcx>,
639+
) -> Erased<Value<'tcx>> {
640+
#[cfg(debug_assertions)]
641+
let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
642+
643+
// Call the actual provider function for this query.
644+
let provided_value = call_provider!([$($modifiers)*][tcx, $name, key]);
645+
rustc_middle::ty::print::with_reduced_queries!({
646+
tracing::trace!(?provided_value);
647+
});
648+
649+
provided_to_erased(tcx, provided_value)
650+
}
651+
}
652+
639653
pub(crate) fn make_query_vtable<'tcx>()
640654
-> QueryVTable<'tcx, queries::$name::Storage<'tcx>>
641655
{
@@ -652,22 +666,7 @@ macro_rules! define_queries {
652666
None
653667
}),
654668
execute_query: |tcx, key| erase::erase_val(tcx.$name(key)),
655-
compute: |tcx, key| {
656-
#[cfg(debug_assertions)]
657-
let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
658-
__rust_begin_short_backtrace(||
659-
queries::$name::provided_to_erased(
660-
tcx,
661-
{
662-
let ret = call_provider!([$($modifiers)*][tcx, $name, key]);
663-
rustc_middle::ty::print::with_reduced_queries!({
664-
tracing::trace!(?ret);
665-
});
666-
ret
667-
}
668-
)
669-
)
670-
},
669+
compute_fn: self::compute_fn::__rust_begin_short_backtrace,
671670
try_load_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] {
672671
Some(|tcx, key, prev_index, index| {
673672
// Check the `cache_on_disk_if` condition for this key.

src/tools/run-make-support/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub use crate::assertion_helpers::{
4747
assert_contains, assert_contains_regex, assert_count_is, assert_dirs_are_equal, assert_equals,
4848
assert_not_contains, assert_not_contains_regex,
4949
};
50+
pub use crate::command::CompletedProcess;
5051
// `diff` is implemented in terms of the [similar] library.
5152
//
5253
// [similar]: https://github.com/mitsuhiko/similar

tests/run-make/short-ice/rmake.rs

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,40 +12,53 @@
1212
// - FIXME(#143198): On `x86_64-pc-windows-msvc`: full backtrace sometimes do not contain matching
1313
// count of short backtrace markers (e.g. 5x end marker, but 3x start marker).
1414

15-
use run_make_support::rustc;
15+
use run_make_support::CompletedProcess;
1616

1717
fn main() {
18-
let rust_test_1 =
19-
rustc().set_backtrace_level("1").input("src/lib.rs").arg("-Ztreat-err-as-bug=1").run_fail();
20-
let rust_test_2 = rustc()
21-
.set_backtrace_level("full")
22-
.input("src/lib.rs")
23-
.arg("-Ztreat-err-as-bug=1")
24-
.run_fail();
18+
// Run the same command twice with `RUST_BACKTRACE=1` and `RUST_BACKTRACE=full`.
19+
let configure_rustc = || {
20+
let mut rustc = run_make_support::rustc();
21+
rustc.input("src/lib.rs").arg("-Ztreat-err-as-bug=1");
22+
rustc
23+
};
24+
let rustc_bt_short = configure_rustc().set_backtrace_level("1").run_fail();
25+
let rustc_bt_full = configure_rustc().set_backtrace_level("full").run_fail();
2526

26-
let mut rust_test_log_1 = rust_test_1.stderr_utf8();
27-
rust_test_log_1.push_str(&rust_test_1.stdout_utf8());
28-
let rust_test_log_1 = rust_test_log_1.as_str();
27+
// Combine stderr and stdout for subsequent checks.
28+
let concat_stderr_stdout =
29+
|proc: &CompletedProcess| format!("{}\n{}", proc.stderr_utf8(), proc.stdout_utf8());
30+
let output_bt_short = &concat_stderr_stdout(&rustc_bt_short);
31+
let output_bt_full = &concat_stderr_stdout(&rustc_bt_full);
2932

30-
let mut rust_test_log_2 = rust_test_2.stderr_utf8();
31-
rust_test_log_2.push_str(&rust_test_2.stdout_utf8());
32-
let rust_test_log_2 = rust_test_log_2.as_str();
33+
// Count how many lines of output mention symbols or paths in
34+
// `rustc_query_system` or `rustc_query_impl`, which are the kinds of
35+
// stack frames we want to be omitting in short backtraces.
36+
let rustc_query_count_short = count_lines_with(output_bt_short, "rustc_query_");
37+
let rustc_query_count_full = count_lines_with(output_bt_full, "rustc_query_");
3338

34-
let rustc_query_count_full = count_lines_with(rust_test_log_2, "rustc_query_");
39+
// Dump both outputs in full to make debugging easier, especially on CI.
40+
// Use `--no-capture --force-rerun` to view output even when the test is passing.
41+
println!("=== BEGIN SHORT BACKTRACE ===\n{output_bt_short}\n=== END SHORT BACKTRACE === ");
42+
println!("=== BEGIN FULL BACKTRACE ===\n{output_bt_full}\n=== END FULL BACKTRACE === ");
3543

3644
assert!(
37-
rust_test_log_1.lines().count() < rust_test_log_2.lines().count(),
38-
"Short backtrace should be shorter than full backtrace.\nShort backtrace:\n\
39-
{rust_test_log_1}\nFull backtrace:\n{rust_test_log_2}"
45+
output_bt_short.lines().count() < output_bt_full.lines().count(),
46+
"Short backtrace should be shorter than full backtrace"
4047
);
48+
49+
let n_begin = count_lines_with(output_bt_full, "__rust_begin_short_backtrace");
50+
let n_end = count_lines_with(output_bt_full, "__rust_end_short_backtrace");
51+
assert!(n_begin + n_end > 0, "Full backtrace should contain short-backtrace markers");
4152
assert_eq!(
42-
count_lines_with(rust_test_log_2, "__rust_begin_short_backtrace"),
43-
count_lines_with(rust_test_log_2, "__rust_end_short_backtrace"),
44-
"Full backtrace should contain the short backtrace markers.\nFull backtrace:\n\
45-
{rust_test_log_2}"
53+
n_begin, n_end,
54+
"Full backtrace should contain equal numbers of begin and end markers"
55+
);
56+
57+
assert!(
58+
rustc_query_count_short + 5 < rustc_query_count_full,
59+
"Short backtrace should have omitted more query plumbing lines \
60+
(actual: {rustc_query_count_short} vs {rustc_query_count_full})"
4661
);
47-
assert!(count_lines_with(rust_test_log_1, "rustc_query_") + 5 < rustc_query_count_full);
48-
assert!(rustc_query_count_full > 5);
4962
}
5063

5164
fn count_lines_with(s: &str, search: &str) -> usize {

0 commit comments

Comments
 (0)