1
- use rustc_mir:: interpret:: InterpErrorInfo ;
2
1
use std:: cell:: RefCell ;
3
2
3
+ use rustc_span:: DUMMY_SP ;
4
+
4
5
use crate :: * ;
5
6
6
7
/// Miri specific diagnostics
@@ -14,62 +15,80 @@ pub fn report_diagnostic<'tcx, 'mir>(
14
15
ecx : & InterpCx < ' mir , ' tcx , Evaluator < ' tcx > > ,
15
16
mut e : InterpErrorInfo < ' tcx > ,
16
17
) -> 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
+ } ;
18
26
let msg = match e. kind {
19
- InterpError :: MachineStop ( ref info) => {
27
+ MachineStop ( ref info) => {
20
28
let info = info. downcast_ref :: < TerminationInfo > ( ) . expect ( "invalid MachineStop payload" ) ;
21
29
match info {
22
30
TerminationInfo :: Exit ( code) => return Some ( * code) ,
23
31
TerminationInfo :: Abort ( None ) => format ! ( "the evaluated program aborted execution" ) ,
24
32
TerminationInfo :: Abort ( Some ( msg) ) => format ! ( "the evaluated program aborted execution: {}" , msg) ,
25
33
}
26
34
}
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) ,
32
35
_ => e. to_string ( ) ,
33
36
} ;
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
+ } ;
34
48
e. print_backtrace ( ) ;
35
- report_msg ( ecx, msg, true )
49
+ report_msg ( ecx, & format ! ( "{}: {}" , title , msg) , msg , help , true )
36
50
}
37
51
38
52
/// Report an error or note (depending on the `error` argument) at the current frame's current statement.
39
53
/// Also emits a full stacktrace of the interpreter stack.
40
54
pub fn report_msg < ' tcx , ' mir > (
41
55
ecx : & InterpCx < ' mir , ' tcx , Evaluator < ' tcx > > ,
42
- msg : String ,
56
+ title : & str ,
57
+ span_msg : String ,
58
+ help : Option < & str > ,
43
59
error : bool ,
44
60
) -> 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 ( ) ) ;
51
85
} 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 ( ) ) ;
67
87
}
68
- err. emit ( ) ;
69
- } else {
70
- ecx. tcx . sess . err ( & msg) ;
71
88
}
72
89
90
+ err. emit ( ) ;
91
+
73
92
for ( i, frame) in ecx. stack ( ) . iter ( ) . enumerate ( ) {
74
93
trace ! ( "-------------------" ) ;
75
94
trace ! ( "Frame {}" , i) ;
@@ -106,7 +125,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
106
125
CreatedAlloc ( AllocId ( id) ) =>
107
126
format ! ( "created allocation with id {}" , id) ,
108
127
} ;
109
- report_msg ( this, msg, false ) ;
128
+ report_msg ( this, "tracking was triggered" , msg, None , false ) ;
110
129
}
111
130
} ) ;
112
131
}
0 commit comments