1
Fork 0

interpret errors: add map_err_kind, rename InterpError -> InterpErrorKind

This commit is contained in:
Ralf Jung 2024-10-19 08:49:13 +02:00
parent b27f33a4d9
commit eea74be5c1
17 changed files with 108 additions and 95 deletions

View file

@ -18,9 +18,9 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_target::abi::{Align, HasDataLayout, Size};
use super::{
AllocId, BadBytesAccess, CtfeProvenance, InterpError, InterpResult, Pointer, PointerArithmetic,
Provenance, ResourceExhaustionInfo, Scalar, ScalarSizeMismatch, UndefinedBehaviorInfo,
UnsupportedOpInfo, interp_ok, read_target_uint, write_target_uint,
AllocId, BadBytesAccess, CtfeProvenance, InterpErrorKind, InterpResult, Pointer,
PointerArithmetic, Provenance, ResourceExhaustionInfo, Scalar, ScalarSizeMismatch,
UndefinedBehaviorInfo, UnsupportedOpInfo, interp_ok, read_target_uint, write_target_uint,
};
use crate::ty;
@ -199,22 +199,22 @@ impl From<ScalarSizeMismatch> for AllocError {
}
impl AllocError {
pub fn to_interp_error<'tcx>(self, alloc_id: AllocId) -> InterpError<'tcx> {
pub fn to_interp_error<'tcx>(self, alloc_id: AllocId) -> InterpErrorKind<'tcx> {
use AllocError::*;
match self {
ScalarSizeMismatch(s) => {
InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ScalarSizeMismatch(s))
InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::ScalarSizeMismatch(s))
}
ReadPointerAsInt(info) => InterpError::Unsupported(
ReadPointerAsInt(info) => InterpErrorKind::Unsupported(
UnsupportedOpInfo::ReadPointerAsInt(info.map(|b| (alloc_id, b))),
),
OverwritePartialPointer(offset) => InterpError::Unsupported(
OverwritePartialPointer(offset) => InterpErrorKind::Unsupported(
UnsupportedOpInfo::OverwritePartialPointer(Pointer::new(alloc_id, offset)),
),
ReadPartialPointer(offset) => InterpError::Unsupported(
ReadPartialPointer(offset) => InterpErrorKind::Unsupported(
UnsupportedOpInfo::ReadPartialPointer(Pointer::new(alloc_id, offset)),
),
InvalidUninitBytes(info) => InterpError::UndefinedBehavior(
InvalidUninitBytes(info) => InterpErrorKind::UndefinedBehavior(
UndefinedBehaviorInfo::InvalidUninitBytes(info.map(|b| (alloc_id, b))),
),
}
@ -318,7 +318,7 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
pub fn try_uninit<'tcx>(size: Size, align: Align) -> InterpResult<'tcx, Self> {
Self::uninit_inner(size, align, || {
ty::tls::with(|tcx| tcx.dcx().delayed_bug("exhausted memory during interpretation"));
InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
InterpErrorKind::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
})
.into()
}

View file

@ -113,7 +113,7 @@ pub struct InterpErrorInfo<'tcx>(Box<InterpErrorInfoInner<'tcx>>);
#[derive(Debug)]
struct InterpErrorInfoInner<'tcx> {
kind: InterpError<'tcx>,
kind: InterpErrorKind<'tcx>,
backtrace: InterpErrorBacktrace,
}
@ -154,21 +154,21 @@ impl InterpErrorBacktrace {
}
impl<'tcx> InterpErrorInfo<'tcx> {
pub fn into_parts(self) -> (InterpError<'tcx>, InterpErrorBacktrace) {
pub fn into_parts(self) -> (InterpErrorKind<'tcx>, InterpErrorBacktrace) {
let InterpErrorInfo(box InterpErrorInfoInner { kind, backtrace }) = self;
(kind, backtrace)
}
pub fn into_kind(self) -> InterpError<'tcx> {
pub fn into_kind(self) -> InterpErrorKind<'tcx> {
self.0.kind
}
pub fn from_parts(kind: InterpError<'tcx>, backtrace: InterpErrorBacktrace) -> Self {
pub fn from_parts(kind: InterpErrorKind<'tcx>, backtrace: InterpErrorBacktrace) -> Self {
Self(Box::new(InterpErrorInfoInner { kind, backtrace }))
}
#[inline]
pub fn kind(&self) -> &InterpError<'tcx> {
pub fn kind(&self) -> &InterpErrorKind<'tcx> {
&self.0.kind
}
}
@ -179,13 +179,13 @@ fn print_backtrace(backtrace: &Backtrace) {
impl From<ErrorGuaranteed> for InterpErrorInfo<'_> {
fn from(err: ErrorGuaranteed) -> Self {
InterpError::InvalidProgram(InvalidProgramInfo::AlreadyReported(err.into())).into()
InterpErrorKind::InvalidProgram(InvalidProgramInfo::AlreadyReported(err.into())).into()
}
}
impl From<ErrorHandled> for InterpErrorInfo<'_> {
fn from(err: ErrorHandled) -> Self {
InterpError::InvalidProgram(match err {
InterpErrorKind::InvalidProgram(match err {
ErrorHandled::Reported(r, _span) => InvalidProgramInfo::AlreadyReported(r),
ErrorHandled::TooGeneric(_span) => InvalidProgramInfo::TooGeneric,
})
@ -193,8 +193,8 @@ impl From<ErrorHandled> for InterpErrorInfo<'_> {
}
}
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
fn from(kind: InterpError<'tcx>) -> Self {
impl<'tcx> From<InterpErrorKind<'tcx>> for InterpErrorInfo<'tcx> {
fn from(kind: InterpErrorKind<'tcx>) -> Self {
InterpErrorInfo(Box::new(InterpErrorInfoInner {
kind,
backtrace: InterpErrorBacktrace::new(),
@ -590,7 +590,7 @@ impl dyn MachineStopType {
}
#[derive(Debug)]
pub enum InterpError<'tcx> {
pub enum InterpErrorKind<'tcx> {
/// The program caused undefined behavior.
UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
/// The program did something the interpreter does not support (some of these *might* be UB
@ -606,25 +606,25 @@ pub enum InterpError<'tcx> {
MachineStop(Box<dyn MachineStopType>),
}
impl InterpError<'_> {
impl InterpErrorKind<'_> {
/// Some errors do string formatting even if the error is never printed.
/// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors,
/// so this method lets us detect them and `bug!` on unexpected errors.
pub fn formatted_string(&self) -> bool {
matches!(
self,
InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { .. })
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
InterpErrorKind::Unsupported(UnsupportedOpInfo::Unsupported(_))
| InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { .. })
| InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
)
}
}
// Macros for constructing / throwing `InterpError`
// Macros for constructing / throwing `InterpErrorKind`
#[macro_export]
macro_rules! err_unsup {
($($tt:tt)*) => {
$crate::mir::interpret::InterpError::Unsupported(
$crate::mir::interpret::InterpErrorKind::Unsupported(
$crate::mir::interpret::UnsupportedOpInfo::$($tt)*
)
};
@ -638,7 +638,7 @@ macro_rules! err_unsup_format {
#[macro_export]
macro_rules! err_inval {
($($tt:tt)*) => {
$crate::mir::interpret::InterpError::InvalidProgram(
$crate::mir::interpret::InterpErrorKind::InvalidProgram(
$crate::mir::interpret::InvalidProgramInfo::$($tt)*
)
};
@ -647,7 +647,7 @@ macro_rules! err_inval {
#[macro_export]
macro_rules! err_ub {
($($tt:tt)*) => {
$crate::mir::interpret::InterpError::UndefinedBehavior(
$crate::mir::interpret::InterpErrorKind::UndefinedBehavior(
$crate::mir::interpret::UndefinedBehaviorInfo::$($tt)*
)
};
@ -680,7 +680,7 @@ macro_rules! err_ub_custom {
#[macro_export]
macro_rules! err_exhaust {
($($tt:tt)*) => {
$crate::mir::interpret::InterpError::ResourceExhaustion(
$crate::mir::interpret::InterpErrorKind::ResourceExhaustion(
$crate::mir::interpret::ResourceExhaustionInfo::$($tt)*
)
};
@ -689,7 +689,7 @@ macro_rules! err_exhaust {
#[macro_export]
macro_rules! err_machine_stop {
($($tt:tt)*) => {
$crate::mir::interpret::InterpError::MachineStop(Box::new($($tt)*))
$crate::mir::interpret::InterpErrorKind::MachineStop(Box::new($($tt)*))
};
}
@ -792,9 +792,9 @@ impl<'tcx, T> ops::FromResidual for InterpResult_<'tcx, T> {
}
// Allow `yeet`ing `InterpError` in functions returning `InterpResult_`.
impl<'tcx, T> ops::FromResidual<ops::Yeet<InterpError<'tcx>>> for InterpResult_<'tcx, T> {
impl<'tcx, T> ops::FromResidual<ops::Yeet<InterpErrorKind<'tcx>>> for InterpResult_<'tcx, T> {
#[inline]
fn from_residual(ops::Yeet(e): ops::Yeet<InterpError<'tcx>>) -> Self {
fn from_residual(ops::Yeet(e): ops::Yeet<InterpErrorKind<'tcx>>) -> Self {
Self::new(Err(e.into()))
}
}
@ -856,7 +856,7 @@ impl<'tcx, T> InterpResult_<'tcx, T> {
}
#[inline]
pub fn map_err(
pub fn map_err_info(
self,
f: impl FnOnce(InterpErrorInfo<'tcx>) -> InterpErrorInfo<'tcx>,
) -> InterpResult<'tcx, T> {
@ -864,8 +864,19 @@ impl<'tcx, T> InterpResult_<'tcx, T> {
}
#[inline]
pub fn inspect_err(self, f: impl FnOnce(&InterpErrorInfo<'tcx>)) -> InterpResult<'tcx, T> {
InterpResult_::new(self.disarm().inspect_err(f))
pub fn map_err_kind(
self,
f: impl FnOnce(InterpErrorKind<'tcx>) -> InterpErrorKind<'tcx>,
) -> InterpResult<'tcx, T> {
InterpResult_::new(self.disarm().map_err(|mut e| {
e.0.kind = f(e.0.kind);
e
}))
}
#[inline]
pub fn inspect_err_kind(self, f: impl FnOnce(&InterpErrorKind<'tcx>)) -> InterpResult<'tcx, T> {
InterpResult_::new(self.disarm().inspect_err(|e| f(&e.0.kind)))
}
#[inline]

View file

@ -36,7 +36,7 @@ pub use self::allocation::{
pub use self::error::{
BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled, EvalStaticInitializerRawResult,
EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, ExpectedKind,
InterpError, InterpErrorInfo, InterpResult, InvalidMetaKind, InvalidProgramInfo,
InterpErrorInfo, InterpErrorKind, InterpResult, InvalidMetaKind, InvalidProgramInfo,
MachineStopType, Misalignment, PointerKind, ReportedErrorInfo, ResourceExhaustionInfo,
ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
ValidationErrorKind, interp_ok,