@@ -14,7 +14,10 @@ use rustc_hir as hir;
1414use rustc_macros:: HashStable ;
1515use rustc_session:: CtfeBacktrace ;
1616use rustc_span:: { def_id:: DefId , Pos , Span } ;
17- use std:: { any:: Any , fmt} ;
17+ use std:: {
18+ any:: { Any , TypeId } ,
19+ fmt, mem,
20+ } ;
1821
1922#[ derive( Debug , Copy , Clone , PartialEq , Eq , HashStable , RustcEncodable , RustcDecodable ) ]
2023pub enum ErrorHandled {
@@ -451,9 +454,6 @@ impl fmt::Debug for UndefinedBehaviorInfo {
451454pub enum UnsupportedOpInfo {
452455 /// Free-form case. Only for errors that are never caught!
453456 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 ) ,
457457 /// Accessing an unsupported foreign static.
458458 ReadForeignStatic ( DefId ) ,
459459 /// Could not find MIR for a function.
@@ -472,9 +472,6 @@ impl fmt::Debug for UnsupportedOpInfo {
472472 use UnsupportedOpInfo :: * ;
473473 match self {
474474 Unsupported ( ref msg) => write ! ( f, "{}" , msg) ,
475- ConstPropUnsupported ( ref msg) => {
476- write ! ( f, "Constant propagation encountered an unsupported situation: {}" , msg)
477- }
478475 ReadForeignStatic ( did) => {
479476 write ! ( f, "tried to read from foreign (extern) static {:?}" , did)
480477 }
@@ -516,6 +513,35 @@ impl fmt::Debug for ResourceExhaustionInfo {
516513 }
517514}
518515
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+
519545pub enum InterpError < ' tcx > {
520546 /// The program caused undefined behavior.
521547 UndefinedBehavior ( UndefinedBehaviorInfo ) ,
@@ -529,7 +555,7 @@ pub enum InterpError<'tcx> {
529555 ResourceExhaustion ( ResourceExhaustionInfo ) ,
530556 /// Stop execution for a machine-controlled reason. This is never raised by
531557 /// the core engine itself.
532- MachineStop ( Box < dyn Any + Send > ) ,
558+ MachineStop ( Box < dyn MachineStopType > ) ,
533559}
534560
535561pub type InterpResult < ' tcx , T = ( ) > = Result < T , InterpErrorInfo < ' tcx > > ;
@@ -549,7 +575,7 @@ impl fmt::Debug for InterpError<'_> {
549575 InvalidProgram ( ref msg) => write ! ( f, "{:?}" , msg) ,
550576 UndefinedBehavior ( ref msg) => write ! ( f, "{:?}" , msg) ,
551577 ResourceExhaustion ( ref msg) => write ! ( f, "{:?}" , msg) ,
552- MachineStop ( _ ) => bug ! ( "unhandled MachineStop" ) ,
578+ MachineStop ( ref msg ) => write ! ( f , "{:?}" , msg ) ,
553579 }
554580 }
555581}
@@ -560,8 +586,9 @@ impl InterpError<'_> {
560586 /// waste of resources.
561587 pub fn allocates ( & self ) -> bool {
562588 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 ( _) )
565592 | InterpError :: UndefinedBehavior ( UndefinedBehaviorInfo :: ValidationFailure ( _) )
566593 | InterpError :: UndefinedBehavior ( UndefinedBehaviorInfo :: Ub ( _) )
567594 | InterpError :: UndefinedBehavior ( UndefinedBehaviorInfo :: UbExperimental ( _) ) => true ,
0 commit comments