@@ -4,12 +4,20 @@ use std::num::NonZeroU64;
44
55use log:: trace;
66
7- use rustc_middle:: ty:: { self , TyCtxt } ;
7+ use rustc_middle:: ty;
88use rustc_span:: { source_map:: DUMMY_SP , Span , SpanData , Symbol } ;
99
10- use crate :: stacked_borrows:: { AccessKind , SbTag } ;
10+ use crate :: stacked_borrows:: { AccessKind , SbTag , TagHistory } ;
1111use crate :: * ;
1212
13+ struct HexRange ( AllocRange ) ;
14+
15+ impl std:: fmt:: Display for HexRange {
16+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
17+ write ! ( f, "[{:#x}..{:#x}]" , self . 0 . start. bytes( ) , self . 0 . end( ) . bytes( ) )
18+ }
19+ }
20+
1321/// Details of premature program termination.
1422pub enum TerminationInfo {
1523 Exit ( i64 ) ,
@@ -18,6 +26,7 @@ pub enum TerminationInfo {
1826 ExperimentalUb {
1927 msg : String ,
2028 url : String ,
29+ history : Option < TagHistory > ,
2130 } ,
2231 Deadlock ,
2332 MultipleSymbolDefinitions {
@@ -93,7 +102,8 @@ fn prune_stacktrace<'mir, 'tcx>(
93102 // Only prune frames if there is at least one local frame. This check ensures that if
94103 // we get a backtrace that never makes it to the user code because it has detected a
95104 // bug in the Rust runtime, we don't prune away every frame.
96- let has_local_frame = stacktrace. iter ( ) . any ( |frame| frame. instance . def_id ( ) . is_local ( ) ) ;
105+ let has_local_frame =
106+ stacktrace. iter ( ) . any ( |frame| ecx. machine . is_local ( frame. instance . def_id ( ) ) ) ;
97107 if has_local_frame {
98108 // This is part of the logic that `std` uses to select the relevant part of a
99109 // backtrace. But here, we only look for __rust_begin_short_backtrace, not
@@ -114,7 +124,9 @@ fn prune_stacktrace<'mir, 'tcx>(
114124 // This len check ensures that we don't somehow remove every frame, as doing so breaks
115125 // the primary error message.
116126 while stacktrace. len ( ) > 1
117- && stacktrace. last ( ) . map_or ( false , |e| !e. instance . def_id ( ) . is_local ( ) )
127+ && stacktrace
128+ . last ( )
129+ . map_or ( false , |frame| !ecx. machine . is_local ( frame. instance . def_id ( ) ) )
118130 {
119131 stacktrace. pop ( ) ;
120132 }
@@ -152,11 +164,38 @@ pub fn report_error<'tcx, 'mir>(
152164 ( None , format!( "pass the flag `-Zmiri-disable-isolation` to disable isolation;" ) ) ,
153165 ( None , format!( "or pass `-Zmiri-isolation-error=warn to configure Miri to return an error code from isolated operations (if supported for that operation) and continue with a warning" ) ) ,
154166 ] ,
155- ExperimentalUb { url, .. } =>
156- vec ! [
167+ ExperimentalUb { url, history , .. } => {
168+ let mut helps = vec ! [
157169 ( None , format!( "this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental" ) ) ,
158170 ( None , format!( "see {} for further information" , url) ) ,
159- ] ,
171+ ] ;
172+ match history {
173+ Some ( TagHistory :: Tagged { tag, created : ( created_range, created_span) , invalidated} ) => {
174+ let msg = format ! ( "{:?} was created due to a retag at offsets {}" , tag, HexRange ( * created_range) ) ;
175+ helps. push ( ( Some ( created_span. clone ( ) ) , msg) ) ;
176+ if let Some ( ( invalidated_range, invalidated_span) ) = invalidated {
177+ let msg = format ! ( "{:?} was later invalidated due to a retag at offsets {}" , tag, HexRange ( * invalidated_range) ) ;
178+ helps. push ( ( Some ( invalidated_span. clone ( ) ) , msg) ) ;
179+ }
180+ }
181+ Some ( TagHistory :: Untagged { recently_created, recently_invalidated, matching_created } ) => {
182+ if let Some ( ( range, span) ) = recently_created {
183+ let msg = format ! ( "tag was most recently created at offsets {}" , HexRange ( * range) ) ;
184+ helps. push ( ( Some ( span. clone ( ) ) , msg) ) ;
185+ }
186+ if let Some ( ( range, span) ) = recently_invalidated {
187+ let msg = format ! ( "tag was later invalidated at offsets {}" , HexRange ( * range) ) ;
188+ helps. push ( ( Some ( span. clone ( ) ) , msg) ) ;
189+ }
190+ if let Some ( ( range, span) ) = matching_created {
191+ let msg = format ! ( "this tag was also created here at offsets {}" , HexRange ( * range) ) ;
192+ helps. push ( ( Some ( span. clone ( ) ) , msg) ) ;
193+ }
194+ }
195+ None => { }
196+ }
197+ helps
198+ }
160199 MultipleSymbolDefinitions { first, first_crate, second, second_crate, .. } =>
161200 vec ! [
162201 ( Some ( * first) , format!( "it's first defined here, in crate `{}`" , first_crate) ) ,
@@ -213,7 +252,7 @@ pub fn report_error<'tcx, 'mir>(
213252 e. print_backtrace ( ) ;
214253 let msg = e. to_string ( ) ;
215254 report_msg (
216- * ecx. tcx ,
255+ ecx,
217256 DiagLevel :: Error ,
218257 & if let Some ( title) = title { format ! ( "{}: {}" , title, msg) } else { msg. clone ( ) } ,
219258 msg,
@@ -256,24 +295,25 @@ pub fn report_error<'tcx, 'mir>(
256295
257296/// Report an error or note (depending on the `error` argument) with the given stacktrace.
258297/// Also emits a full stacktrace of the interpreter stack.
259- fn report_msg < ' tcx > (
260- tcx : TyCtxt < ' tcx > ,
298+ fn report_msg < ' mir , ' tcx > (
299+ ecx : & MiriEvalContext < ' mir , ' tcx > ,
261300 diag_level : DiagLevel ,
262301 title : & str ,
263302 span_msg : String ,
264303 mut helps : Vec < ( Option < SpanData > , String ) > ,
265304 stacktrace : & [ FrameInfo < ' tcx > ] ,
266305) {
267306 let span = stacktrace. first ( ) . map_or ( DUMMY_SP , |fi| fi. span ) ;
307+ let sess = ecx. tcx . sess ;
268308 let mut err = match diag_level {
269- DiagLevel :: Error => tcx . sess . struct_span_err ( span, title) . forget_guarantee ( ) ,
270- DiagLevel :: Warning => tcx . sess . struct_span_warn ( span, title) ,
271- DiagLevel :: Note => tcx . sess . diagnostic ( ) . span_note_diag ( span, title) ,
309+ DiagLevel :: Error => sess. struct_span_err ( span, title) . forget_guarantee ( ) ,
310+ DiagLevel :: Warning => sess. struct_span_warn ( span, title) ,
311+ DiagLevel :: Note => sess. diagnostic ( ) . span_note_diag ( span, title) ,
272312 } ;
273313
274314 // Show main message.
275315 if span != DUMMY_SP {
276- err. span_label ( span, span_msg) ;
316+ err. span_label ( span, span_msg) . note ( & stacktrace [ 0 ] . to_string ( ) ) ;
277317 } else {
278318 // Make sure we show the message even when it is a dummy span.
279319 err. note ( & span_msg) ;
@@ -293,7 +333,7 @@ fn report_msg<'tcx>(
293333 }
294334 // Add backtrace
295335 for ( idx, frame_info) in stacktrace. iter ( ) . enumerate ( ) {
296- let is_local = frame_info. instance . def_id ( ) . is_local ( ) ;
336+ let is_local = ecx . machine . is_local ( frame_info. instance . def_id ( ) ) ;
297337 // No span for non-local frames and the first frame (which is the error site).
298338 if is_local && idx > 0 {
299339 err. span_note ( frame_info. span , & frame_info. to_string ( ) ) ;
@@ -413,7 +453,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
413453 _ => ( "tracking was triggered" , DiagLevel :: Note ) ,
414454 } ;
415455
416- report_msg ( * this. tcx , diag_level, title, msg, vec ! [ ] , & stacktrace) ;
456+ report_msg ( this, diag_level, title, msg, vec ! [ ] , & stacktrace) ;
417457 }
418458 } ) ;
419459 }
0 commit comments