@@ -15,9 +15,7 @@ use ty::{Ty, layout};
1515use ty:: layout:: { Size , Align , LayoutError } ;
1616use rustc_target:: spec:: abi:: Abi ;
1717
18- use super :: {
19- Pointer , Lock , AccessKind
20- } ;
18+ use super :: Pointer ;
2119
2220use backtrace:: Backtrace ;
2321
@@ -53,7 +51,7 @@ pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
5351#[ derive( Clone , Debug , RustcEncodable , RustcDecodable ) ]
5452pub struct ConstEvalErr < ' tcx > {
5553 pub span : Span ,
56- pub error : :: mir:: interpret:: EvalError < ' tcx > ,
54+ pub error : :: mir:: interpret:: EvalErrorKind < ' tcx , u64 > ,
5755 pub stacktrace : Vec < FrameInfo > ,
5856}
5957
@@ -112,7 +110,7 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
112110 message : & str ,
113111 lint_root : Option < ast:: NodeId > ,
114112 ) -> Result < DiagnosticBuilder < ' tcx > , ErrorHandled > {
115- match self . error . kind {
113+ match self . error {
116114 EvalErrorKind :: Layout ( LayoutError :: Unknown ( _) ) |
117115 EvalErrorKind :: TooGeneric => return Err ( ErrorHandled :: TooGeneric ) ,
118116 EvalErrorKind :: Layout ( LayoutError :: SizeOverflow ( _) ) |
@@ -151,50 +149,74 @@ pub fn struct_error<'a, 'gcx, 'tcx>(
151149 struct_span_err ! ( tcx. sess, tcx. span, E0080 , "{}" , msg)
152150}
153151
154- #[ derive( Debug , Clone , RustcEncodable , RustcDecodable ) ]
152+ #[ derive( Debug , Clone ) ]
155153pub struct EvalError < ' tcx > {
156154 pub kind : EvalErrorKind < ' tcx , u64 > ,
155+ pub backtrace : Option < Box < Backtrace > > ,
156+ }
157+
158+ impl < ' tcx > EvalError < ' tcx > {
159+ pub fn print_backtrace ( & mut self ) {
160+ if let Some ( ref mut backtrace) = self . backtrace {
161+ eprintln ! ( "{}" , print_backtrace( & mut * backtrace) ) ;
162+ }
163+ }
164+ }
165+
166+ fn print_backtrace ( backtrace : & mut Backtrace ) -> String {
167+ use std:: fmt:: Write ;
168+
169+ backtrace. resolve ( ) ;
170+
171+ let mut trace_text = "\n \n An error occurred in miri:\n " . to_string ( ) ;
172+ write ! ( trace_text, "backtrace frames: {}\n " , backtrace. frames( ) . len( ) ) . unwrap ( ) ;
173+ ' frames: for ( i, frame) in backtrace. frames ( ) . iter ( ) . enumerate ( ) {
174+ if frame. symbols ( ) . is_empty ( ) {
175+ write ! ( trace_text, "{}: no symbols\n " , i) . unwrap ( ) ;
176+ }
177+ for symbol in frame. symbols ( ) {
178+ write ! ( trace_text, "{}: " , i) . unwrap ( ) ;
179+ if let Some ( name) = symbol. name ( ) {
180+ write ! ( trace_text, "{}\n " , name) . unwrap ( ) ;
181+ } else {
182+ write ! ( trace_text, "<unknown>\n " ) . unwrap ( ) ;
183+ }
184+ write ! ( trace_text, "\t at " ) . unwrap ( ) ;
185+ if let Some ( file_path) = symbol. filename ( ) {
186+ write ! ( trace_text, "{}" , file_path. display( ) ) . unwrap ( ) ;
187+ } else {
188+ write ! ( trace_text, "<unknown_file>" ) . unwrap ( ) ;
189+ }
190+ if let Some ( line) = symbol. lineno ( ) {
191+ write ! ( trace_text, ":{}\n " , line) . unwrap ( ) ;
192+ } else {
193+ write ! ( trace_text, "\n " ) . unwrap ( ) ;
194+ }
195+ }
196+ }
197+ trace_text
157198}
158199
159200impl < ' tcx > From < EvalErrorKind < ' tcx , u64 > > for EvalError < ' tcx > {
160201 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 ( ) ;
202+ let backtrace = match env:: var ( "RUST_CTFE_BACKTRACE" ) {
203+ // matching RUST_BACKTRACE, we treat "0" the same as "not present".
204+ Ok ( ref val) if val != "0" => {
205+ let mut backtrace = Backtrace :: new_unresolved ( ) ;
164206
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- }
207+ if val == "immediate" {
208+ // Print it now
209+ eprintln ! ( "{}" , print_backtrace( & mut backtrace) ) ;
210+ None
211+ } else {
212+ Some ( Box :: new ( backtrace) )
191213 }
192- error ! ( "{}" , trace_text) ;
193214 } ,
194- _ => { } ,
195- }
215+ _ => None ,
216+ } ;
196217 EvalError {
197218 kind,
219+ backtrace,
198220 }
199221 }
200222}
@@ -250,29 +272,6 @@ pub enum EvalErrorKind<'tcx, O> {
250272 required : Align ,
251273 has : Align ,
252274 } ,
253- MemoryLockViolation {
254- ptr : Pointer ,
255- len : u64 ,
256- frame : usize ,
257- access : AccessKind ,
258- lock : Lock ,
259- } ,
260- MemoryAcquireConflict {
261- ptr : Pointer ,
262- len : u64 ,
263- kind : AccessKind ,
264- lock : Lock ,
265- } ,
266- InvalidMemoryLockRelease {
267- ptr : Pointer ,
268- len : u64 ,
269- frame : usize ,
270- lock : Lock ,
271- } ,
272- DeallocatedLockedMemory {
273- ptr : Pointer ,
274- lock : Lock ,
275- } ,
276275 ValidationFailure ( String ) ,
277276 CalledClosureAsFunction ,
278277 VtableForArgumentlessMethod ,
@@ -336,16 +335,8 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> {
336335 "pointer offset outside bounds of allocation" ,
337336 InvalidNullPointerUsage =>
338337 "invalid use of NULL pointer" ,
339- MemoryLockViolation { .. } =>
340- "memory access conflicts with lock" ,
341- MemoryAcquireConflict { .. } =>
342- "new memory lock conflicts with existing lock" ,
343338 ValidationFailure ( ..) =>
344339 "type validation failed" ,
345- InvalidMemoryLockRelease { .. } =>
346- "invalid attempt to release write lock" ,
347- DeallocatedLockedMemory { .. } =>
348- "tried to deallocate memory in conflict with a lock" ,
349340 ReadPointerAsBytes =>
350341 "a raw memory access tried to access part of a pointer value as raw bytes" ,
351342 ReadBytesAsPointer =>
@@ -452,7 +443,13 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> {
452443
453444impl < ' tcx > fmt:: Display for EvalError < ' tcx > {
454445 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
455- write ! ( f, "{:?}" , self . kind)
446+ write ! ( f, "{}" , self . kind)
447+ }
448+ }
449+
450+ impl < ' tcx > fmt:: Display for EvalErrorKind < ' tcx , u64 > {
451+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
452+ write ! ( f, "{:?}" , self )
456453 }
457454}
458455
@@ -465,22 +462,6 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> {
465462 if access { "memory access" } else { "pointer computed" } ,
466463 ptr. offset. bytes( ) , ptr. alloc_id, allocation_size. bytes( ) )
467464 } ,
468- MemoryLockViolation { ptr, len, frame, access, ref lock } => {
469- write ! ( f, "{:?} access by frame {} at {:?}, size {}, is in conflict with lock {:?}" ,
470- access, frame, ptr, len, lock)
471- }
472- MemoryAcquireConflict { ptr, len, kind, ref lock } => {
473- write ! ( f, "new {:?} lock at {:?}, size {}, is in conflict with lock {:?}" ,
474- kind, ptr, len, lock)
475- }
476- InvalidMemoryLockRelease { ptr, len, frame, ref lock } => {
477- write ! ( f, "frame {} tried to release memory write lock at {:?}, size {}, but \
478- cannot release lock {:?}", frame, ptr, len, lock)
479- }
480- DeallocatedLockedMemory { ptr, ref lock } => {
481- write ! ( f, "tried to deallocate memory at {:?} in conflict with lock {:?}" ,
482- ptr, lock)
483- }
484465 ValidationFailure ( ref err) => {
485466 write ! ( f, "type validation failed: {}" , err)
486467 }
0 commit comments