Skip to content

Commit 97d8492

Browse files
committed
adjust how backtraces get rendered; always show thread name when there are multiple threads
1 parent 5c65433 commit 97d8492

File tree

233 files changed

+997
-765
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

233 files changed

+997
-765
lines changed

src/diagnostics.rs

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ pub fn report_result<'tcx>(
250250
StackedBorrowsUb { .. } | TreeBorrowsUb { .. } | DataRace { .. } =>
251251
Some("Undefined Behavior"),
252252
LocalDeadlock => {
253-
labels.push(format!("this thread got stuck here"));
253+
labels.push(format!("thread got stuck here"));
254254
None
255255
}
256256
GlobalDeadlock => {
@@ -264,10 +264,7 @@ pub fn report_result<'tcx>(
264264
report_msg(
265265
DiagLevel::Error,
266266
format!("the evaluated program deadlocked"),
267-
vec![format!(
268-
"thread `{}` got stuck here",
269-
ecx.machine.threads.get_thread_display_name(thread)
270-
)],
267+
vec![format!("thread got stuck here")],
271268
vec![],
272269
vec![],
273270
&stacktrace,
@@ -563,6 +560,7 @@ pub fn report_msg<'tcx>(
563560
None =>
564561
match thread {
565562
Some(thread_id) => machine.threads.thread_ref(thread_id).origin_span,
563+
// This fallback is super rare, but can happen e.g. when `main` has the wrong ABI
566564
None => DUMMY_SP,
567565
},
568566
};
@@ -608,36 +606,53 @@ pub fn report_msg<'tcx>(
608606
}
609607

