@@ -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 ) ,
@@ -18,6 +26,7 @@ pub enum TerminationInfo {
18
26
ExperimentalUb {
19
27
msg : String ,
20
28
url : String ,
29
+ history : Option < TagHistory > ,
21
30
} ,
22
31
Deadlock ,
23
32
MultipleSymbolDefinitions {
@@ -93,7 +102,8 @@ fn prune_stacktrace<'mir, 'tcx>(
93
102
// Only prune frames if there is at least one local frame. This check ensures that if
94
103
// we get a backtrace that never makes it to the user code because it has detected a
95
104
// 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 ( ) ) ) ;
97
107
if has_local_frame {
98
108
// This is part of the logic that `std` uses to select the relevant part of a
99
109
// backtrace. But here, we only look for __rust_begin_short_backtrace, not
@@ -114,7 +124,9 @@ fn prune_stacktrace<'mir, 'tcx>(
114
124
// This len check ensures that we don't somehow remove every frame, as doing so breaks
115
125
// the primary error message.
116
126
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 ( ) ) )
118
130
{
119
131
stacktrace. pop ( ) ;
120
132
}
@@ -152,11 +164,38 @@ pub fn report_error<'tcx, 'mir>(
152
164
( None , format!( "pass the flag `-Zmiri-disable-isolation` to disable isolation;" ) ) ,
153
165
( 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" ) ) ,
154
166
] ,
155
- ExperimentalUb { url, .. } =>
156
- vec ! [
167
+ ExperimentalUb { url, history , .. } => {
168
+ let mut helps = vec ! [
157
169
( None , format!( "this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental" ) ) ,
158
170
( 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
+ }
160
199
MultipleSymbolDefinitions { first, first_crate, second, second_crate, .. } =>
161
200
vec ! [
162
201
( Some ( * first) , format!( "it's first defined here, in crate `{}`" , first_crate) ) ,
@@ -213,7 +252,7 @@ pub fn report_error<'tcx, 'mir>(
213
252
e. print_backtrace ( ) ;
214
253
let msg = e. to_string ( ) ;
215
254
report_msg (
216
- * ecx. tcx ,
255
+ ecx,
217
256
DiagLevel :: Error ,
218
257
& if let Some ( title) = title { format ! ( "{}: {}" , title, msg) } else { msg. clone ( ) } ,
219
258
msg,
@@ -256,24 +295,25 @@ pub fn report_error<'tcx, 'mir>(
256
295
257
296
/// Report an error or note (depending on the `error` argument) with the given stacktrace.
258
297
/// 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 > ,
261
300
diag_level : DiagLevel ,
262
301
title : & str ,
263
302
span_msg : String ,
264
303
mut helps : Vec < ( Option < SpanData > , String ) > ,
265
304
stacktrace : & [ FrameInfo < ' tcx > ] ,
266
305
) {
267
306
let span = stacktrace. first ( ) . map_or ( DUMMY_SP , |fi| fi. span ) ;
307
+ let sess = ecx. tcx . sess ;
268
308
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) ,
272
312
} ;
273
313
274
314
// Show main message.
275
315
if span != DUMMY_SP {
276
- err. span_label ( span, span_msg) ;
316
+ err. span_label ( span, span_msg) . note ( & stacktrace [ 0 ] . to_string ( ) ) ;
277
317
} else {
278
318
// Make sure we show the message even when it is a dummy span.
279
319
err. note ( & span_msg) ;
@@ -293,7 +333,7 @@ fn report_msg<'tcx>(
293
333
}
294
334
// Add backtrace
295
335
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 ( ) ) ;
297
337
// No span for non-local frames and the first frame (which is the error site).
298
338
if is_local && idx > 0 {
299
339
err. span_note ( frame_info. span , & frame_info. to_string ( ) ) ;
@@ -413,7 +453,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
413
453
_ => ( "tracking was triggered" , DiagLevel :: Note ) ,
414
454
} ;
415
455
416
- report_msg ( * this. tcx , diag_level, title, msg, vec ! [ ] , & stacktrace) ;
456
+ report_msg ( this, diag_level, title, msg, vec ! [ ] , & stacktrace) ;
417
457
}
418
458
} ) ;
419
459
}
0 commit comments