@@ -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 ) ,
@@ -19,6 +27,7 @@ pub enum TerminationInfo {
1927 msg : String ,
2028 help : Option < String > ,
2129 url : String ,
30+ history : Option < TagHistory > ,
2231 } ,
2332 Deadlock ,
2433 MultipleSymbolDefinitions {
@@ -94,7 +103,8 @@ fn prune_stacktrace<'mir, 'tcx>(
94103 // Only prune frames if there is at least one local frame. This check ensures that if
95104 // we get a backtrace that never makes it to the user code because it has detected a
96105 // bug in the Rust runtime, we don't prune away every frame.
97- let has_local_frame = stacktrace. iter ( ) . any ( |frame| frame. instance . def_id ( ) . is_local ( ) ) ;
106+ let has_local_frame =
107+ stacktrace. iter ( ) . any ( |frame| ecx. machine . is_local ( frame. instance . def_id ( ) ) ) ;
98108 if has_local_frame {
99109 // This is part of the logic that `std` uses to select the relevant part of a
100110 // backtrace. But here, we only look for __rust_begin_short_backtrace, not
@@ -115,7 +125,9 @@ fn prune_stacktrace<'mir, 'tcx>(
115125 // This len check ensures that we don't somehow remove every frame, as doing so breaks
116126 // the primary error message.
117127 while stacktrace. len ( ) > 1
118- && stacktrace. last ( ) . map_or ( false , |e| !e. instance . def_id ( ) . is_local ( ) )
128+ && stacktrace
129+ . last ( )
130+ . map_or ( false , |frame| !ecx. machine . is_local ( frame. instance . def_id ( ) ) )
119131 {
120132 stacktrace. pop ( ) ;
121133 }
@@ -155,12 +167,38 @@ pub fn report_error<'tcx, 'mir>(
155167 ( None , format!( "pass the flag `-Zmiri-disable-isolation` to disable isolation;" ) ) ,
156168 ( 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" ) ) ,
157169 ] ,
158- ExperimentalUb { url, help, .. } => {
170+ ExperimentalUb { url, help, history , .. } => {
159171 msg. extend ( help. clone ( ) ) ;
160- vec ! [
172+ let mut helps = vec ! [
161173 ( None , format!( "this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental" ) ) ,
162- ( None , format!( "see {} for further information" , url) )
163- ]
174+ ( None , format!( "see {} for further information" , url) ) ,
175+ ] ;
176+ match history {
177+ Some ( TagHistory :: Tagged { tag, created : ( created_range, created_span) , invalidated} ) => {
178+ let msg = format ! ( "{:?} was created due to a retag at offsets {}" , tag, HexRange ( * created_range) ) ;
179+ helps. push ( ( Some ( created_span. clone ( ) ) , msg) ) ;
180+ if let Some ( ( invalidated_range, invalidated_span) ) = invalidated {
181+ let msg = format ! ( "{:?} was later invalidated due to a retag at offsets {}" , tag, HexRange ( * invalidated_range) ) ;
182+ helps. push ( ( Some ( invalidated_span. clone ( ) ) , msg) ) ;
183+ }
184+ }
185+ Some ( TagHistory :: Untagged { recently_created, recently_invalidated, matching_created } ) => {
186+ if let Some ( ( range, span) ) = recently_created {
187+ let msg = format ! ( "tag was most recently created at offsets {}" , HexRange ( * range) ) ;
188+ helps. push ( ( Some ( span. clone ( ) ) , msg) ) ;
189+ }
190+ if let Some ( ( range, span) ) = recently_invalidated {
191+ let msg = format ! ( "tag was later invalidated at offsets {}" , HexRange ( * range) ) ;
192+ helps. push ( ( Some ( span. clone ( ) ) , msg) ) ;
193+ }
194+ if let Some ( ( range, span) ) = matching_created {
195+ let msg = format ! ( "this tag was also created here at offsets {}" , HexRange ( * range) ) ;
196+ helps. push ( ( Some ( span. clone ( ) ) , msg) ) ;
197+ }
198+ }
199+ None => { }
200+ }
201+ helps
164202 }
165203 MultipleSymbolDefinitions { first, first_crate, second, second_crate, .. } =>
166204 vec ! [
@@ -218,7 +256,7 @@ pub fn report_error<'tcx, 'mir>(
218256 e. print_backtrace ( ) ;
219257 msg. insert ( 0 , e. to_string ( ) ) ;
220258 report_msg (
221- * ecx. tcx ,
259+ ecx,
222260 DiagLevel :: Error ,
223261 & if let Some ( title) = title { format ! ( "{}: {}" , title, msg[ 0 ] ) } else { msg[ 0 ] . clone ( ) } ,
224262 msg,
@@ -264,19 +302,20 @@ pub fn report_error<'tcx, 'mir>(
264302/// We want to present a multi-line span message for some errors. Diagnostics do not support this
265303/// directly, so we pass the lines as a `Vec<String>` and display each line after the first with an
266304/// additional `span_label` or `note` call.
267- fn report_msg < ' tcx > (
268- tcx : TyCtxt < ' tcx > ,
305+ fn report_msg < ' mir , ' tcx > (
306+ ecx : & MiriEvalContext < ' mir , ' tcx > ,
269307 diag_level : DiagLevel ,
270308 title : & str ,
271309 span_msg : Vec < String > ,
272310 mut helps : Vec < ( Option < SpanData > , String ) > ,
273311 stacktrace : & [ FrameInfo < ' tcx > ] ,
274312) {
275313 let span = stacktrace. first ( ) . map_or ( DUMMY_SP , |fi| fi. span ) ;
314+ let sess = ecx. tcx . sess ;
276315 let mut err = match diag_level {
277- DiagLevel :: Error => tcx . sess . struct_span_err ( span, title) . forget_guarantee ( ) ,
278- DiagLevel :: Warning => tcx . sess . struct_span_warn ( span, title) ,
279- DiagLevel :: Note => tcx . sess . diagnostic ( ) . span_note_diag ( span, title) ,
316+ DiagLevel :: Error => sess. struct_span_err ( span, title) . forget_guarantee ( ) ,
317+ DiagLevel :: Warning => sess. struct_span_warn ( span, title) ,
318+ DiagLevel :: Note => sess. diagnostic ( ) . span_note_diag ( span, title) ,
280319 } ;
281320
282321 // Show main message.
@@ -306,7 +345,7 @@ fn report_msg<'tcx>(
306345 }
307346 // Add backtrace
308347 for ( idx, frame_info) in stacktrace. iter ( ) . enumerate ( ) {
309- let is_local = frame_info. instance . def_id ( ) . is_local ( ) ;
348+ let is_local = ecx . machine . is_local ( frame_info. instance . def_id ( ) ) ;
310349 // No span for non-local frames and the first frame (which is the error site).
311350 if is_local && idx > 0 {
312351 err. span_note ( frame_info. span , & frame_info. to_string ( ) ) ;
@@ -426,7 +465,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
426465 _ => ( "tracking was triggered" , DiagLevel :: Note ) ,
427466 } ;
428467
429- report_msg ( * this. tcx , diag_level, title, vec ! [ msg] , vec ! [ ] , & stacktrace) ;
468+ report_msg ( this, diag_level, title, vec ! [ msg] , vec ! [ ] , & stacktrace) ;
430469 }
431470 } ) ;
432471 }
0 commit comments