@@ -138,10 +138,12 @@ impl<'tcx> ConstEvalErr<'tcx> {
138138 lint_root : Option < hir:: HirId > ,
139139 ) -> Result < DiagnosticBuilder < ' tcx > , ErrorHandled > {
140140 match self . error {
141- InterpError :: Layout ( LayoutError :: Unknown ( _) ) |
142- InterpError :: TooGeneric => return Err ( ErrorHandled :: TooGeneric ) ,
143- InterpError :: Layout ( LayoutError :: SizeOverflow ( _) ) |
144- InterpError :: TypeckError => return Err ( ErrorHandled :: Reported ) ,
141+ err_inval ! ( Layout ( LayoutError :: Unknown ( _) ) ) |
142+ err_inval ! ( TooGeneric ) =>
143+ return Err ( ErrorHandled :: TooGeneric ) ,
144+ err_inval ! ( Layout ( LayoutError :: SizeOverflow ( _) ) ) |
145+ err_inval ! ( TypeckError ) =>
146+ return Err ( ErrorHandled :: Reported ) ,
145147 _ => { } ,
146148 }
147149 trace ! ( "reporting const eval failure at {:?}" , self . span) ;
@@ -181,8 +183,8 @@ pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'
181183/// Packages the kind of error we got from the const code interpreter
182184/// up with a Rust-level backtrace of where the error occured.
183185/// Thsese should always be constructed by calling `.into()` on
184- /// a `InterpError`. In `librustc_mir::interpret`, we have the `err! `
185- /// macro for this.
186+ /// a `InterpError`. In `librustc_mir::interpret`, we have `throw_err_* `
187+ /// macros for this.
186188#[ derive( Debug , Clone ) ]
187189pub struct InterpErrorInfo < ' tcx > {
188190 pub kind : InterpError < ' tcx > ,
@@ -234,7 +236,7 @@ impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
234236}
235237
236238#[ derive( Clone , RustcEncodable , RustcDecodable , HashStable ) ]
237- pub enum PanicMessage < O > {
239+ pub enum PanicInfo < O > {
238240 Panic {
239241 msg : Symbol ,
240242 line : u32 ,
@@ -254,14 +256,14 @@ pub enum PanicMessage<O> {
254256}
255257
256258/// Type for MIR `Assert` terminator error messages.
257- pub type AssertMessage < ' tcx > = PanicMessage < mir:: Operand < ' tcx > > ;
259+ pub type AssertMessage < ' tcx > = PanicInfo < mir:: Operand < ' tcx > > ;
258260
259- impl < O > PanicMessage < O > {
261+ impl < O > PanicInfo < O > {
260262 /// Getting a description does not require `O` to be printable, and does not
261263 /// require allocation.
262264 /// The caller is expected to handle `Panic` and `BoundsCheck` separately.
263265 pub fn description ( & self ) -> & ' static str {
264- use PanicMessage :: * ;
266+ use PanicInfo :: * ;
265267 match self {
266268 Overflow ( mir:: BinOp :: Add ) =>
267269 "attempt to add with overflow" ,
@@ -290,14 +292,14 @@ impl<O> PanicMessage<O> {
290292 GeneratorResumedAfterPanic =>
291293 "generator resumed after panicking" ,
292294 Panic { .. } | BoundsCheck { .. } =>
293- bug ! ( "Unexpected PanicMessage " ) ,
295+ bug ! ( "Unexpected PanicInfo " ) ,
294296 }
295297 }
296298}
297299
298- impl < O : fmt:: Debug > fmt:: Debug for PanicMessage < O > {
300+ impl < O : fmt:: Debug > fmt:: Debug for PanicInfo < O > {
299301 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
300- use PanicMessage :: * ;
302+ use PanicInfo :: * ;
301303 match self {
302304 Panic { ref msg, line, col, ref file } =>
303305 write ! ( f, "the evaluated program panicked at '{}', {}:{}:{}" , msg, file, line, col) ,
@@ -310,20 +312,64 @@ impl<O: fmt::Debug> fmt::Debug for PanicMessage<O> {
310312}
311313
312314#[ derive( Clone , RustcEncodable , RustcDecodable , HashStable ) ]
313- pub enum InterpError < ' tcx > {
314- /// This variant is used by machines to signal their own errors that do not
315- /// match an existing variant.
316- MachineError ( String ) ,
315+ pub enum InvalidProgramInfo < ' tcx > {
316+ /// Resolution can fail if we are in a too generic context.
317+ TooGeneric ,
318+ /// Cannot compute this constant because it depends on another one
319+ /// which already produced an error.
320+ ReferencedConstant ,
321+ /// Abort in case type errors are reached.
322+ TypeckError ,
323+ /// An error occurred during layout computation.
324+ Layout ( layout:: LayoutError < ' tcx > ) ,
325+ }
317326
318- /// Not actually an interpreter error -- used to signal that execution has exited
319- /// with the given status code. Used by Miri, but not by CTFE.
320- Exit ( i32 ) ,
327+ impl fmt:: Debug for InvalidProgramInfo < ' tcx > {
328+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
329+ use InvalidProgramInfo :: * ;
330+ match self {
331+ TooGeneric =>
332+ write ! ( f, "encountered overly generic constant" ) ,
333+ ReferencedConstant =>
334+ write ! ( f, "referenced constant has errors" ) ,
335+ TypeckError =>
336+ write ! ( f, "encountered constants with type errors, stopping evaluation" ) ,
337+ Layout ( ref err) =>
338+ write ! ( f, "rustc layout computation failed: {:?}" , err) ,
339+ }
340+ }
341+ }
321342
343+ #[ derive( Clone , RustcEncodable , RustcDecodable , HashStable ) ]
344+ pub enum UndefinedBehaviourInfo {
345+ /// Handle cases which for which we do not have a fixed variant.
346+ Ub ( String ) ,
347+ /// Unreachable code was executed.
348+ Unreachable ,
349+ }
350+
351+ impl fmt:: Debug for UndefinedBehaviourInfo {
352+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
353+ use UndefinedBehaviourInfo :: * ;
354+ match self {
355+ Ub ( ref msg) =>
356+ write ! ( f, "{}" , msg) ,
357+ Unreachable =>
358+ write ! ( f, "entered unreachable code" ) ,
359+ }
360+ }
361+ }
362+
363+ #[ derive( Clone , RustcEncodable , RustcDecodable , HashStable ) ]
364+ pub enum UnsupportedOpInfo < ' tcx > {
365+ /// Handle cases which for which we do not have a fixed variant.
366+ Unimplemented ( String ) ,
367+
368+ // -- Everything below is not classified yet --
322369 FunctionAbiMismatch ( Abi , Abi ) ,
323370 FunctionArgMismatch ( Ty < ' tcx > , Ty < ' tcx > ) ,
324371 FunctionRetMismatch ( Ty < ' tcx > , Ty < ' tcx > ) ,
325372 FunctionArgCountMismatch ,
326- NoMirFor ( String ) ,
327373 UnterminatedCString ( Pointer ) ,
328374 DanglingPointerDeref ,
329375 DoubleFree ,
@@ -344,12 +390,17 @@ pub enum InterpError<'tcx> {
344390 ReadUndefBytes ( Size ) ,
345391 DeadLocal ,
346392 InvalidBoolOp ( mir:: BinOp ) ,
347- Unimplemented ( String ) ,
393+ InlineAsm ,
394+ UnimplementedTraitSelection ,
395+ CalledClosureAsFunction ,
396+ NoMirFor ( String ) ,
397+ /// This variant is used by machines to signal their own errors that do not
398+ /// match an existing variant.
399+ MachineError ( String ) ,
348400 DerefFunctionPointer ,
349401 ExecuteMemory ,
350402 Intrinsic ( String ) ,
351403 InvalidChar ( u128 ) ,
352- StackFrameLimitReached ,
353404 OutOfTls ,
354405 TlsOutOfBounds ,
355406 AbiViolation ( String ) ,
@@ -358,49 +409,26 @@ pub enum InterpError<'tcx> {
358409 has : Align ,
359410 } ,
360411 ValidationFailure ( String ) ,
361- CalledClosureAsFunction ,
362412 VtableForArgumentlessMethod ,
363413 ModifiedConstantMemory ,
364414 ModifiedStatic ,
365415 AssumptionNotHeld ,
366- InlineAsm ,
367416 TypeNotPrimitive ( Ty < ' tcx > ) ,
368417 ReallocatedWrongMemoryKind ( String , String ) ,
369418 DeallocatedWrongMemoryKind ( String , String ) ,
370419 ReallocateNonBasePtr ,
371420 DeallocateNonBasePtr ,
372421 IncorrectAllocationInformation ( Size , Size , Align , Align ) ,
373- Layout ( layout:: LayoutError < ' tcx > ) ,
374422 HeapAllocZeroBytes ,
375423 HeapAllocNonPowerOfTwoAlignment ( u64 ) ,
376- Unreachable ,
377- Panic ( PanicMessage < u64 > ) ,
378424 ReadFromReturnPointer ,
379425 PathNotFound ( Vec < String > ) ,
380- UnimplementedTraitSelection ,
381- /// Abort in case type errors are reached
382- TypeckError ,
383- /// Resolution can fail if we are in a too generic context
384- TooGeneric ,
385- /// Cannot compute this constant because it depends on another one
386- /// which already produced an error
387- ReferencedConstant ,
388- InfiniteLoop ,
389- }
390-
391- pub type InterpResult < ' tcx , T = ( ) > = Result < T , InterpErrorInfo < ' tcx > > ;
392-
393- impl fmt:: Display for InterpError < ' _ > {
394- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
395- // Forward `Display` to `Debug`
396- write ! ( f, "{:?}" , self )
397- }
398426}
399427
400- impl fmt:: Debug for InterpError < ' _ > {
428+ impl fmt:: Debug for UnsupportedOpInfo < ' tcx > {
401429 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
402- use InterpError :: * ;
403- match * self {
430+ use UnsupportedOpInfo :: * ;
431+ match self {
404432 PointerOutOfBounds { ptr, msg, allocation_size } => {
405433 write ! ( f, "{} failed: pointer must be in-bounds at offset {}, \
406434 but is outside bounds of allocation {} which has size {}",
@@ -434,8 +462,6 @@ impl fmt::Debug for InterpError<'_> {
434462 has. bytes( ) , required. bytes( ) ) ,
435463 TypeNotPrimitive ( ty) =>
436464 write ! ( f, "expected primitive type, got {}" , ty) ,
437- Layout ( ref err) =>
438- write ! ( f, "rustc layout computation failed: {:?}" , err) ,
439465 PathNotFound ( ref path) =>
440466 write ! ( f, "Cannot find path {:?}" , path) ,
441467 IncorrectAllocationInformation ( size, size2, align, align2) =>
@@ -444,8 +470,6 @@ impl fmt::Debug for InterpError<'_> {
444470 size. bytes( ) , align. bytes( ) , size2. bytes( ) , align2. bytes( ) ) ,
445471 InvalidDiscriminant ( val) =>
446472 write ! ( f, "encountered invalid enum discriminant {}" , val) ,
447- Exit ( code) =>
448- write ! ( f, "exited with status code {}" , code) ,
449473 InvalidMemoryAccess =>
450474 write ! ( f, "tried to access memory through an invalid pointer" ) ,
451475 DanglingPointerDeref =>
@@ -474,8 +498,6 @@ impl fmt::Debug for InterpError<'_> {
474498 write ! ( f, "tried to dereference a function pointer" ) ,
475499 ExecuteMemory =>
476500 write ! ( f, "tried to treat a memory pointer as a function pointer" ) ,
477- StackFrameLimitReached =>
478- write ! ( f, "reached the configured maximum number of stack frames" ) ,
479501 OutOfTls =>
480502 write ! ( f, "reached the maximum number of representable TLS keys" ) ,
481503 TlsOutOfBounds =>
@@ -501,21 +523,10 @@ impl fmt::Debug for InterpError<'_> {
501523 existing object") ,
502524 HeapAllocZeroBytes =>
503525 write ! ( f, "tried to re-, de- or allocate zero bytes on the heap" ) ,
504- Unreachable =>
505- write ! ( f, "entered unreachable code" ) ,
506526 ReadFromReturnPointer =>
507527 write ! ( f, "tried to read from the return pointer" ) ,
508528 UnimplementedTraitSelection =>
509529 write ! ( f, "there were unresolved type arguments during trait selection" ) ,
510- TypeckError =>
511- write ! ( f, "encountered constants with type errors, stopping evaluation" ) ,
512- TooGeneric =>
513- write ! ( f, "encountered overly generic constant" ) ,
514- ReferencedConstant =>
515- write ! ( f, "referenced constant has errors" ) ,
516- InfiniteLoop =>
517- write ! ( f, "duplicate interpreter state observed here, const evaluation will never \
518- terminate") ,
519530 InvalidBoolOp ( _) =>
520531 write ! ( f, "invalid boolean operation" ) ,
521532 UnterminatedCString ( _) =>
@@ -531,8 +542,75 @@ impl fmt::Debug for InterpError<'_> {
531542 AbiViolation ( ref msg) |
532543 Intrinsic ( ref msg) =>
533544 write ! ( f, "{}" , msg) ,
545+ }
546+ }
547+ }
548+
549+ #[ derive( Clone , RustcEncodable , RustcDecodable , HashStable ) ]
550+ pub enum ResourceExhaustionInfo {
551+ /// The stack grew too big.
552+ StackFrameLimitReached ,
553+ /// The program ran into an infinite loop.
554+ InfiniteLoop ,
555+ }
556+
557+ impl fmt:: Debug for ResourceExhaustionInfo {
558+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
559+ use ResourceExhaustionInfo :: * ;
560+ match self {
561+ StackFrameLimitReached =>
562+ write ! ( f, "reached the configured maximum number of stack frames" ) ,
563+ InfiniteLoop =>
564+ write ! ( f, "duplicate interpreter state observed here, const evaluation will never \
565+ terminate") ,
566+ }
567+ }
568+ }
569+
570+ #[ derive( Clone , RustcEncodable , RustcDecodable , HashStable ) ]
571+ pub enum InterpError < ' tcx > {
572+ /// The program panicked.
573+ Panic ( PanicInfo < u64 > ) ,
574+ /// The program caused undefined behavior.
575+ UndefinedBehaviour ( UndefinedBehaviourInfo ) ,
576+ /// The program did something the interpreter does not support (some of these *might* be UB
577+ /// but the interpreter is not sure).
578+ Unsupported ( UnsupportedOpInfo < ' tcx > ) ,
579+ /// The program was invalid (ill-typed, not sufficiently monomorphized, ...).
580+ InvalidProgram ( InvalidProgramInfo < ' tcx > ) ,
581+ /// The program exhausted the interpreter's resources (stack/heap too big,
582+ /// execution takes too long, ..).
583+ ResourceExhaustion ( ResourceExhaustionInfo ) ,
584+ /// Not actually an interpreter error -- used to signal that execution has exited
585+ /// with the given status code. Used by Miri, but not by CTFE.
586+ Exit ( i32 ) ,
587+ }
588+
589+ pub type InterpResult < ' tcx , T = ( ) > = Result < T , InterpErrorInfo < ' tcx > > ;
590+
591+ impl fmt:: Display for InterpError < ' _ > {
592+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
593+ // Forward `Display` to `Debug`
594+ write ! ( f, "{:?}" , self )
595+ }
596+ }
597+
598+ impl fmt:: Debug for InterpError < ' _ > {
599+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
600+ use InterpError :: * ;
601+ match * self {
602+ Unsupported ( ref msg) =>
603+ write ! ( f, "{:?}" , msg) ,
604+ InvalidProgram ( ref msg) =>
605+ write ! ( f, "{:?}" , msg) ,
606+ UndefinedBehaviour ( ref msg) =>
607+ write ! ( f, "{:?}" , msg) ,
608+ ResourceExhaustion ( ref msg) =>
609+ write ! ( f, "{:?}" , msg) ,
534610 Panic ( ref msg) =>
535611 write ! ( f, "{:?}" , msg) ,
612+ Exit ( code) =>
613+ write ! ( f, "exited with status code {}" , code) ,
536614 }
537615 }
538616}
0 commit comments