@@ -138,10 +138,12 @@ impl<'tcx> ConstEvalErr<'tcx> {
138
138
lint_root : Option < hir:: HirId > ,
139
139
) -> Result < DiagnosticBuilder < ' tcx > , ErrorHandled > {
140
140
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 ) ,
145
147
_ => { } ,
146
148
}
147
149
trace ! ( "reporting const eval failure at {:?}" , self . span) ;
@@ -181,8 +183,8 @@ pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'
181
183
/// Packages the kind of error we got from the const code interpreter
182
184
/// up with a Rust-level backtrace of where the error occured.
183
185
/// 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.
186
188
#[ derive( Debug , Clone ) ]
187
189
pub struct InterpErrorInfo < ' tcx > {
188
190
pub kind : InterpError < ' tcx > ,
@@ -234,7 +236,7 @@ impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
234
236
}
235
237
236
238
#[ derive( Clone , RustcEncodable , RustcDecodable , HashStable ) ]
237
- pub enum PanicMessage < O > {
239
+ pub enum PanicInfo < O > {
238
240
Panic {
239
241
msg : Symbol ,
240
242
line : u32 ,
@@ -254,14 +256,14 @@ pub enum PanicMessage<O> {
254
256
}
255
257
256
258
/// 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 > > ;
258
260
259
- impl < O > PanicMessage < O > {
261
+ impl < O > PanicInfo < O > {
260
262
/// Getting a description does not require `O` to be printable, and does not
261
263
/// require allocation.
262
264
/// The caller is expected to handle `Panic` and `BoundsCheck` separately.
263
265
pub fn description ( & self ) -> & ' static str {
264
- use PanicMessage :: * ;
266
+ use PanicInfo :: * ;
265
267
match self {
266
268
Overflow ( mir:: BinOp :: Add ) =>
267
269
"attempt to add with overflow" ,
@@ -290,14 +292,14 @@ impl<O> PanicMessage<O> {
290
292
GeneratorResumedAfterPanic =>
291
293
"generator resumed after panicking" ,
292
294
Panic { .. } | BoundsCheck { .. } =>
293
- bug ! ( "Unexpected PanicMessage " ) ,
295
+ bug ! ( "Unexpected PanicInfo " ) ,
294
296
}
295
297
}
296
298
}
297
299
298
- impl < O : fmt:: Debug > fmt:: Debug for PanicMessage < O > {
300
+ impl < O : fmt:: Debug > fmt:: Debug for PanicInfo < O > {
299
301
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
300
- use PanicMessage :: * ;
302
+ use PanicInfo :: * ;
301
303
match self {
302
304
Panic { ref msg, line, col, ref file } =>
303
305
write ! ( f, "the evaluated program panicked at '{}', {}:{}:{}" , msg, file, line, col) ,
@@ -310,20 +312,64 @@ impl<O: fmt::Debug> fmt::Debug for PanicMessage<O> {
310
312
}
311
313
312
314
#[ 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
+ }
317
326
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
+ }
321
342
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 --
322
369
FunctionAbiMismatch ( Abi , Abi ) ,
323
370
FunctionArgMismatch ( Ty < ' tcx > , Ty < ' tcx > ) ,
324
371
FunctionRetMismatch ( Ty < ' tcx > , Ty < ' tcx > ) ,
325
372
FunctionArgCountMismatch ,
326
- NoMirFor ( String ) ,
327
373
UnterminatedCString ( Pointer ) ,
328
374
DanglingPointerDeref ,
329
375
DoubleFree ,
@@ -344,12 +390,17 @@ pub enum InterpError<'tcx> {
344
390
ReadUndefBytes ( Size ) ,
345
391
DeadLocal ,
346
392
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 ) ,
348
400
DerefFunctionPointer ,
349
401
ExecuteMemory ,
350
402
Intrinsic ( String ) ,
351
403
InvalidChar ( u128 ) ,
352
- StackFrameLimitReached ,
353
404
OutOfTls ,
354
405
TlsOutOfBounds ,
355
406
AbiViolation ( String ) ,
@@ -358,49 +409,26 @@ pub enum InterpError<'tcx> {
358
409
has : Align ,
359
410
} ,
360
411
ValidationFailure ( String ) ,
361
- CalledClosureAsFunction ,
362
412
VtableForArgumentlessMethod ,
363
413
ModifiedConstantMemory ,
364
414
ModifiedStatic ,
365
415
AssumptionNotHeld ,
366
- InlineAsm ,
367
416
TypeNotPrimitive ( Ty < ' tcx > ) ,
368
417
ReallocatedWrongMemoryKind ( String , String ) ,
369
418
DeallocatedWrongMemoryKind ( String , String ) ,
370
419
ReallocateNonBasePtr ,
371
420
DeallocateNonBasePtr ,
372
421
IncorrectAllocationInformation ( Size , Size , Align , Align ) ,
373
- Layout ( layout:: LayoutError < ' tcx > ) ,
374
422
HeapAllocZeroBytes ,
375
423
HeapAllocNonPowerOfTwoAlignment ( u64 ) ,
376
- Unreachable ,
377
- Panic ( PanicMessage < u64 > ) ,
378
424
ReadFromReturnPointer ,
379
425
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
- }
398
426
}
399
427
400
- impl fmt:: Debug for InterpError < ' _ > {
428
+ impl fmt:: Debug for UnsupportedOpInfo < ' tcx > {
401
429
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
402
- use InterpError :: * ;
403
- match * self {
430
+ use UnsupportedOpInfo :: * ;
431
+ match self {
404
432
PointerOutOfBounds { ptr, msg, allocation_size } => {
405
433
write ! ( f, "{} failed: pointer must be in-bounds at offset {}, \
406
434
but is outside bounds of allocation {} which has size {}",
@@ -434,8 +462,6 @@ impl fmt::Debug for InterpError<'_> {
434
462
has. bytes( ) , required. bytes( ) ) ,
435
463
TypeNotPrimitive ( ty) =>
436
464
write ! ( f, "expected primitive type, got {}" , ty) ,
437
- Layout ( ref err) =>
438
- write ! ( f, "rustc layout computation failed: {:?}" , err) ,
439
465
PathNotFound ( ref path) =>
440
466
write ! ( f, "Cannot find path {:?}" , path) ,
441
467
IncorrectAllocationInformation ( size, size2, align, align2) =>
@@ -444,8 +470,6 @@ impl fmt::Debug for InterpError<'_> {
444
470
size. bytes( ) , align. bytes( ) , size2. bytes( ) , align2. bytes( ) ) ,
445
471
InvalidDiscriminant ( val) =>
446
472
write ! ( f, "encountered invalid enum discriminant {}" , val) ,
447
- Exit ( code) =>
448
- write ! ( f, "exited with status code {}" , code) ,
449
473
InvalidMemoryAccess =>
450
474
write ! ( f, "tried to access memory through an invalid pointer" ) ,
451
475
DanglingPointerDeref =>
@@ -474,8 +498,6 @@ impl fmt::Debug for InterpError<'_> {
474
498
write ! ( f, "tried to dereference a function pointer" ) ,
475
499
ExecuteMemory =>
476
500
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" ) ,
479
501
OutOfTls =>
480
502
write ! ( f, "reached the maximum number of representable TLS keys" ) ,
481
503
TlsOutOfBounds =>
@@ -501,21 +523,10 @@ impl fmt::Debug for InterpError<'_> {
501
523
existing object") ,
502
524
HeapAllocZeroBytes =>
503
525
write ! ( f, "tried to re-, de- or allocate zero bytes on the heap" ) ,
504
- Unreachable =>
505
- write ! ( f, "entered unreachable code" ) ,
506
526
ReadFromReturnPointer =>
507
527
write ! ( f, "tried to read from the return pointer" ) ,
508
528
UnimplementedTraitSelection =>
509
529
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") ,
519
530
InvalidBoolOp ( _) =>
520
531
write ! ( f, "invalid boolean operation" ) ,
521
532
UnterminatedCString ( _) =>
@@ -531,8 +542,75 @@ impl fmt::Debug for InterpError<'_> {
531
542
AbiViolation ( ref msg) |
532
543
Intrinsic ( ref msg) =>
533
544
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) ,
534
610
Panic ( ref msg) =>
535
611
write ! ( f, "{:?}" , msg) ,
612
+ Exit ( code) =>
613
+ write ! ( f, "exited with status code {}" , code) ,
536
614
}
537
615
}
538
616
}
0 commit comments