@@ -75,24 +75,26 @@ enum DiagLevel {
7575 Note ,
7676}
7777
78- fn has_local_frame ( stacktrace : & [ FrameInfo < ' _ > ] ) -> bool {
79- stacktrace. iter ( ) . any ( |frame| frame. instance . def_id ( ) . is_local ( ) )
80- }
81-
78+ /// Attempts to prune a stacktrace to omit the Rust runtime, and returns a bool indicating if any
79+ /// frames were pruned. If the stacktrace does not have any local frames, we conclude that it must
80+ /// be pointing to a problem in the Rust runtime itself, and do not prune it at all.
8281fn prune_stacktrace < ' mir , ' tcx > (
8382 ecx : & InterpCx < ' mir , ' tcx , Evaluator < ' mir , ' tcx > > ,
8483 mut stacktrace : Vec < FrameInfo < ' tcx > > ,
85- ) -> Vec < FrameInfo < ' tcx > > {
84+ ) -> ( Vec < FrameInfo < ' tcx > > , bool ) {
8685 match ecx. machine . backtrace_style {
8786 BacktraceStyle :: Off => {
8887 // Retain one frame so that we can print a span for the error itself
8988 stacktrace. truncate ( 1 ) ;
89+ ( stacktrace, false )
9090 }
9191 BacktraceStyle :: Short => {
92+ let original_len = stacktrace. len ( ) ;
9293 // Only prune frames if there is at least one local frame. This check ensures that if
9394 // we get a backtrace that never makes it to the user code because it has detected a
9495 // bug in the Rust runtime, we don't prune away every frame.
95- if has_local_frame ( & stacktrace) {
96+ let has_local_frame = stacktrace. iter ( ) . any ( |frame| frame. instance . def_id ( ) . is_local ( ) ) ;
97+ if has_local_frame {
9698 // This is part of the logic that `std` uses to select the relevant part of a
9799 // backtrace. But here, we only look for __rust_begin_short_backtrace, not
98100 // __rust_end_short_backtrace because the end symbol comes from a call to the default
@@ -117,10 +119,11 @@ fn prune_stacktrace<'mir, 'tcx>(
117119 stacktrace. pop ( ) ;
118120 }
119121 }
122+ let was_pruned = stacktrace. len ( ) != original_len;
123+ ( stacktrace, was_pruned)
120124 }
121- BacktraceStyle :: Full => { }
125+ BacktraceStyle :: Full => ( stacktrace , false ) ,
122126 }
123- stacktrace
124127}
125128
126129/// Emit a custom diagnostic without going through the miri-engine machinery
@@ -206,7 +209,7 @@ pub fn report_error<'tcx, 'mir>(
206209 } ;
207210
208211 let stacktrace = ecx. generate_stacktrace ( ) ;
209- let stacktrace = prune_stacktrace ( ecx, stacktrace) ;
212+ let ( stacktrace, was_pruned ) = prune_stacktrace ( ecx, stacktrace) ;
210213 e. print_backtrace ( ) ;
211214 let msg = e. to_string ( ) ;
212215 report_msg (
@@ -218,9 +221,8 @@ pub fn report_error<'tcx, 'mir>(
218221 & stacktrace,
219222 ) ;
220223
221- // Include a note like `std` does for short backtraces, but since we are opt-out not opt-in, we
222- // do not include a note when backtraces are off.
223- if ecx. machine . backtrace_style == BacktraceStyle :: Short && has_local_frame ( & stacktrace) {
224+ // Include a note like `std` does when we omit frames from a backtrace
225+ if was_pruned {
224226 ecx. tcx . sess . diagnostic ( ) . note_without_error (
225227 "some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace" ,
226228 ) ;
@@ -377,7 +379,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
377379 ) ;
378380 }
379381
380- let stacktrace = prune_stacktrace ( this, stacktrace) ;
382+ let ( stacktrace, _was_pruned ) = prune_stacktrace ( this, stacktrace) ;
381383
382384 // Show diagnostics.
383385 for e in diagnostics. drain ( ..) {
0 commit comments