2023-10-10 08:52:21 +00:00
|
|
|
use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar};
|
2017-08-02 16:59:01 +02:00
|
|
|
|
2023-09-11 23:09:11 +02:00
|
|
|
use crate::error;
|
2023-09-16 09:36:22 +02:00
|
|
|
use crate::mir::{ConstAlloc, ConstValue};
|
2023-09-11 23:09:11 +02:00
|
|
|
use crate::ty::{layout, tls, Ty, TyCtxt, ValTree};
|
2017-07-21 13:39:06 +02:00
|
|
|
|
2024-02-27 18:11:23 +00:00
|
|
|
use rustc_ast_ir::Mutability;
|
2020-02-16 20:32:25 -05:00
|
|
|
use rustc_data_structures::sync::Lock;
|
2024-03-05 16:53:24 +11:00
|
|
|
use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg};
|
2019-09-06 03:57:44 +01:00
|
|
|
use rustc_macros::HashStable;
|
2020-02-16 20:32:25 -05:00
|
|
|
use rustc_session::CtfeBacktrace;
|
2023-09-11 09:52:45 +02:00
|
|
|
use rustc_span::{def_id::DefId, Span, DUMMY_SP};
|
2023-07-24 11:44:58 +02:00
|
|
|
use rustc_target::abi::{call, Align, Size, VariantIdx, WrappingRange};
|
|
|
|
|
2023-05-17 10:30:14 +00:00
|
|
|
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-09-11 09:52:45 +02:00
|
|
|
Reported(ReportedErrorInfo, Span),
|
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.
|
2023-09-11 09:52:45 +02:00
|
|
|
TooGeneric(Span),
|
2018-08-26 15:19:34 +02:00
|
|
|
}
|
|
|
|
|
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 {
|
2023-09-11 09:52:45 +02:00
|
|
|
ErrorHandled::Reported(error.into(), DUMMY_SP)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ErrorHandled {
|
|
|
|
pub fn with_span(self, span: Span) -> Self {
|
|
|
|
match self {
|
|
|
|
ErrorHandled::Reported(err, _span) => ErrorHandled::Reported(err, span),
|
|
|
|
ErrorHandled::TooGeneric(_span) => ErrorHandled::TooGeneric(span),
|
|
|
|
}
|
2023-05-15 00:00:00 +00:00
|
|
|
}
|
2023-09-11 23:09:11 +02:00
|
|
|
|
|
|
|
pub fn emit_note(&self, tcx: TyCtxt<'_>) {
|
|
|
|
match self {
|
|
|
|
&ErrorHandled::Reported(err, span) => {
|
|
|
|
if !err.is_tainted_by_errors && !span.is_dummy() {
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx().emit_note(error::ErroneousConstant { span });
|
2023-09-11 23:09:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
&ErrorHandled::TooGeneric(_) => {}
|
|
|
|
}
|
2023-05-15 00:00:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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 }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-14 12:05:05 +10:00
|
|
|
TrivialTypeTraversalImpls! { ErrorHandled }
|
2019-05-31 10:23:22 +02:00
|
|
|
|
2020-09-07 17:30:38 +02:00
|
|
|
pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
|
2023-10-10 08:52:21 +00:00
|
|
|
pub type EvalStaticInitializerRawResult<'tcx> = Result<ConstAllocation<'tcx>, ErrorHandled>;
|
2020-08-20 18:55:07 +02:00
|
|
|
pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
|
2023-09-12 23:28:25 +02:00
|
|
|
/// `Ok(None)` indicates the constant was fine, but the valtree couldn't be constructed.
|
|
|
|
/// This is needed in `thir::pattern::lower_inline_const`.
|
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
|
|
|
|
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 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) {
|
2023-08-02 11:27:00 +02:00
|
|
|
eprintln!("\n\nAn error occurred in the MIR interpreter:\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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-11 09:52:45 +02:00
|
|
|
impl From<ErrorHandled> for InterpErrorInfo<'_> {
|
|
|
|
fn from(err: ErrorHandled) -> Self {
|
|
|
|
InterpError::InvalidProgram(match err {
|
|
|
|
ErrorHandled::Reported(r, _span) => InvalidProgramInfo::AlreadyReported(r),
|
|
|
|
ErrorHandled::TooGeneric(_span) => InvalidProgramInfo::TooGeneric,
|
|
|
|
})
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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),
|
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.
|
2023-09-26 16:25:05 +02:00
|
|
|
#[derive(Debug, Copy, Clone)]
|
2020-04-30 20:37:58 +02:00
|
|
|
pub enum CheckInAllocMsg {
|
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-09-26 16:25:05 +02:00
|
|
|
/// Details of which pointer is not aligned.
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
|
|
pub enum CheckAlignMsg {
|
|
|
|
/// The accessed pointer did not have proper alignment.
|
|
|
|
AccessedPtr,
|
|
|
|
/// The access ocurred with a place that was based on a misaligned pointer.
|
|
|
|
BasedOn,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
2023-05-17 10:30:14 +00:00
|
|
|
pub enum InvalidMetaKind {
|
|
|
|
/// Size of a `[T]` is too big
|
|
|
|
SliceTooBig,
|
|
|
|
/// Size of a DST is too big
|
|
|
|
TooBig,
|
|
|
|
}
|
|
|
|
|
2024-03-05 16:53:24 +11:00
|
|
|
impl IntoDiagArg for InvalidMetaKind {
|
|
|
|
fn into_diag_arg(self) -> DiagArgValue {
|
2024-02-23 14:37:48 +11:00
|
|
|
DiagArgValue::Str(Cow::Borrowed(match self {
|
2023-05-17 10:30:14 +00:00
|
|
|
InvalidMetaKind::SliceTooBig => "slice_too_big",
|
|
|
|
InvalidMetaKind::TooBig => "too_big",
|
|
|
|
}))
|
2020-04-30 20:37:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-02 16:14:36 +02:00
|
|
|
/// Details of an access to uninitialized bytes / bad pointer bytes where it is not allowed.
|
2023-05-17 10:30:14 +00:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
2023-08-02 16:14:36 +02:00
|
|
|
pub struct BadBytesAccess {
|
2022-07-06 10:52:20 -04:00
|
|
|
/// Range of the original memory access.
|
|
|
|
pub access: AllocRange,
|
2023-08-02 16:14:36 +02:00
|
|
|
/// Range of the bad memory that was encountered. (Might not be maximal.)
|
|
|
|
pub bad: 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-09-05 15:12:18 +02:00
|
|
|
/// Information about a misaligned pointer.
|
|
|
|
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
|
|
|
|
pub struct Misalignment {
|
|
|
|
pub has: Align,
|
|
|
|
pub required: Align,
|
|
|
|
}
|
|
|
|
|
2024-03-05 16:53:24 +11:00
|
|
|
macro_rules! impl_into_diag_arg_through_debug {
|
2023-05-17 10:30:14 +00:00
|
|
|
($($ty:ty),*$(,)?) => {$(
|
2024-03-05 16:53:24 +11:00
|
|
|
impl IntoDiagArg for $ty {
|
|
|
|
fn into_diag_arg(self) -> DiagArgValue {
|
2024-02-23 14:37:48 +11:00
|
|
|
DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
|
2023-05-17 10:30:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
)*}
|
|
|
|
}
|
|
|
|
|
|
|
|
// These types have nice `Debug` output so we can just use them in diagnostics.
|
2024-03-05 16:53:24 +11:00
|
|
|
impl_into_diag_arg_through_debug! {
|
2023-05-17 10:30:14 +00:00
|
|
|
AllocId,
|
2023-11-25 18:41:53 +01:00
|
|
|
Pointer<AllocId>,
|
2023-05-17 10:30:14 +00:00
|
|
|
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)]
|
2023-09-09 10:50:14 +02:00
|
|
|
pub enum UndefinedBehaviorInfo<'tcx> {
|
2023-05-17 10:30:14 +00:00
|
|
|
/// Free-form case. Only for errors that are never caught! Used by miri
|
2019-07-26 19:08:12 +05:30
|
|
|
Ub(String),
|
2023-09-09 10:50:14 +02:00
|
|
|
// FIXME(fee1-dead) these should all be actual variants of the enum instead of dynamically
|
|
|
|
// dispatched
|
|
|
|
/// A custom (free-form) fluent-translated error, created by `err_ub_custom!`.
|
|
|
|
Custom(crate::error::CustomSubdiagnostic<'tcx>),
|
|
|
|
/// Validation error.
|
|
|
|
ValidationError(ValidationErrorInfo<'tcx>),
|
|
|
|
|
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.
|
2023-11-25 18:41:53 +01:00
|
|
|
UnterminatedCString(Pointer<AllocId>),
|
2023-08-01 17:03:19 +02:00
|
|
|
/// Using a pointer after it got freed.
|
|
|
|
PointerUseAfterFree(AllocId, CheckInAllocMsg),
|
2020-03-08 18:52:30 +01:00
|
|
|
/// 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-09-26 16:25:05 +02:00
|
|
|
AlignmentCheckFailed(Misalignment, CheckAlignMsg),
|
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.
|
2023-11-25 18:41:53 +01:00
|
|
|
InvalidTag(Scalar<AllocId>),
|
2020-04-30 20:37:58 +02:00
|
|
|
/// Using a pointer-not-to-a-function as function pointer.
|
2023-11-25 18:41:53 +01:00
|
|
|
InvalidFunctionPointer(Pointer<AllocId>),
|
2022-07-17 16:02:49 -04:00
|
|
|
/// Using a pointer-not-to-a-vtable as vtable pointer.
|
2023-11-25 18:41:53 +01:00
|
|
|
InvalidVTablePointer(Pointer<AllocId>),
|
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.
|
2023-08-02 16:14:36 +02:00
|
|
|
InvalidUninitBytes(Option<(AllocId, BadBytesAccess)>),
|
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.
|
2023-07-24 11:44:58 +02:00
|
|
|
UninhabitedEnumVariantWritten(VariantIdx),
|
|
|
|
/// An uninhabited enum variant is projected.
|
|
|
|
UninhabitedEnumVariantRead(VariantIdx),
|
2024-02-10 15:26:55 +01:00
|
|
|
/// Trying to set discriminant to the niched variant, but the value does not match.
|
|
|
|
InvalidNichedEnumVariantWritten { enum_ty: Ty<'tcx> },
|
2023-09-09 10:50:14 +02:00
|
|
|
/// ABI-incompatible argument types.
|
|
|
|
AbiMismatchArgument { caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx> },
|
|
|
|
/// ABI-incompatible return types.
|
|
|
|
AbiMismatchReturn { caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx> },
|
2023-05-17 10:30:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
pub enum PointerKind {
|
2024-02-16 09:58:53 +01:00
|
|
|
Ref(Mutability),
|
2023-05-17 10:30:14 +00:00
|
|
|
Box,
|
|
|
|
}
|
|
|
|
|
2024-03-05 16:53:24 +11:00
|
|
|
impl IntoDiagArg for PointerKind {
|
|
|
|
fn into_diag_arg(self) -> DiagArgValue {
|
2024-02-23 14:37:48 +11:00
|
|
|
DiagArgValue::Str(
|
2023-05-17 10:30:14 +00:00
|
|
|
match self {
|
2024-02-16 09:58:53 +01:00
|
|
|
Self::Ref(_) => "ref",
|
2023-05-17 10:30:14 +00:00
|
|
|
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,
|
2023-08-02 16:14:36 +02:00
|
|
|
EnumTag,
|
|
|
|
Str,
|
2023-05-17 10:30:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<PointerKind> for ExpectedKind {
|
|
|
|
fn from(x: PointerKind) -> ExpectedKind {
|
|
|
|
match x {
|
|
|
|
PointerKind::Box => ExpectedKind::Box,
|
2024-02-16 09:58:53 +01:00
|
|
|
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> {
|
2023-08-02 16:14:36 +02:00
|
|
|
PointerAsInt { expected: ExpectedKind },
|
|
|
|
PartialPointer,
|
2023-05-17 10:30:14 +00:00
|
|
|
PtrToUninhabited { ptr_kind: PointerKind, ty: Ty<'tcx> },
|
|
|
|
PtrToStatic { ptr_kind: PointerKind },
|
2024-01-06 13:48:48 +01:00
|
|
|
ConstRefToMutable,
|
2024-01-06 15:06:22 +01:00
|
|
|
ConstRefToExtern,
|
2023-12-16 16:24:25 +01:00
|
|
|
MutableRefToImmutable,
|
|
|
|
UnsafeCellInImmutable,
|
2023-05-17 10:30:14 +00:00
|
|
|
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 },
|
|
|
|
UninhabitedVal { ty: Ty<'tcx> },
|
|
|
|
InvalidEnumTag { value: String },
|
2023-08-02 16:14:36 +02:00
|
|
|
UninhabitedEnumVariant,
|
2023-05-17 10:30:14 +00:00
|
|
|
Uninit { expected: ExpectedKind },
|
|
|
|
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),
|
2023-08-06 18:40:37 +02:00
|
|
|
/// Unsized local variables.
|
|
|
|
UnsizedLocal,
|
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.
|
2023-08-02 16:14:36 +02:00
|
|
|
OverwritePartialPointer(Pointer<AllocId>),
|
|
|
|
/// Attempting to read or copy parts of a pointer to somewhere else; without knowing absolute
|
2022-11-07 19:12:24 +01:00
|
|
|
/// addresses, the resulting state cannot be represented by the CTFE interpreter.
|
2023-08-02 16:14:36 +02:00
|
|
|
ReadPartialPointer(Pointer<AllocId>),
|
|
|
|
/// Encountered a pointer where we needed an integer.
|
|
|
|
ReadPointerAsInt(Option<(AllocId, BadBytesAccess)>),
|
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.
|
2024-02-10 15:41:08 +01:00
|
|
|
ExternStatic(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
|
2024-02-29 11:58:51 +11:00
|
|
|
fn diagnostic_message(&self) -> DiagMessage;
|
2023-05-17 10:30:14 +00:00
|
|
|
/// Add diagnostic arguments by passing name and value pairs to `adder`, which are passed to
|
|
|
|
/// fluent for formatting the translated diagnostic message.
|
2024-02-23 14:37:48 +11:00
|
|
|
fn add_args(self: Box<Self>, adder: &mut dyn FnMut(DiagArgName, DiagArgValue));
|
2023-05-17 10:30:14 +00:00
|
|
|
}
|
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-08-02 16:14:36 +02:00
|
|
|
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { .. })
|
2021-11-06 01:31:32 +01:00
|
|
|
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
|
|
|
|
)
|
2020-03-04 08:40:13 +01:00
|
|
|
}
|
|
|
|
}
|