610608
// Add backtrace
611-
if stacktrace.len() > 1 {
612-
let mut backtrace_title = String::from("BACKTRACE");
613-
if extra_span {
614-
write!(backtrace_title, " (of the first span)").unwrap();
609+
if let Some((first, rest)) = stacktrace.split_first() {
610+
// Start with the function and thread that contain the first span.
611+
let mut fn_and_thread = String::new();
612+
// Only print thread name if there are multiple threads.
613+
if let Some(thread) = thread
614+
&& machine.threads.get_total_thread_count() > 1
615+
{
616+
write!(
617+
fn_and_thread,
618+
"on thread `{}`",
619+
machine.threads.get_thread_display_name(thread)
620+
)
621+
.unwrap();
622+
}
623+
// Only print function name if we show a backtrace
624+
if rest.len() > 0 {
625+
if !fn_and_thread.is_empty() {
626+
fn_and_thread.push_str(", ");
627+
}
628+
write!(fn_and_thread, "{first}").unwrap();
615629
}
616-
if let Some(thread) = thread {
617-
let thread_name = machine.threads.get_thread_display_name(thread);
618-
if thread_name != "main" {
619-
// Only print thread name if it is not `main`.
620-
write!(backtrace_title, " on thread `{thread_name}`").unwrap();
621-
};
630+
if !fn_and_thread.is_empty() {
631+
if extra_span && rest.len() > 0 {
632+
// Print a `span_note` as otherwise the backtrace looks attached to the last
633+
// `span_help`. We somewhat arbitrarily use the span of the surrounding function.
634+
err.span_note(
635+
machine.tcx.def_span(first.instance.def_id()),
636+
format!("{level} occurred {fn_and_thread}"),
637+
);
638+
} else {
639+
err.note(format!("this is {fn_and_thread}"));
640+
}
622641
}
623-
write!(backtrace_title, ":").unwrap();
624-
err.note(backtrace_title);
625-
for (idx, frame_info) in stacktrace.iter().enumerate() {
642+
// Continue with where that function got called.
643+
for frame_info in rest.iter() {
626644
let is_local = machine.is_local(frame_info.instance);
627645
// No span for non-local frames and the first frame (which is the error site).
628-
if is_local && idx > 0 {
629-
err.subdiagnostic(frame_info.as_note(machine.tcx));
646+
if is_local {
647+
err.span_note(frame_info.span, format!("which got called {frame_info}"));
630648
} else {
631649
let sm = sess.source_map();
632650
let span = sm.span_to_embeddable_string(frame_info.span);
633-
err.note(format!("{frame_info} at {span}"));
651+
err.note(format!("which got called {frame_info} (at {span})"));
634652
}
635653
}
636-
} else if stacktrace.len() == 0 && !span.is_dummy() {
637-
err.note(format!(
638-
"this {} occurred while pushing a call frame onto an empty stack",
639-
level.to_str()
640-
));
654+
} else if !span.is_dummy() {
655+
err.note(format!("this {level} occurred while pushing a call frame onto an empty stack"));
641656
err.note("the span indicates which code caused the function to be called, but may not be the literal call site");
642657
}
643658

tests/fail-dep/concurrency/apple_os_unfair_lock_move_with_queue.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ LL | let _val = atomic_ref.load(Ordering::Relaxed);
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: this is on thread `unnamed-ID`
910

1011
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
1112

tests/fail-dep/concurrency/libc_pthread_cond_move.init.stderr

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ LL | libc::pthread_cond_destroy(cond2.as_mut_ptr());
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9-
= note: BACKTRACE:
10-
= note: inside `check` at tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC
11-
note: inside `main`
9+
= note: this is inside `check`
10+
note: which got called inside `main`
1211
--> tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC
1312
|
1413
LL | check()

tests/fail-dep/concurrency/libc_pthread_cond_move.static_initializer.stderr

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ LL | libc::pthread_cond_destroy(&mut cond2 as *mut _);
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9-
= note: BACKTRACE:
10-
= note: inside `check` at tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC
11-
note: inside `main`
9+
= note: this is inside `check`
10+
note: which got called inside `main`
1211
--> tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC
1312
|
1413
LL | check()

tests/fail-dep/concurrency/libc_pthread_join_detached.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ LL | assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0);
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: this is on thread `main`
910

1011
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
1112

tests/fail-dep/concurrency/libc_pthread_join_joined.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ LL | ... assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0);
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: this is on thread `main`
910

1011
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
1112

tests/fail-dep/concurrency/libc_pthread_join_main.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ LL | ... assert_eq!(libc::pthread_join(thread_id, ptr::null_mut()), 0);
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: this is on thread `unnamed-ID`
910

1011
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
1112

tests/fail-dep/concurrency/libc_pthread_join_multiple.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ LL | ... assert_eq!(libc::pthread_join(native_copy, ptr::null_mut()), 0);
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: this is on thread `unnamed-ID`
910

1011
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
1112

tests/fail-dep/concurrency/libc_pthread_join_self.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ LL | assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0);
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: this is on thread `unnamed-ID`
910

1011
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
1112

tests/fail-dep/concurrency/libc_pthread_mutex_deadlock.stderr

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ error: the evaluated program deadlocked
22
--> RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC
33
|
44
LL | let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) };
5-
| ^ thread `main` got stuck here
5+
| ^ thread got stuck here
66
|
7-
= note: BACKTRACE:
8-
= note: inside `std::sys::thread::PLATFORM::Thread::join` at RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC
9-
= note: inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC
10-
= note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/join_handle.rs:LL:CC
11-
note: inside `main`
7+
= note: this is on thread `main`, inside `std::sys::thread::PLATFORM::Thread::join`
8+
= note: which got called inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` (at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC)
9+
= note: which got called inside `std::thread::JoinHandle::<()>::join` (at RUSTLIB/std/src/thread/join_handle.rs:LL:CC)
10+
note: which got called inside `main`
1211
--> tests/fail-dep/concurrency/libc_pthread_mutex_deadlock.rs:LL:CC
1312
|
1413
LL | / thread::spawn(move || {
@@ -21,7 +20,9 @@ error: the evaluated program deadlocked
2120
--> tests/fail-dep/concurrency/libc_pthread_mutex_deadlock.rs:LL:CC
2221
|
2322
LL | assert_eq!(libc::pthread_mutex_lock(lock_copy.0.get() as *mut _), 0);
24-
| ^ thread `unnamed-ID` got stuck here
23+
| ^ thread got stuck here
24+
|
25+
= note: this is on thread `unnamed-ID`
2526

2627
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
2728

0 commit comments

Comments
 (0)