1
Fork 0

Rollup merge of #66926 - RalfJung:miri-stop, r=oli-obk

add reusable MachineStop variant to Miri engine error enum

Replace the Miri-tool-specific `Exit` error variant with something dynamically typed that all clients of the Miri engine can use.

r? @oli-obk
Cc https://github.com/rust-lang/rust/issues/66902
This commit is contained in:
Mazdak Farrokhzad 2019-12-02 04:09:07 +01:00 committed by GitHub
commit cd47551a0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 13 additions and 17 deletions

View file

@ -14,7 +14,7 @@ use rustc_target::spec::abi::Abi;
use syntax_pos::{Pos, Span}; use syntax_pos::{Pos, Span};
use syntax::symbol::Symbol; use syntax::symbol::Symbol;
use hir::GeneratorKind; use hir::GeneratorKind;
use std::{fmt, env}; use std::{fmt, env, any::Any};
use rustc_error_codes::*; use rustc_error_codes::*;
@ -44,14 +44,14 @@ CloneTypeFoldableImpls! {
pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>; pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>; pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
#[derive(Clone, Debug)] #[derive(Debug)]
pub struct ConstEvalErr<'tcx> { pub struct ConstEvalErr<'tcx> {
pub span: Span, pub span: Span,
pub error: crate::mir::interpret::InterpError<'tcx>, pub error: crate::mir::interpret::InterpError<'tcx>,
pub stacktrace: Vec<FrameInfo<'tcx>>, pub stacktrace: Vec<FrameInfo<'tcx>>,
} }
#[derive(Clone, Debug)] #[derive(Debug)]
pub struct FrameInfo<'tcx> { pub struct FrameInfo<'tcx> {
/// This span is in the caller. /// This span is in the caller.
pub call_site: Span, pub call_site: Span,
@ -138,6 +138,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
lint_root: Option<hir::HirId>, lint_root: Option<hir::HirId>,
) -> Result<DiagnosticBuilder<'tcx>, ErrorHandled> { ) -> Result<DiagnosticBuilder<'tcx>, ErrorHandled> {
let must_error = match self.error { let must_error = match self.error {
InterpError::MachineStop(_) => bug!("CTFE does not stop"),
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(Layout(LayoutError::Unknown(_))) |
err_inval!(TooGeneric) => err_inval!(TooGeneric) =>
return Err(ErrorHandled::TooGeneric), return Err(ErrorHandled::TooGeneric),
@ -189,7 +190,7 @@ pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'
/// Thsese should always be constructed by calling `.into()` on /// Thsese should always be constructed by calling `.into()` on
/// a `InterpError`. In `librustc_mir::interpret`, we have `throw_err_*` /// a `InterpError`. In `librustc_mir::interpret`, we have `throw_err_*`
/// macros for this. /// macros for this.
#[derive(Debug, Clone)] #[derive(Debug)]
pub struct InterpErrorInfo<'tcx> { pub struct InterpErrorInfo<'tcx> {
pub kind: InterpError<'tcx>, pub kind: InterpError<'tcx>,
backtrace: Option<Box<Backtrace>>, backtrace: Option<Box<Backtrace>>,
@ -331,7 +332,6 @@ impl<O: fmt::Debug> fmt::Debug for PanicInfo<O> {
/// Error information for when the program we executed turned out not to actually be a valid /// Error information for when the program we executed turned out not to actually be a valid
/// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp /// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp
/// where we work on generic code or execution does not have all information available. /// where we work on generic code or execution does not have all information available.
#[derive(Clone, HashStable)]
pub enum InvalidProgramInfo<'tcx> { pub enum InvalidProgramInfo<'tcx> {
/// Resolution can fail if we are in a too generic context. /// Resolution can fail if we are in a too generic context.
TooGeneric, TooGeneric,
@ -361,7 +361,6 @@ impl fmt::Debug for InvalidProgramInfo<'tcx> {
} }
/// Error information for when the program caused Undefined Behavior. /// Error information for when the program caused Undefined Behavior.
#[derive(Clone, HashStable)]
pub enum UndefinedBehaviorInfo { pub enum UndefinedBehaviorInfo {
/// Free-form case. Only for errors that are never caught! /// Free-form case. Only for errors that are never caught!
Ub(String), Ub(String),
@ -394,7 +393,6 @@ impl fmt::Debug for UndefinedBehaviorInfo {
/// ///
/// Currently, we also use this as fall-back error kind for errors that have not been /// Currently, we also use this as fall-back error kind for errors that have not been
/// categorized yet. /// categorized yet.
#[derive(Clone, HashStable)]
pub enum UnsupportedOpInfo<'tcx> { pub enum UnsupportedOpInfo<'tcx> {
/// Free-form case. Only for errors that are never caught! /// Free-form case. Only for errors that are never caught!
Unsupported(String), Unsupported(String),
@ -571,7 +569,6 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
/// Error information for when the program exhausted the resources granted to it /// Error information for when the program exhausted the resources granted to it
/// by the interpreter. /// by the interpreter.
#[derive(Clone, HashStable)]
pub enum ResourceExhaustionInfo { pub enum ResourceExhaustionInfo {
/// The stack grew too big. /// The stack grew too big.
StackFrameLimitReached, StackFrameLimitReached,
@ -592,7 +589,6 @@ impl fmt::Debug for ResourceExhaustionInfo {
} }
} }
#[derive(Clone, HashStable)]
pub enum InterpError<'tcx> { pub enum InterpError<'tcx> {
/// The program panicked. /// The program panicked.
Panic(PanicInfo<u64>), Panic(PanicInfo<u64>),
@ -601,14 +597,14 @@ pub enum InterpError<'tcx> {
/// The program did something the interpreter does not support (some of these *might* be UB /// The program did something the interpreter does not support (some of these *might* be UB
/// but the interpreter is not sure). /// but the interpreter is not sure).
Unsupported(UnsupportedOpInfo<'tcx>), Unsupported(UnsupportedOpInfo<'tcx>),
/// The program was invalid (ill-typed, not sufficiently monomorphized, ...). /// The program was invalid (ill-typed, bad MIR, not sufficiently monomorphized, ...).
InvalidProgram(InvalidProgramInfo<'tcx>), InvalidProgram(InvalidProgramInfo<'tcx>),
/// The program exhausted the interpreter's resources (stack/heap too big, /// The program exhausted the interpreter's resources (stack/heap too big,
/// execution takes too long, ..). /// execution takes too long, ...).
ResourceExhaustion(ResourceExhaustionInfo), ResourceExhaustion(ResourceExhaustionInfo),
/// Not actually an interpreter error -- used to signal that execution has exited /// Stop execution for a machine-controlled reason. This is never raised by
/// with the given status code. Used by Miri, but not by CTFE. /// the core engine itself.
Exit(i32), MachineStop(Box<dyn Any + Send>),
} }
pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>; pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
@ -634,8 +630,8 @@ impl fmt::Debug for InterpError<'_> {
write!(f, "{:?}", msg), write!(f, "{:?}", msg),
Panic(ref msg) => Panic(ref msg) =>
write!(f, "{:?}", msg), write!(f, "{:?}", msg),
Exit(code) => MachineStop(_) =>
write!(f, "exited with status code {}", code), write!(f, "machine caused execution to stop"),
} }
} }
} }

View file

@ -377,7 +377,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
InterpError::* InterpError::*
}; };
match error.kind { match error.kind {
Exit(_) => bug!("the CTFE program cannot exit"), MachineStop(_) => bug!("ConstProp does not stop"),
// Some error shouldn't come up because creating them causes // Some error shouldn't come up because creating them causes
// an allocation, which we should avoid. When that happens, // an allocation, which we should avoid. When that happens,