1- use rustc_mir:: interpret:: InterpErrorInfo ;
21use std:: cell:: RefCell ;
32
3+ use rustc_span:: DUMMY_SP ;
4+
45use crate :: * ;
56
67/// Miri specific diagnostics
@@ -14,62 +15,80 @@ pub fn report_diagnostic<'tcx, 'mir>(
1415 ecx : & InterpCx < ' mir , ' tcx , Evaluator < ' tcx > > ,
1516 mut e : InterpErrorInfo < ' tcx > ,
1617) -> Option < i64 > {
17- // Special treatment for some error kinds
18+ use InterpError :: * ;
19+ let title = match e. kind {
20+ Unsupported ( _) => "unsupported operation" ,
21+ UndefinedBehavior ( _) => "Undefined Behavior" ,
22+ InvalidProgram ( _) => bug ! ( "This error should be impossible in Miri: {}" , e) ,
23+ ResourceExhaustion ( _) => "resource exhaustion" ,
24+ MachineStop ( _) => "program stopped" ,
25+ } ;
1826 let msg = match e. kind {
19- InterpError :: MachineStop ( ref info) => {
27+ MachineStop ( ref info) => {
2028 let info = info. downcast_ref :: < TerminationInfo > ( ) . expect ( "invalid MachineStop payload" ) ;
2129 match info {
2230 TerminationInfo :: Exit ( code) => return Some ( * code) ,
2331 TerminationInfo :: Abort ( None ) => format ! ( "the evaluated program aborted execution" ) ,
2432 TerminationInfo :: Abort ( Some ( msg) ) => format ! ( "the evaluated program aborted execution: {}" , msg) ,
2533 }
2634 }
27- err_unsup ! ( NoMirFor ( ..) ) => format ! (
28- "{}. Did you set `MIRI_SYSROOT` to a Miri-enabled sysroot? You can prepare one with `cargo miri setup`." ,
29- e
30- ) ,
31- InterpError :: InvalidProgram ( _) => bug ! ( "This error should be impossible in Miri: {}" , e) ,
3235 _ => e. to_string ( ) ,
3336 } ;
37+ let help = match e. kind {
38+ Unsupported ( UnsupportedOpInfo :: NoMirFor ( ..) ) =>
39+ Some ( "set `MIRI_SYSROOT` to a Miri sysroot, which you can prepare with `cargo miri setup`" ) ,
40+ Unsupported ( _) =>
41+ Some ( "this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support" ) ,
42+ UndefinedBehavior ( UndefinedBehaviorInfo :: UbExperimental ( _) ) =>
43+ Some ( "this indicates a potential bug in the program: it violated *experimental* rules, and caused Undefined Behavior" ) ,
44+ UndefinedBehavior ( _) =>
45+ Some ( "this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior" ) ,
46+ _ => None ,
47+ } ;
3448 e. print_backtrace ( ) ;
35- report_msg ( ecx, msg, true )
49+ report_msg ( ecx, & format ! ( "{}: {}" , title , msg) , msg , help , true )
3650}
3751
3852/// Report an error or note (depending on the `error` argument) at the current frame's current statement.
3953/// Also emits a full stacktrace of the interpreter stack.
4054pub fn report_msg < ' tcx , ' mir > (
4155 ecx : & InterpCx < ' mir , ' tcx , Evaluator < ' tcx > > ,
42- msg : String ,
56+ title : & str ,
57+ span_msg : String ,
58+ help : Option < & str > ,
4359 error : bool ,
4460) -> Option < i64 > {
45- if let Some ( frame) = ecx. stack ( ) . last ( ) {
46- let span = frame. current_source_info ( ) . unwrap ( ) . span ;
47-
48- let mut err = if error {
49- let msg = format ! ( "Miri evaluation error: {}" , msg) ;
50- ecx. tcx . sess . struct_span_err ( span, msg. as_str ( ) )
61+ let span = if let Some ( frame) = ecx. stack ( ) . last ( ) {
62+ frame. current_source_info ( ) . unwrap ( ) . span
63+ } else {
64+ DUMMY_SP
65+ } ;
66+ let mut err = if error {
67+ ecx. tcx . sess . struct_span_err ( span, title)
68+ } else {
69+ ecx. tcx . sess . diagnostic ( ) . span_note_diag ( span, title)
70+ } ;
71+ err. span_label ( span, span_msg) ;
72+ if let Some ( help) = help {
73+ err. help ( help) ;
74+ }
75+ // Add backtrace
76+ let frames = ecx. generate_stacktrace ( None ) ;
77+ // We iterate with indices because we need to look at the next frame (the caller).
78+ for idx in 0 ..frames. len ( ) {
79+ let frame_info = & frames[ idx] ;
80+ let call_site_is_local = frames
81+ . get ( idx + 1 )
82+ . map_or ( false , |caller_info| caller_info. instance . def_id ( ) . is_local ( ) ) ;
83+ if call_site_is_local {
84+ err. span_note ( frame_info. call_site , & frame_info. to_string ( ) ) ;
5185 } else {
52- ecx. tcx . sess . diagnostic ( ) . span_note_diag ( span, msg. as_str ( ) )
53- } ;
54- let frames = ecx. generate_stacktrace ( None ) ;
55- err. span_label ( span, msg) ;
56- // We iterate with indices because we need to look at the next frame (the caller).
57- for idx in 0 ..frames. len ( ) {
58- let frame_info = & frames[ idx] ;
59- let call_site_is_local = frames
60- . get ( idx + 1 )
61- . map_or ( false , |caller_info| caller_info. instance . def_id ( ) . is_local ( ) ) ;
62- if call_site_is_local {
63- err. span_note ( frame_info. call_site , & frame_info. to_string ( ) ) ;
64- } else {
65- err. note ( & frame_info. to_string ( ) ) ;
66- }
86+ err. note ( & frame_info. to_string ( ) ) ;
6787 }
68- err. emit ( ) ;
69- } else {
70- ecx. tcx . sess . err ( & msg) ;
7188 }
7289
90+ err. emit ( ) ;
91+
7392 for ( i, frame) in ecx. stack ( ) . iter ( ) . enumerate ( ) {
7493 trace ! ( "-------------------" ) ;
7594 trace ! ( "Frame {}" , i) ;
@@ -106,7 +125,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
106125 CreatedAlloc ( AllocId ( id) ) =>
107126 format ! ( "created allocation with id {}" , id) ,
108127 } ;
109- report_msg ( this, msg, false ) ;
128+ report_msg ( this, "tracking was triggered" , msg, None , false ) ;
110129 }
111130 } ) ;
112131 }
0 commit comments