@@ -4,12 +4,20 @@ use std::num::NonZeroU64;
4
4
5
5
use log:: trace;
6
6
7
- use rustc_middle:: ty:: { self , TyCtxt } ;
7
+ use rustc_middle:: ty;
8
8
use rustc_span:: { source_map:: DUMMY_SP , Span , SpanData , Symbol } ;
9
9
10
- use crate :: stacked_borrows:: { AccessKind , SbTag } ;
10
+ use crate :: stacked_borrows:: { AccessKind , SbTag , TagHistory } ;
11
11
use crate :: * ;
12
12
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
+
13
21
/// Details of premature program termination.
14
22
pub enum TerminationInfo {
15
23
Exit ( i64 ) ,
@@ -19,6 +27,7 @@ pub enum TerminationInfo {
19
27
msg : String ,
20
28
help : Option < String > ,
21
29
url : String ,
30
+ history : Option < TagHistory > ,
22
31
} ,
23
32
Deadlock ,
24
33
MultipleSymbolDefinitions {
@@ -94,7 +103,8 @@ fn prune_stacktrace<'mir, 'tcx>(
94
103
// Only prune frames if there is at least one local frame. This check ensures that if
95
104
// we get a backtrace that never makes it to the user code because it has detected a
96
105
// 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 ( ) ) ) ;
98
108
if has_local_frame {
99
109
// This is part of the logic that `std` uses to select the relevant part of a
100
110
// backtrace. But here, we only look for __rust_begin_short_backtrace, not
@@ -115,7 +125,9 @@ fn prune_stacktrace<'mir, 'tcx>(
115
125
// This len check ensures that we don't somehow remove every frame, as doing so breaks
116
126
// the primary error message.
117
127
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 ( ) ) )
119
131
{
120
132
stacktrace. pop ( ) ;
121
133
}
@@ -155,12 +167,38 @@ pub fn report_error<'tcx, 'mir>(
155
167
( None , format!( "pass the flag `-Zmiri-disable-isolation` to disable isolation;" ) ) ,
156
168
( 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" ) ) ,
157
169
] ,
158
- ExperimentalUb { url, help, .. } => {
170
+ ExperimentalUb { url, help, history , .. } => {
159
171
msg. extend ( help. clone ( ) ) ;
160
- vec ! [
172
+ let mut helps = vec ! [
161
173
( 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
164
202
}
165
203
MultipleSymbolDefinitions { first, first_crate, second, second_crate, .. } =>
166
204
vec ! [
@@ -218,7 +256,7 @@ pub fn report_error<'tcx, 'mir>(
218
256
e. print_backtrace ( ) ;
219
257
msg. insert ( 0 , e. to_string ( ) ) ;
220
258
report_msg (
221
- * ecx. tcx ,
259
+ ecx,
222
260
DiagLevel :: Error ,
223
261
& if let Some ( title) = title { format ! ( "{}: {}" , title, msg[ 0 ] ) } else { msg[ 0 ] . clone ( ) } ,
224
262
msg,
@@ -264,19 +302,20 @@ pub fn report_error<'tcx, 'mir>(
264
302
/// We want to present a multi-line span message for some errors. Diagnostics do not support this
265
303
/// directly, so we pass the lines as a `Vec<String>` and display each line after the first with an
266
304
/// 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 > ,
269
307
diag_level : DiagLevel ,
270
308
title : & str ,
271
309
span_msg : Vec < String > ,
272
310
mut helps : Vec < ( Option < SpanData > , String ) > ,
273
311
stacktrace : & [ FrameInfo < ' tcx > ] ,
274
312
) {
275
313
let span = stacktrace. first ( ) . map_or ( DUMMY_SP , |fi| fi. span ) ;
314
+ let sess = ecx. tcx . sess ;
276
315
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) ,
280
319
} ;
281
320
282
321
// Show main message.
@@ -306,7 +345,7 @@ fn report_msg<'tcx>(
306
345
}
307
346
// Add backtrace
308
347
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 ( ) ) ;
310
349
// No span for non-local frames and the first frame (which is the error site).
311
350
if is_local && idx > 0 {
312
351
err. span_note ( frame_info. span , & frame_info. to_string ( ) ) ;
@@ -426,7 +465,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
426
465
_ => ( "tracking was triggered" , DiagLevel :: Note ) ,
427
466
} ;
428
467
429
- report_msg ( * this. tcx , diag_level, title, vec ! [ msg] , vec ! [ ] , & stacktrace) ;
468
+ report_msg ( this, diag_level, title, vec ! [ msg] , vec ! [ ] , & stacktrace) ;
430
469
}
431
470
} ) ;
432
471
}
0 commit comments