@@ -14,7 +14,10 @@ use rustc_hir as hir;
14
14
use rustc_macros:: HashStable ;
15
15
use rustc_session:: CtfeBacktrace ;
16
16
use rustc_span:: { def_id:: DefId , Pos , Span } ;
17
- use std:: { any:: Any , fmt} ;
17
+ use std:: {
18
+ any:: { Any , TypeId } ,
19
+ fmt, mem,
20
+ } ;
18
21
19
22
#[ derive( Debug , Copy , Clone , PartialEq , Eq , HashStable , RustcEncodable , RustcDecodable ) ]
20
23
pub enum ErrorHandled {
@@ -451,9 +454,6 @@ impl fmt::Debug for UndefinedBehaviorInfo {
451
454
pub enum UnsupportedOpInfo {
452
455
/// Free-form case. Only for errors that are never caught!
453
456
Unsupported ( String ) ,
454
- /// When const-prop encounters a situation it does not support, it raises this error.
455
- /// This must not allocate for performance reasons (hence `str`, not `String`).
456
- ConstPropUnsupported ( & ' static str ) ,
457
457
/// Accessing an unsupported foreign static.
458
458
ReadForeignStatic ( DefId ) ,
459
459
/// Could not find MIR for a function.
@@ -472,9 +472,6 @@ impl fmt::Debug for UnsupportedOpInfo {
472
472
use UnsupportedOpInfo :: * ;
473
473
match self {
474
474
Unsupported ( ref msg) => write ! ( f, "{}" , msg) ,
475
- ConstPropUnsupported ( ref msg) => {
476
- write ! ( f, "Constant propagation encountered an unsupported situation: {}" , msg)
477
- }
478
475
ReadForeignStatic ( did) => {
479
476
write ! ( f, "tried to read from foreign (extern) static {:?}" , did)
480
477
}
@@ -516,6 +513,35 @@ impl fmt::Debug for ResourceExhaustionInfo {
516
513
}
517
514
}
518
515
516
+ /// A trait for machine-specific errors (or other "machine stop" conditions).
517
+ pub trait MachineStopType : Any + fmt:: Debug + Send { }
518
+ impl MachineStopType for String { }
519
+
520
+ // Copy-pasted from `any.rs`; there does not seem to be a way to re-use that.
521
+ impl dyn MachineStopType {
522
+ pub fn is < T : Any > ( & self ) -> bool {
523
+ // Get `TypeId` of the type this function is instantiated with.
524
+ let t = TypeId :: of :: < T > ( ) ;
525
+
526
+ // Get `TypeId` of the type in the trait object (`self`).
527
+ let concrete = self . type_id ( ) ;
528
+
529
+ // Compare both `TypeId`s on equality.
530
+ t == concrete
531
+ }
532
+
533
+ pub fn downcast_ref < T : Any > ( & self ) -> Option < & T > {
534
+ if self . is :: < T > ( ) {
535
+ // SAFETY: just checked whether we are pointing to the correct type, and we can rely on
536
+ // that check for memory safety because `Any` is implemented for all types; no other
537
+ // impls can exist as they would conflict with our impl.
538
+ unsafe { Some ( & * ( self as * const dyn MachineStopType as * const T ) ) }
539
+ } else {
540
+ None
541
+ }
542
+ }
543
+ }
544
+
519
545
pub enum InterpError < ' tcx > {
520
546
/// The program caused undefined behavior.
521
547
UndefinedBehavior ( UndefinedBehaviorInfo ) ,
@@ -529,7 +555,7 @@ pub enum InterpError<'tcx> {
529
555
ResourceExhaustion ( ResourceExhaustionInfo ) ,
530
556
/// Stop execution for a machine-controlled reason. This is never raised by
531
557
/// the core engine itself.
532
- MachineStop ( Box < dyn Any + Send > ) ,
558
+ MachineStop ( Box < dyn MachineStopType > ) ,
533
559
}
534
560
535
561
pub type InterpResult < ' tcx , T = ( ) > = Result < T , InterpErrorInfo < ' tcx > > ;
@@ -549,7 +575,7 @@ impl fmt::Debug for InterpError<'_> {
549
575
InvalidProgram ( ref msg) => write ! ( f, "{:?}" , msg) ,
550
576
UndefinedBehavior ( ref msg) => write ! ( f, "{:?}" , msg) ,
551
577
ResourceExhaustion ( ref msg) => write ! ( f, "{:?}" , msg) ,
552
- MachineStop ( _ ) => bug ! ( "unhandled MachineStop" ) ,
578
+ MachineStop ( ref msg ) => write ! ( f , "{:?}" , msg ) ,
553
579
}
554
580
}
555
581
}
@@ -560,8 +586,9 @@ impl InterpError<'_> {
560
586
/// waste of resources.
561
587
pub fn allocates ( & self ) -> bool {
562
588
match self {
563
- InterpError :: MachineStop ( _)
564
- | InterpError :: Unsupported ( UnsupportedOpInfo :: Unsupported ( _) )
589
+ // Zero-sized boxes to not allocate.
590
+ InterpError :: MachineStop ( b) => mem:: size_of_val ( & * * b) > 0 ,
591
+ InterpError :: Unsupported ( UnsupportedOpInfo :: Unsupported ( _) )
565
592
| InterpError :: UndefinedBehavior ( UndefinedBehaviorInfo :: ValidationFailure ( _) )
566
593
| InterpError :: UndefinedBehavior ( UndefinedBehaviorInfo :: Ub ( _) )
567
594
| InterpError :: UndefinedBehavior ( UndefinedBehaviorInfo :: UbExperimental ( _) ) => true ,
0 commit comments