2022-07-06 10:52:20 -04:00
|
|
|
use super::{AllocId, AllocRange, ConstAlloc, Pointer, Scalar};
|
2017-08-02 16:59:01 +02:00
|
|
|
|
2020-02-15 11:56:23 +13:00
|
|
|
use crate::mir::interpret::ConstValue;
|
2023-05-16 01:53:21 +02:00
|
|
|
use crate::query::TyCtxtAt;
|
|
|
|
use crate::ty::{layout, tls, Ty, ValTree};
|
2017-07-21 13:39:06 +02:00
|
|
|
|
2020-02-16 20:32:25 -05:00
|
|
|
use rustc_data_structures::sync::Lock;
|
2023-05-17 10:30:14 +00:00
|
|
|
use rustc_errors::{
|
|
|
|
struct_span_err, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed,
|
|
|
|
IntoDiagnosticArg,
|
|
|
|
};
|
2019-09-06 03:57:44 +01:00
|
|
|
use rustc_macros::HashStable;
|
2020-02-16 20:32:25 -05:00
|
|
|
use rustc_session::CtfeBacktrace;
|
2020-08-09 15:37:32 +02:00
|
|
|
use rustc_span::def_id::DefId;
|
2023-05-17 10:30:14 +00:00
|
|
|
use rustc_target::abi::{call, Align, Size, WrappingRange};
|
|
|
|
use std::borrow::Cow;
|
2021-02-20 19:01:25 +01:00
|
|
|
use std::{any::Any, backtrace::Backtrace, fmt};
|
2019-09-06 03:57:44 +01:00
|
|
|
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
2018-08-26 15:19:34 +02:00
|
|
|
pub enum ErrorHandled {
|
2020-04-12 04:24:25 +03:00
|
|
|
/// Already reported an error for this evaluation, and the compilation is
|
|
|
|
/// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`.
|
2023-05-15 00:00:00 +00:00
|
|
|
Reported(ReportedErrorInfo),
|
2018-08-26 15:19:34 +02:00
|
|
|
/// Don't emit an error, the evaluation failed because the MIR was generic
|
2023-07-11 22:35:29 +01:00
|
|
|
/// and the args didn't fully monomorphize it.
|
2018-08-26 15:19:34 +02:00
|
|
|
TooGeneric,
|
|
|
|
}
|
|
|
|
|
2022-01-23 12:34:26 -06:00
|
|
|
impl From<ErrorGuaranteed> for ErrorHandled {
|
2023-05-15 00:00:00 +00:00
|
|
|
#[inline]
|
|
|
|
fn from(error: ErrorGuaranteed) -> ErrorHandled {
|
|
|
|
ErrorHandled::Reported(error.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
|
|
|
pub struct ReportedErrorInfo {
|
|
|
|
error: ErrorGuaranteed,
|
|
|
|
is_tainted_by_errors: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ReportedErrorInfo {
|
|
|
|
#[inline]
|
|
|
|
pub fn tainted_by_errors(error: ErrorGuaranteed) -> ReportedErrorInfo {
|
|
|
|
ReportedErrorInfo { is_tainted_by_errors: true, error }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if evaluation failed because MIR was tainted by errors.
|
|
|
|
#[inline]
|
|
|
|
pub fn is_tainted_by_errors(self) -> bool {
|
|
|
|
self.is_tainted_by_errors
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ErrorGuaranteed> for ReportedErrorInfo {
|
|
|
|
#[inline]
|
|
|
|
fn from(error: ErrorGuaranteed) -> ReportedErrorInfo {
|
|
|
|
ReportedErrorInfo { is_tainted_by_errors: false, error }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Into<ErrorGuaranteed> for ReportedErrorInfo {
|
|
|
|
#[inline]
|
|
|
|
fn into(self) -> ErrorGuaranteed {
|
|
|
|
self.error
|
2020-09-21 23:25:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-17 11:05:17 +01:00
|
|
|
TrivialTypeTraversalAndLiftImpls! {
|
2019-05-31 10:23:22 +02:00
|
|
|
ErrorHandled,
|
|
|
|
}
|
|
|
|
|
2020-09-07 17:30:38 +02:00
|
|
|
pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
|
2020-08-20 18:55:07 +02:00
|
|
|
pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
|
2022-04-12 18:14:28 +02:00
|
|
|
pub type EvalToValTreeResult<'tcx> = Result<Option<ValTree<'tcx>>, ErrorHandled>;
|
2018-06-25 18:46:02 +02:00
|
|
|
|
2022-01-27 09:44:25 +00:00
|
|
|
pub fn struct_error<'tcx>(
|
|
|
|
tcx: TyCtxtAt<'tcx>,
|
|
|
|
msg: &str,
|
2022-01-23 12:34:26 -06:00
|
|
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
2018-06-25 18:46:02 +02:00
|
|
|
struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
|
|
|
|
}
|
|
|
|
|
2021-03-06 16:02:48 +00:00
|
|
|
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
2021-02-14 00:00:00 +00:00
|
|
|
static_assert_size!(InterpErrorInfo<'_>, 8);
|
|
|
|
|
2019-06-07 15:51:29 +02:00
|
|
|
/// Packages the kind of error we got from the const code interpreter
|
2019-11-26 22:19:54 -05:00
|
|
|
/// up with a Rust-level backtrace of where the error occurred.
|
2021-04-19 15:57:08 +03:00
|
|
|
/// These should always be constructed by calling `.into()` on
|
2021-08-22 14:46:15 +02:00
|
|
|
/// an `InterpError`. In `rustc_mir::interpret`, we have `throw_err_*`
|
2019-07-30 16:08:32 +05:30
|
|
|
/// macros for this.
|
2019-12-01 11:42:19 +01:00
|
|
|
#[derive(Debug)]
|
2021-02-14 00:00:00 +00:00
|
|
|
pub struct InterpErrorInfo<'tcx>(Box<InterpErrorInfoInner<'tcx>>);
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct InterpErrorInfoInner<'tcx> {
|
|
|
|
kind: InterpError<'tcx>,
|
2023-05-17 10:30:14 +00:00
|
|
|
backtrace: InterpErrorBacktrace,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct InterpErrorBacktrace {
|
2019-06-07 13:48:38 +02:00
|
|
|
backtrace: Option<Box<Backtrace>>,
|
2018-09-18 11:01:13 +02:00
|
|
|
}
|
|
|
|
|
2023-05-17 10:30:14 +00:00
|
|
|
impl InterpErrorBacktrace {
|
|
|
|
pub fn new() -> InterpErrorBacktrace {
|
|
|
|
let capture_backtrace = tls::with_opt(|tcx| {
|
|
|
|
if let Some(tcx) = tcx {
|
|
|
|
*Lock::borrow(&tcx.sess.ctfe_backtrace)
|
|
|
|
} else {
|
|
|
|
CtfeBacktrace::Disabled
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
let backtrace = match capture_backtrace {
|
|
|
|
CtfeBacktrace::Disabled => None,
|
|
|
|
CtfeBacktrace::Capture => Some(Box::new(Backtrace::force_capture())),
|
|
|
|
CtfeBacktrace::Immediate => {
|
|
|
|
// Print it now.
|
|
|
|
let backtrace = Backtrace::force_capture();
|
|
|
|
print_backtrace(&backtrace);
|
|
|
|
None
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
InterpErrorBacktrace { backtrace }
|
2019-07-24 10:24:55 +02:00
|
|
|
}
|
|
|
|
|
2020-04-30 18:24:43 +02:00
|
|
|
pub fn print_backtrace(&self) {
|
2023-05-17 10:30:14 +00:00
|
|
|
if let Some(backtrace) = self.backtrace.as_ref() {
|
2020-04-30 18:24:43 +02:00
|
|
|
print_backtrace(backtrace);
|
2018-09-18 11:01:13 +02:00
|
|
|
}
|
|
|
|
}
|
2023-05-17 10:30:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> InterpErrorInfo<'tcx> {
|
|
|
|
pub fn from_parts(kind: InterpError<'tcx>, backtrace: InterpErrorBacktrace) -> Self {
|
|
|
|
Self(Box::new(InterpErrorInfoInner { kind, backtrace }))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn into_parts(self) -> (InterpError<'tcx>, InterpErrorBacktrace) {
|
|
|
|
let InterpErrorInfo(box InterpErrorInfoInner { kind, backtrace }) = self;
|
|
|
|
(kind, backtrace)
|
|
|
|
}
|
2021-02-14 00:00:00 +00:00
|
|
|
|
|
|
|
pub fn into_kind(self) -> InterpError<'tcx> {
|
|
|
|
let InterpErrorInfo(box InterpErrorInfoInner { kind, .. }) = self;
|
|
|
|
kind
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn kind(&self) -> &InterpError<'tcx> {
|
|
|
|
&self.0.kind
|
|
|
|
}
|
2018-09-18 11:01:13 +02:00
|
|
|
}
|
|
|
|
|
2020-04-30 18:24:43 +02:00
|
|
|
fn print_backtrace(backtrace: &Backtrace) {
|
|
|
|
eprintln!("\n\nAn error occurred in miri:\n{}", backtrace);
|
2017-08-02 16:59:01 +02:00
|
|
|
}
|
|
|
|
|
2022-01-23 12:34:26 -06:00
|
|
|
impl From<ErrorGuaranteed> for InterpErrorInfo<'_> {
|
|
|
|
fn from(err: ErrorGuaranteed) -> Self {
|
2023-05-15 00:00:00 +00:00
|
|
|
InterpError::InvalidProgram(InvalidProgramInfo::AlreadyReported(err.into())).into()
|
2020-11-04 22:23:43 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-24 10:24:55 +02:00
|
|
|
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
|
|
|
|
fn from(kind: InterpError<'tcx>) -> Self {
|
2023-05-17 10:30:14 +00:00
|
|
|
InterpErrorInfo(Box::new(InterpErrorInfoInner {
|
|
|
|
kind,
|
|
|
|
backtrace: InterpErrorBacktrace::new(),
|
|
|
|
}))
|
2017-08-02 16:59:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-17 08:58:51 +02:00
|
|
|
/// 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
|
|
|
|
/// where we work on generic code or execution does not have all information available.
|
2023-05-17 10:30:14 +00:00
|
|
|
#[derive(Debug)]
|
2019-07-26 15:28:27 +05:30
|
|
|
pub enum InvalidProgramInfo<'tcx> {
|
2019-07-29 20:17:52 +05:30
|
|
|
/// Resolution can fail if we are in a too generic context.
|
2019-07-25 16:59:38 +05:30
|
|
|
TooGeneric,
|
2020-11-04 22:23:43 +05:30
|
|
|
/// Abort in case errors are already reported.
|
2023-05-15 00:00:00 +00:00
|
|
|
AlreadyReported(ReportedErrorInfo),
|
2019-07-26 19:08:12 +05:30
|
|
|
/// An error occurred during layout computation.
|
2019-07-26 15:28:27 +05:30
|
|
|
Layout(layout::LayoutError<'tcx>),
|
2021-12-11 18:45:03 -05:00
|
|
|
/// An error occurred during FnAbi computation: the passed --target lacks FFI support
|
|
|
|
/// (which unfortunately typeck does not reject).
|
|
|
|
/// Not using `FnAbiError` as that contains a nested `LayoutError`.
|
|
|
|
FnAbiAdjustForForeignAbi(call::AdjustForForeignAbiError),
|
2021-01-21 20:10:40 +03:00
|
|
|
/// SizeOf of unsized type was requested.
|
|
|
|
SizeOfUnsizedType(Ty<'tcx>),
|
2023-07-23 21:35:54 +02:00
|
|
|
/// We are runnning into a nonsense situation due to ConstProp violating our invariants.
|
|
|
|
ConstPropNonsense,
|
2019-07-25 16:59:38 +05:30
|
|
|
}
|
|
|
|
|
2020-04-30 20:37:58 +02:00
|
|
|
/// Details of why a pointer had to be in-bounds.
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
|
2020-04-30 20:37:58 +02:00
|
|
|
pub enum CheckInAllocMsg {
|
2021-07-14 09:56:54 +02:00
|
|
|
/// We are dereferencing a pointer (i.e., creating a place).
|
|
|
|
DerefTest,
|
2021-05-07 15:11:18 +02:00
|
|
|
/// We are access memory.
|
2020-04-30 20:37:58 +02:00
|
|
|
MemoryAccessTest,
|
2021-05-07 15:11:18 +02:00
|
|
|
/// We are doing pointer arithmetic.
|
2020-04-30 20:37:58 +02:00
|
|
|
PointerArithmeticTest,
|
2022-03-10 18:30:32 -05:00
|
|
|
/// We are doing pointer offset_from.
|
|
|
|
OffsetFromTest,
|
2021-05-07 15:11:18 +02:00
|
|
|
/// None of the above -- generic/unspecific inbounds test.
|
2020-04-30 20:37:58 +02:00
|
|
|
InboundsTest,
|
|
|
|
}
|
|
|
|
|
2023-05-17 10:30:14 +00:00
|
|
|
#[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
|
|
|
|
pub enum InvalidMetaKind {
|
|
|
|
/// Size of a `[T]` is too big
|
|
|
|
SliceTooBig,
|
|
|
|
/// Size of a DST is too big
|
|
|
|
TooBig,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IntoDiagnosticArg for InvalidMetaKind {
|
|
|
|
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
|
|
|
DiagnosticArgValue::Str(Cow::Borrowed(match self {
|
|
|
|
InvalidMetaKind::SliceTooBig => "slice_too_big",
|
|
|
|
InvalidMetaKind::TooBig => "too_big",
|
|
|
|
}))
|
2020-04-30 20:37:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-14 07:46:43 -05:00
|
|
|
/// Details of an access to uninitialized bytes where it is not allowed.
|
2023-05-17 10:30:14 +00:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
2020-05-14 07:46:43 -05:00
|
|
|
pub struct UninitBytesAccess {
|
2022-07-06 10:52:20 -04:00
|
|
|
/// Range of the original memory access.
|
|
|
|
pub access: AllocRange,
|
|
|
|
/// Range of the uninit memory that was encountered. (Might not be maximal.)
|
|
|
|
pub uninit: AllocRange,
|
2020-05-14 07:46:43 -05:00
|
|
|
}
|
|
|
|
|
2022-04-07 16:22:09 -04:00
|
|
|
/// Information about a size mismatch.
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct ScalarSizeMismatch {
|
|
|
|
pub target_size: u64,
|
|
|
|
pub data_size: u64,
|
|
|
|
}
|
|
|
|
|
2023-05-17 10:30:14 +00:00
|
|
|
macro_rules! impl_into_diagnostic_arg_through_debug {
|
|
|
|
($($ty:ty),*$(,)?) => {$(
|
|
|
|
impl IntoDiagnosticArg for $ty {
|
|
|
|
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
|
|
|
DiagnosticArgValue::Str(Cow::Owned(format!("{self:?}")))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)*}
|
|
|
|
}
|
|
|
|
|
|
|
|
// These types have nice `Debug` output so we can just use them in diagnostics.
|
|
|
|
impl_into_diagnostic_arg_through_debug! {
|
|
|
|
AllocId,
|
|
|
|
Pointer,
|
|
|
|
AllocRange,
|
|
|
|
}
|
|
|
|
|
2019-09-17 08:58:51 +02:00
|
|
|
/// Error information for when the program caused Undefined Behavior.
|
2023-05-17 10:30:14 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum UndefinedBehaviorInfo<'a> {
|
|
|
|
/// Free-form case. Only for errors that are never caught! Used by miri
|
2019-07-26 19:08:12 +05:30
|
|
|
Ub(String),
|
2019-07-27 17:49:12 +05:30
|
|
|
/// Unreachable code was executed.
|
2019-07-26 15:28:27 +05:30
|
|
|
Unreachable,
|
2019-12-01 12:08:05 +01:00
|
|
|
/// A slice/array index projection went out-of-bounds.
|
2023-05-17 10:30:14 +00:00
|
|
|
BoundsCheckFailed { len: u64, index: u64 },
|
2019-12-01 12:08:05 +01:00
|
|
|
/// Something was divided by 0 (x / 0).
|
|
|
|
DivisionByZero,
|
|
|
|
/// Something was "remainded" by 0 (x % 0).
|
|
|
|
RemainderByZero,
|
2022-03-01 20:02:59 -05:00
|
|
|
/// Signed division overflowed (INT_MIN / -1).
|
|
|
|
DivisionOverflow,
|
|
|
|
/// Signed remainder overflowed (INT_MIN % -1).
|
|
|
|
RemainderOverflow,
|
2019-12-01 12:08:05 +01:00
|
|
|
/// Overflowing inbounds pointer arithmetic.
|
|
|
|
PointerArithOverflow,
|
2023-05-17 10:30:14 +00:00
|
|
|
/// Invalid metadata in a wide pointer
|
|
|
|
InvalidMeta(InvalidMetaKind),
|
2020-03-08 18:52:30 +01:00
|
|
|
/// Reading a C string that does not end within its allocation.
|
|
|
|
UnterminatedCString(Pointer),
|
|
|
|
/// Dereferencing a dangling pointer after it got freed.
|
|
|
|
PointerUseAfterFree(AllocId),
|
|
|
|
/// Used a pointer outside the bounds it is valid for.
|
2021-07-17 20:12:28 +02:00
|
|
|
/// (If `ptr_size > 0`, determines the size of the memory range that was expected to be in-bounds.)
|
2020-03-08 18:52:30 +01:00
|
|
|
PointerOutOfBounds {
|
2021-07-12 18:22:15 +02:00
|
|
|
alloc_id: AllocId,
|
2021-07-17 20:12:28 +02:00
|
|
|
alloc_size: Size,
|
|
|
|
ptr_offset: i64,
|
|
|
|
ptr_size: Size,
|
2020-03-08 18:52:30 +01:00
|
|
|
msg: CheckInAllocMsg,
|
|
|
|
},
|
2020-04-30 20:37:58 +02:00
|
|
|
/// Using an integer as a pointer in the wrong way.
|
|
|
|
DanglingIntPointer(u64, CheckInAllocMsg),
|
2020-03-08 18:52:30 +01:00
|
|
|
/// Used a pointer with bad alignment.
|
2023-05-17 10:30:14 +00:00
|
|
|
AlignmentCheckFailed { required: Align, has: Align },
|
2020-03-08 18:52:30 +01:00
|
|
|
/// Writing to read-only memory.
|
|
|
|
WriteToReadOnly(AllocId),
|
2023-05-17 10:30:14 +00:00
|
|
|
/// Trying to access the data behind a function pointer.
|
2020-03-08 18:52:30 +01:00
|
|
|
DerefFunctionPointer(AllocId),
|
2023-05-17 10:30:14 +00:00
|
|
|
/// Trying to access the data behind a vtable pointer.
|
2022-07-19 19:57:44 -04:00
|
|
|
DerefVTablePointer(AllocId),
|
2020-03-08 18:52:30 +01:00
|
|
|
/// Using a non-boolean `u8` as bool.
|
|
|
|
InvalidBool(u8),
|
|
|
|
/// Using a non-character `u32` as character.
|
|
|
|
InvalidChar(u32),
|
2020-05-30 14:21:56 +02:00
|
|
|
/// The tag of an enum does not encode an actual discriminant.
|
|
|
|
InvalidTag(Scalar),
|
2020-04-30 20:37:58 +02:00
|
|
|
/// Using a pointer-not-to-a-function as function pointer.
|
|
|
|
InvalidFunctionPointer(Pointer),
|
2022-07-17 16:02:49 -04:00
|
|
|
/// Using a pointer-not-to-a-vtable as vtable pointer.
|
2022-07-19 19:57:44 -04:00
|
|
|
InvalidVTablePointer(Pointer),
|
2020-05-06 00:07:53 +02:00
|
|
|
/// Using a string that is not valid UTF-8,
|
|
|
|
InvalidStr(std::str::Utf8Error),
|
2020-03-08 18:52:30 +01:00
|
|
|
/// Using uninitialized data where it is not allowed.
|
2021-05-16 18:53:20 +02:00
|
|
|
InvalidUninitBytes(Option<(AllocId, UninitBytesAccess)>),
|
2020-03-08 18:52:30 +01:00
|
|
|
/// Working with a local that is not currently live.
|
|
|
|
DeadLocal,
|
2020-04-26 18:44:38 +02:00
|
|
|
/// Data size is not equal to target size.
|
2022-04-07 16:22:09 -04:00
|
|
|
ScalarSizeMismatch(ScalarSizeMismatch),
|
2021-10-13 16:53:09 -04:00
|
|
|
/// A discriminant of an uninhabited enum variant is written.
|
|
|
|
UninhabitedEnumVariantWritten,
|
2023-05-17 10:30:14 +00:00
|
|
|
/// Validation error.
|
|
|
|
Validation(ValidationErrorInfo<'a>),
|
|
|
|
// FIXME(fee1-dead) these should all be actual variants of the enum instead of dynamically
|
|
|
|
// dispatched
|
|
|
|
/// A custom (free-form) error, created by `err_ub_custom!`.
|
|
|
|
Custom(crate::error::CustomSubdiagnostic<'a>),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
pub enum PointerKind {
|
|
|
|
Ref,
|
|
|
|
Box,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IntoDiagnosticArg for PointerKind {
|
|
|
|
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
|
|
|
DiagnosticArgValue::Str(
|
|
|
|
match self {
|
|
|
|
Self::Ref => "ref",
|
|
|
|
Self::Box => "box",
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
)
|
|
|
|
}
|
2019-07-26 10:51:54 +05:30
|
|
|
}
|
|
|
|
|
2023-05-17 10:30:14 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct ValidationErrorInfo<'tcx> {
|
|
|
|
pub path: Option<String>,
|
|
|
|
pub kind: ValidationErrorKind<'tcx>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum ExpectedKind {
|
|
|
|
Reference,
|
|
|
|
Box,
|
|
|
|
RawPtr,
|
|
|
|
InitScalar,
|
|
|
|
Bool,
|
|
|
|
Char,
|
|
|
|
Float,
|
|
|
|
Int,
|
|
|
|
FnPtr,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<PointerKind> for ExpectedKind {
|
|
|
|
fn from(x: PointerKind) -> ExpectedKind {
|
|
|
|
match x {
|
|
|
|
PointerKind::Box => ExpectedKind::Box,
|
|
|
|
PointerKind::Ref => ExpectedKind::Reference,
|
2019-07-27 17:49:12 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-17 10:30:14 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum ValidationErrorKind<'tcx> {
|
|
|
|
PtrToUninhabited { ptr_kind: PointerKind, ty: Ty<'tcx> },
|
|
|
|
PtrToStatic { ptr_kind: PointerKind },
|
|
|
|
PtrToMut { ptr_kind: PointerKind },
|
|
|
|
ExpectedNonPtr { value: String },
|
|
|
|
MutableRefInConst,
|
|
|
|
NullFnPtr,
|
|
|
|
NeverVal,
|
2023-07-21 22:35:57 -07:00
|
|
|
NullablePtrOutOfRange { range: WrappingRange, max_value: u128 },
|
2023-05-17 10:30:14 +00:00
|
|
|
PtrOutOfRange { range: WrappingRange, max_value: u128 },
|
|
|
|
OutOfRange { value: String, range: WrappingRange, max_value: u128 },
|
|
|
|
UnsafeCell,
|
|
|
|
UninhabitedVal { ty: Ty<'tcx> },
|
|
|
|
InvalidEnumTag { value: String },
|
|
|
|
UninitEnumTag,
|
|
|
|
UninitStr,
|
|
|
|
Uninit { expected: ExpectedKind },
|
|
|
|
UninitVal,
|
|
|
|
InvalidVTablePtr { value: String },
|
|
|
|
InvalidMetaSliceTooLarge { ptr_kind: PointerKind },
|
|
|
|
InvalidMetaTooLarge { ptr_kind: PointerKind },
|
|
|
|
UnalignedPtr { ptr_kind: PointerKind, required_bytes: u64, found_bytes: u64 },
|
|
|
|
NullPtr { ptr_kind: PointerKind },
|
|
|
|
DanglingPtrNoProvenance { ptr_kind: PointerKind, pointer: String },
|
|
|
|
DanglingPtrOutOfBounds { ptr_kind: PointerKind },
|
|
|
|
DanglingPtrUseAfterFree { ptr_kind: PointerKind },
|
|
|
|
InvalidBool { value: String },
|
|
|
|
InvalidChar { value: String },
|
|
|
|
InvalidFnPtr { value: String },
|
|
|
|
}
|
|
|
|
|
2019-09-17 08:58:51 +02:00
|
|
|
/// Error information for when the program did something that might (or might not) be correct
|
|
|
|
/// to do according to the Rust spec, but due to limitations in the interpreter, the
|
|
|
|
/// operation could not be carried out. These limitations can differ between CTFE and the
|
2020-04-30 14:53:28 +02:00
|
|
|
/// Miri engine, e.g., CTFE does not support dereferencing pointers at integral addresses.
|
2023-05-17 10:30:14 +00:00
|
|
|
#[derive(Debug)]
|
2020-03-08 18:52:30 +01:00
|
|
|
pub enum UnsupportedOpInfo {
|
2019-08-03 20:36:05 +02:00
|
|
|
/// Free-form case. Only for errors that are never caught!
|
2023-05-17 10:30:14 +00:00
|
|
|
// FIXME still use translatable diagnostics
|
2019-08-02 23:41:24 +02:00
|
|
|
Unsupported(String),
|
2020-04-30 17:05:36 +02:00
|
|
|
//
|
2020-04-16 17:32:48 +02:00
|
|
|
// The variants below are only reachable from CTFE/const prop, miri will never emit them.
|
2020-04-30 17:05:36 +02:00
|
|
|
//
|
2022-11-07 19:12:24 +01:00
|
|
|
/// Overwriting parts of a pointer; without knowing absolute addresses, the resulting state
|
|
|
|
/// cannot be represented by the CTFE interpreter.
|
|
|
|
PartialPointerOverwrite(Pointer<AllocId>),
|
|
|
|
/// Attempting to `copy` parts of a pointer to somewhere else; without knowing absolute
|
|
|
|
/// addresses, the resulting state cannot be represented by the CTFE interpreter.
|
|
|
|
PartialPointerCopy(Pointer<AllocId>),
|
2022-08-27 14:54:02 -04:00
|
|
|
/// Encountered a pointer where we needed raw bytes.
|
|
|
|
ReadPointerAsBytes,
|
2020-05-02 21:44:25 +02:00
|
|
|
/// Accessing thread local statics
|
|
|
|
ThreadLocalStatic(DefId),
|
2020-07-26 11:11:17 +02:00
|
|
|
/// Accessing an unsupported extern static.
|
|
|
|
ReadExternStatic(DefId),
|
2016-03-14 21:48:00 -06:00
|
|
|
}
|
|
|
|
|
2019-09-17 08:58:51 +02:00
|
|
|
/// Error information for when the program exhausted the resources granted to it
|
|
|
|
/// by the interpreter.
|
2023-05-17 10:30:14 +00:00
|
|
|
#[derive(Debug)]
|
2019-07-28 20:07:33 +05:30
|
|
|
pub enum ResourceExhaustionInfo {
|
2019-07-31 12:48:54 +05:30
|
|
|
/// The stack grew too big.
|
2019-07-28 20:07:33 +05:30
|
|
|
StackFrameLimitReached,
|
2023-02-07 11:39:07 +01:00
|
|
|
/// There is not enough memory (on the host) to perform an allocation.
|
2021-06-12 19:49:48 -04:00
|
|
|
MemoryExhausted,
|
2023-02-07 11:39:07 +01:00
|
|
|
/// The address space (of the target) is full.
|
|
|
|
AddressSpaceFull,
|
2019-07-28 20:07:33 +05:30
|
|
|
}
|
|
|
|
|
2020-03-22 11:41:07 +01:00
|
|
|
/// A trait for machine-specific errors (or other "machine stop" conditions).
|
2023-05-17 10:30:14 +00:00
|
|
|
pub trait MachineStopType: Any + fmt::Debug + Send {
|
|
|
|
/// The diagnostic message for this error
|
|
|
|
fn diagnostic_message(&self) -> DiagnosticMessage;
|
|
|
|
/// Add diagnostic arguments by passing name and value pairs to `adder`, which are passed to
|
|
|
|
/// fluent for formatting the translated diagnostic message.
|
|
|
|
fn add_args(
|
|
|
|
self: Box<Self>,
|
|
|
|
adder: &mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue<'static>),
|
|
|
|
);
|
|
|
|
}
|
2020-03-22 11:41:07 +01:00
|
|
|
|
|
|
|
impl dyn MachineStopType {
|
2020-03-22 20:24:22 +01:00
|
|
|
#[inline(always)]
|
2020-03-22 11:41:07 +01:00
|
|
|
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
|
2023-05-17 10:30:14 +00:00
|
|
|
let x: &dyn Any = self;
|
|
|
|
x.downcast_ref()
|
2020-03-22 11:41:07 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-29 03:32:38 +00:00
|
|
|
#[derive(Debug)]
|
2019-07-28 20:07:33 +05:30
|
|
|
pub enum InterpError<'tcx> {
|
|
|
|
/// The program caused undefined behavior.
|
2023-05-17 10:30:14 +00:00
|
|
|
UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
|
2019-07-28 20:07:33 +05:30
|
|
|
/// The program did something the interpreter does not support (some of these *might* be UB
|
|
|
|
/// but the interpreter is not sure).
|
2020-03-08 18:52:30 +01:00
|
|
|
Unsupported(UnsupportedOpInfo),
|
2019-12-01 11:42:19 +01:00
|
|
|
/// The program was invalid (ill-typed, bad MIR, not sufficiently monomorphized, ...).
|
2019-07-28 20:07:33 +05:30
|
|
|
InvalidProgram(InvalidProgramInfo<'tcx>),
|
|
|
|
/// The program exhausted the interpreter's resources (stack/heap too big,
|
2019-12-01 11:42:19 +01:00
|
|
|
/// execution takes too long, ...).
|
2019-07-28 20:07:33 +05:30
|
|
|
ResourceExhaustion(ResourceExhaustionInfo),
|
2019-12-01 11:42:19 +01:00
|
|
|
/// Stop execution for a machine-controlled reason. This is never raised by
|
|
|
|
/// the core engine itself.
|
2020-03-22 11:41:07 +01:00
|
|
|
MachineStop(Box<dyn MachineStopType>),
|
2019-07-28 20:07:33 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
|
|
|
|
|
2020-03-04 08:40:13 +01:00
|
|
|
impl InterpError<'_> {
|
2021-06-13 22:40:42 +02:00
|
|
|
/// Some errors do string formatting even if the error is never printed.
|
2021-02-20 19:01:25 +01:00
|
|
|
/// 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 {
|
2021-11-06 01:31:32 +01:00
|
|
|
matches!(
|
|
|
|
self,
|
2020-03-22 11:41:07 +01:00
|
|
|
InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
|
2023-05-17 10:30:14 +00:00
|
|
|
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Validation { .. })
|
2021-11-06 01:31:32 +01:00
|
|
|
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
|
|
|
|
)
|
2020-03-04 08:40:13 +01:00
|
|
|
}
|
|
|
|
}
|