@@ -53,7 +53,7 @@ pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
53
53
#[ derive( Clone , Debug , RustcEncodable , RustcDecodable ) ]
54
54
pub struct ConstEvalErr < ' tcx > {
55
55
pub span : Span ,
56
- pub error : :: mir:: interpret:: EvalError < ' tcx > ,
56
+ pub error : :: mir:: interpret:: EvalErrorKind < ' tcx , u64 > ,
57
57
pub stacktrace : Vec < FrameInfo > ,
58
58
}
59
59
@@ -112,7 +112,7 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
112
112
message : & str ,
113
113
lint_root : Option < ast:: NodeId > ,
114
114
) -> Result < DiagnosticBuilder < ' tcx > , ErrorHandled > {
115
- match self . error . kind {
115
+ match self . error {
116
116
EvalErrorKind :: Layout ( LayoutError :: Unknown ( _) ) |
117
117
EvalErrorKind :: TooGeneric => return Err ( ErrorHandled :: TooGeneric ) ,
118
118
EvalErrorKind :: Layout ( LayoutError :: SizeOverflow ( _) ) |
@@ -151,50 +151,74 @@ pub fn struct_error<'a, 'gcx, 'tcx>(
151
151
struct_span_err ! ( tcx. sess, tcx. span, E0080 , "{}" , msg)
152
152
}
153
153
154
- #[ derive( Debug , Clone , RustcEncodable , RustcDecodable ) ]
154
+ #[ derive( Debug , Clone ) ]
155
155
pub struct EvalError < ' tcx > {
156
156
pub kind : EvalErrorKind < ' tcx , u64 > ,
157
+ pub backtrace : Option < Box < Backtrace > > ,
158
+ }
159
+
160
+ impl < ' tcx > EvalError < ' tcx > {
161
+ pub fn print_backtrace ( & mut self ) {
162
+ if let Some ( ref mut backtrace) = self . backtrace {
163
+ error ! ( "{}" , print_backtrace( & mut * backtrace) ) ;
164
+ }
165
+ }
166
+ }
167
+
168
+ fn print_backtrace ( backtrace : & mut Backtrace ) -> String {
169
+ use std:: fmt:: Write ;
170
+
171
+ backtrace. resolve ( ) ;
172
+
173
+ let mut trace_text = "\n \n An error occurred in miri:\n " . to_string ( ) ;
174
+ write ! ( trace_text, "backtrace frames: {}\n " , backtrace. frames( ) . len( ) ) . unwrap ( ) ;
175
+ ' frames: for ( i, frame) in backtrace. frames ( ) . iter ( ) . enumerate ( ) {
176
+ if frame. symbols ( ) . is_empty ( ) {
177
+ write ! ( trace_text, "{}: no symbols\n " , i) . unwrap ( ) ;
178
+ }
179
+ for symbol in frame. symbols ( ) {
180
+ write ! ( trace_text, "{}: " , i) . unwrap ( ) ;
181
+ if let Some ( name) = symbol. name ( ) {
182
+ write ! ( trace_text, "{}\n " , name) . unwrap ( ) ;
183
+ } else {
184
+ write ! ( trace_text, "<unknown>\n " ) . unwrap ( ) ;
185
+ }
186
+ write ! ( trace_text, "\t at " ) . unwrap ( ) ;
187
+ if let Some ( file_path) = symbol. filename ( ) {
188
+ write ! ( trace_text, "{}" , file_path. display( ) ) . unwrap ( ) ;
189
+ } else {
190
+ write ! ( trace_text, "<unknown_file>" ) . unwrap ( ) ;
191
+ }
192
+ if let Some ( line) = symbol. lineno ( ) {
193
+ write ! ( trace_text, ":{}\n " , line) . unwrap ( ) ;
194
+ } else {
195
+ write ! ( trace_text, "\n " ) . unwrap ( ) ;
196
+ }
197
+ }
198
+ }
199
+ trace_text
157
200
}
158
201
159
202
impl < ' tcx > From < EvalErrorKind < ' tcx , u64 > > for EvalError < ' tcx > {
160
203
fn from ( kind : EvalErrorKind < ' tcx , u64 > ) -> Self {
161
- match env:: var ( "MIRI_BACKTRACE" ) {
162
- Ok ( ref val) if !val. is_empty ( ) => {
163
- let backtrace = Backtrace :: new ( ) ;
204
+ let backtrace = match env:: var ( "RUST_CTFE_BACKTRACE" ) {
205
+ // matching RUST_BACKTRACE, we treat "0" the same as "not present".
206
+ Ok ( ref val) if val != "0" => {
207
+ let mut backtrace = Backtrace :: new_unresolved ( ) ;
164
208
165
- use std:: fmt:: Write ;
166
- let mut trace_text = "\n \n An error occurred in miri:\n " . to_string ( ) ;
167
- write ! ( trace_text, "backtrace frames: {}\n " , backtrace. frames( ) . len( ) ) . unwrap ( ) ;
168
- ' frames: for ( i, frame) in backtrace. frames ( ) . iter ( ) . enumerate ( ) {
169
- if frame. symbols ( ) . is_empty ( ) {
170
- write ! ( trace_text, "{}: no symbols\n " , i) . unwrap ( ) ;
171
- }
172
- for symbol in frame. symbols ( ) {
173
- write ! ( trace_text, "{}: " , i) . unwrap ( ) ;
174
- if let Some ( name) = symbol. name ( ) {
175
- write ! ( trace_text, "{}\n " , name) . unwrap ( ) ;
176
- } else {
177
- write ! ( trace_text, "<unknown>\n " ) . unwrap ( ) ;
178
- }
179
- write ! ( trace_text, "\t at " ) . unwrap ( ) ;
180
- if let Some ( file_path) = symbol. filename ( ) {
181
- write ! ( trace_text, "{}" , file_path. display( ) ) . unwrap ( ) ;
182
- } else {
183
- write ! ( trace_text, "<unknown_file>" ) . unwrap ( ) ;
184
- }
185
- if let Some ( line) = symbol. lineno ( ) {
186
- write ! ( trace_text, ":{}\n " , line) . unwrap ( ) ;
187
- } else {
188
- write ! ( trace_text, "\n " ) . unwrap ( ) ;
189
- }
190
- }
209
+ if val == "immediate" {
210
+ // Print it now
211
+ error ! ( "{}" , print_backtrace( & mut backtrace) ) ;
212
+ None
213
+ } else {
214
+ Some ( Box :: new ( backtrace) )
191
215
}
192
- error ! ( "{}" , trace_text) ;
193
216
} ,
194
- _ => { } ,
195
- }
217
+ _ => None ,
218
+ } ;
196
219
EvalError {
197
220
kind,
221
+ backtrace,
198
222
}
199
223
}
200
224
}
@@ -452,7 +476,13 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> {
452
476
453
477
impl < ' tcx > fmt:: Display for EvalError < ' tcx > {
454
478
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
455
- write ! ( f, "{:?}" , self . kind)
479
+ write ! ( f, "{}" , self . kind)
480
+ }
481
+ }
482
+
483
+ impl < ' tcx > fmt:: Display for EvalErrorKind < ' tcx , u64 > {
484
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
485
+ write ! ( f, "{:?}" , self )
456
486
}
457
487
}
458
488
0 commit comments