summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/mir/interpret
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
commitd1b2d29528b7794b41e66fc2136e395a02f8529b (patch)
treea4a17504b260206dec3cf55b2dca82929a348ac2 /compiler/rustc_middle/src/mir/interpret
parentReleasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz
rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_middle/src/mir/interpret')
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs71
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs6
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs14
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs63
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs22
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs29
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs29
7 files changed, 126 insertions, 108 deletions
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index b8030d9db..c787481bf 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -18,9 +18,9 @@ use rustc_span::DUMMY_SP;
use rustc_target::abi::{Align, HasDataLayout, Size};
use super::{
- read_target_uint, write_target_uint, AllocId, InterpError, InterpResult, Pointer, Provenance,
- ResourceExhaustionInfo, Scalar, ScalarSizeMismatch, UndefinedBehaviorInfo, UninitBytesAccess,
- UnsupportedOpInfo,
+ read_target_uint, write_target_uint, AllocId, BadBytesAccess, InterpError, InterpResult,
+ Pointer, PointerArithmetic, Provenance, ResourceExhaustionInfo, Scalar, ScalarSizeMismatch,
+ UndefinedBehaviorInfo, UnsupportedOpInfo,
};
use crate::ty;
use init_mask::*;
@@ -173,13 +173,13 @@ pub enum AllocError {
/// A scalar had the wrong size.
ScalarSizeMismatch(ScalarSizeMismatch),
/// Encountered a pointer where we needed raw bytes.
- ReadPointerAsBytes,
+ ReadPointerAsInt(Option<BadBytesAccess>),
/// Partially overwriting a pointer.
- PartialPointerOverwrite(Size),
+ OverwritePartialPointer(Size),
/// Partially copying a pointer.
- PartialPointerCopy(Size),
+ ReadPartialPointer(Size),
/// Using uninitialized data where it is not allowed.
- InvalidUninitBytes(Option<UninitBytesAccess>),
+ InvalidUninitBytes(Option<BadBytesAccess>),
}
pub type AllocResult<T = ()> = Result<T, AllocError>;
@@ -196,12 +196,14 @@ impl AllocError {
ScalarSizeMismatch(s) => {
InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ScalarSizeMismatch(s))
}
- ReadPointerAsBytes => InterpError::Unsupported(UnsupportedOpInfo::ReadPointerAsBytes),
- PartialPointerOverwrite(offset) => InterpError::Unsupported(
- UnsupportedOpInfo::PartialPointerOverwrite(Pointer::new(alloc_id, offset)),
+ ReadPointerAsInt(info) => InterpError::Unsupported(
+ UnsupportedOpInfo::ReadPointerAsInt(info.map(|b| (alloc_id, b))),
),
- PartialPointerCopy(offset) => InterpError::Unsupported(
- UnsupportedOpInfo::PartialPointerCopy(Pointer::new(alloc_id, offset)),
+ OverwritePartialPointer(offset) => InterpError::Unsupported(
+ UnsupportedOpInfo::OverwritePartialPointer(Pointer::new(alloc_id, offset)),
+ ),
+ ReadPartialPointer(offset) => InterpError::Unsupported(
+ UnsupportedOpInfo::ReadPartialPointer(Pointer::new(alloc_id, offset)),
),
InvalidUninitBytes(info) => InterpError::UndefinedBehavior(
UndefinedBehaviorInfo::InvalidUninitBytes(info.map(|b| (alloc_id, b))),
@@ -327,6 +329,9 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
/// Try to create an Allocation of `size` bytes, panics if there is not enough memory
/// available to the compiler to do so.
+ ///
+ /// Example use case: To obtain an Allocation filled with specific data,
+ /// first call this function and then call write_scalar to fill in the right data.
pub fn uninit(size: Size, align: Align) -> Self {
match Self::uninit_inner(size, align, || {
panic!("Allocation::uninit called with panic_on_fail had allocation failure");
@@ -433,14 +438,26 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
range: AllocRange,
) -> AllocResult<&[u8]> {
self.init_mask.is_range_initialized(range).map_err(|uninit_range| {
- AllocError::InvalidUninitBytes(Some(UninitBytesAccess {
+ AllocError::InvalidUninitBytes(Some(BadBytesAccess {
access: range,
- uninit: uninit_range,
+ bad: uninit_range,
}))
})?;
if !Prov::OFFSET_IS_ADDR {
if !self.provenance.range_empty(range, cx) {
- return Err(AllocError::ReadPointerAsBytes);
+ // Find the provenance.
+ let (offset, _prov) = self
+ .provenance
+ .range_get_ptrs(range, cx)
+ .first()
+ .copied()
+ .expect("there must be provenance somewhere here");
+ let start = offset.max(range.start); // the pointer might begin before `range`!
+ let end = (offset + cx.pointer_size()).min(range.end()); // the pointer might end after `range`!
+ return Err(AllocError::ReadPointerAsInt(Some(BadBytesAccess {
+ access: range,
+ bad: AllocRange::from(start..end),
+ })));
}
}
Ok(self.get_bytes_unchecked(range))
@@ -536,23 +553,25 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
// Now use this provenance.
let ptr = Pointer::new(prov, Size::from_bytes(bits));
return Ok(Scalar::from_maybe_pointer(ptr, cx));
+ } else {
+ // Without OFFSET_IS_ADDR, the only remaining case we can handle is total absence of
+ // provenance.
+ if self.provenance.range_empty(range, cx) {
+ return Ok(Scalar::from_uint(bits, range.size));
+ }
+ // Else we have mixed provenance, that doesn't work.
+ return Err(AllocError::ReadPartialPointer(range.start));
}
} else {
// We are *not* reading a pointer.
- // If we can just ignore provenance, do exactly that.
- if Prov::OFFSET_IS_ADDR {
+ // If we can just ignore provenance or there is none, that's easy.
+ if Prov::OFFSET_IS_ADDR || self.provenance.range_empty(range, cx) {
// We just strip provenance.
return Ok(Scalar::from_uint(bits, range.size));
}
+ // There is some provenance and we don't have OFFSET_IS_ADDR. This doesn't work.
+ return Err(AllocError::ReadPointerAsInt(None));
}
-
- // Fallback path for when we cannot treat provenance bytewise or ignore it.
- assert!(!Prov::OFFSET_IS_ADDR);
- if !self.provenance.range_empty(range, cx) {
- return Err(AllocError::ReadPointerAsBytes);
- }
- // There is no provenance, we can just return the bits.
- Ok(Scalar::from_uint(bits, range.size))
}
/// Writes a *non-ZST* scalar.
@@ -571,7 +590,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
assert!(self.mutability == Mutability::Mut);
// `to_bits_or_ptr_internal` is the right method because we just want to store this data
- // as-is into memory.
+ // as-is into memory. This also double-checks that `val.size()` matches `range.size`.
let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size)? {
Right(ptr) => {
let (provenance, offset) = ptr.into_parts();
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
index d4dd56a42..2c6bb908f 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
@@ -542,11 +542,7 @@ impl InitMaskMaterialized {
debug_assert_eq!(
result,
find_bit_slow(self, start, end, is_init),
- "optimized implementation of find_bit is wrong for start={:?} end={:?} is_init={} init_mask={:#?}",
- start,
- end,
- is_init,
- self
+ "optimized implementation of find_bit is wrong for start={start:?} end={end:?} is_init={is_init} init_mask={self:#?}"
);
result
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
index 318f93e12..0243fc451 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
@@ -66,7 +66,11 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
/// Returns all ptr-sized provenance in the given range.
/// If the range has length 0, returns provenance that crosses the edge between `start-1` and
/// `start`.
- fn range_get_ptrs(&self, range: AllocRange, cx: &impl HasDataLayout) -> &[(Size, Prov)] {
+ pub(super) fn range_get_ptrs(
+ &self,
+ range: AllocRange,
+ cx: &impl HasDataLayout,
+ ) -> &[(Size, Prov)] {
// We have to go back `pointer_size - 1` bytes, as that one would still overlap with
// the beginning of this range.
let adjusted_start = Size::from_bytes(
@@ -158,7 +162,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
if first < start {
if !Prov::OFFSET_IS_ADDR {
// We can't split up the provenance into less than a pointer.
- return Err(AllocError::PartialPointerOverwrite(first));
+ return Err(AllocError::OverwritePartialPointer(first));
}
// Insert the remaining part in the bytewise provenance.
let prov = self.ptrs[&first];
@@ -171,7 +175,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
let begin_of_last = last - cx.data_layout().pointer_size;
if !Prov::OFFSET_IS_ADDR {
// We can't split up the provenance into less than a pointer.
- return Err(AllocError::PartialPointerOverwrite(begin_of_last));
+ return Err(AllocError::OverwritePartialPointer(begin_of_last));
}
// Insert the remaining part in the bytewise provenance.
let prov = self.ptrs[&begin_of_last];
@@ -246,10 +250,10 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
if !Prov::OFFSET_IS_ADDR {
// There can't be any bytewise provenance, and we cannot split up the begin/end overlap.
if let Some(entry) = begin_overlap {
- return Err(AllocError::PartialPointerCopy(entry.0));
+ return Err(AllocError::ReadPartialPointer(entry.0));
}
if let Some(entry) = end_overlap {
- return Err(AllocError::PartialPointerCopy(entry.0));
+ return Err(AllocError::ReadPartialPointer(entry.0));
}
debug_assert!(self.bytes.is_none());
} else {
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 2435bc59e..e6ef5a41e 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -12,7 +12,8 @@ use rustc_errors::{
use rustc_macros::HashStable;
use rustc_session::CtfeBacktrace;
use rustc_span::def_id::DefId;
-use rustc_target::abi::{call, Align, Size, WrappingRange};
+use rustc_target::abi::{call, Align, Size, VariantIdx, WrappingRange};
+
use std::borrow::Cow;
use std::{any::Any, backtrace::Backtrace, fmt};
@@ -22,7 +23,7 @@ pub enum ErrorHandled {
/// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`.
Reported(ReportedErrorInfo),
/// Don't emit an error, the evaluation failed because the MIR was generic
- /// and the substs didn't fully monomorphize it.
+ /// and the args didn't fully monomorphize it.
TooGeneric,
}
@@ -66,9 +67,7 @@ impl Into<ErrorGuaranteed> for ReportedErrorInfo {
}
}
-TrivialTypeTraversalAndLiftImpls! {
- ErrorHandled,
-}
+TrivialTypeTraversalAndLiftImpls! { ErrorHandled }
pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
@@ -135,10 +134,6 @@ impl InterpErrorBacktrace {
}
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)
@@ -156,7 +151,7 @@ impl<'tcx> InterpErrorInfo<'tcx> {
}
fn print_backtrace(backtrace: &Backtrace) {
- eprintln!("\n\nAn error occurred in miri:\n{}", backtrace);
+ eprintln!("\n\nAn error occurred in the MIR interpreter:\n{backtrace}");
}
impl From<ErrorGuaranteed> for InterpErrorInfo<'_> {
@@ -189,11 +184,8 @@ pub enum InvalidProgramInfo<'tcx> {
/// (which unfortunately typeck does not reject).
/// Not using `FnAbiError` as that contains a nested `LayoutError`.
FnAbiAdjustForForeignAbi(call::AdjustForForeignAbiError),
- /// SizeOf of unsized type was requested.
- SizeOfUnsizedType(Ty<'tcx>),
- /// An unsized local was accessed without having been initialized.
- /// This is not meaningful as we can't even have backing memory for such locals.
- UninitUnsizedLocal,
+ /// We are runnning into a nonsense situation due to ConstProp violating our invariants.
+ ConstPropNonsense,
}
/// Details of why a pointer had to be in-bounds.
@@ -228,13 +220,13 @@ impl IntoDiagnosticArg for InvalidMetaKind {
}
}
-/// Details of an access to uninitialized bytes where it is not allowed.
+/// Details of an access to uninitialized bytes / bad pointer bytes where it is not allowed.
#[derive(Debug, Clone, Copy)]
-pub struct UninitBytesAccess {
+pub struct BadBytesAccess {
/// Range of the original memory access.
pub access: AllocRange,
- /// Range of the uninit memory that was encountered. (Might not be maximal.)
- pub uninit: AllocRange,
+ /// Range of the bad memory that was encountered. (Might not be maximal.)
+ pub bad: AllocRange,
}
/// Information about a size mismatch.
@@ -284,8 +276,8 @@ pub enum UndefinedBehaviorInfo<'a> {
InvalidMeta(InvalidMetaKind),
/// Reading a C string that does not end within its allocation.
UnterminatedCString(Pointer),
- /// Dereferencing a dangling pointer after it got freed.
- PointerUseAfterFree(AllocId),
+ /// Using a pointer after it got freed.
+ PointerUseAfterFree(AllocId, CheckInAllocMsg),
/// Used a pointer outside the bounds it is valid for.
/// (If `ptr_size > 0`, determines the size of the memory range that was expected to be in-bounds.)
PointerOutOfBounds {
@@ -318,15 +310,17 @@ pub enum UndefinedBehaviorInfo<'a> {
/// Using a string that is not valid UTF-8,
InvalidStr(std::str::Utf8Error),
/// Using uninitialized data where it is not allowed.
- InvalidUninitBytes(Option<(AllocId, UninitBytesAccess)>),
+ InvalidUninitBytes(Option<(AllocId, BadBytesAccess)>),
/// Working with a local that is not currently live.
DeadLocal,
/// Data size is not equal to target size.
ScalarSizeMismatch(ScalarSizeMismatch),
/// A discriminant of an uninhabited enum variant is written.
- UninhabitedEnumVariantWritten,
+ UninhabitedEnumVariantWritten(VariantIdx),
+ /// An uninhabited enum variant is projected.
+ UninhabitedEnumVariantRead(VariantIdx),
/// Validation error.
- Validation(ValidationErrorInfo<'a>),
+ ValidationError(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!`.
@@ -368,6 +362,8 @@ pub enum ExpectedKind {
Float,
Int,
FnPtr,
+ EnumTag,
+ Str,
}
impl From<PointerKind> for ExpectedKind {
@@ -381,10 +377,11 @@ impl From<PointerKind> for ExpectedKind {
#[derive(Debug)]
pub enum ValidationErrorKind<'tcx> {
+ PointerAsInt { expected: ExpectedKind },
+ PartialPointer,
PtrToUninhabited { ptr_kind: PointerKind, ty: Ty<'tcx> },
PtrToStatic { ptr_kind: PointerKind },
PtrToMut { ptr_kind: PointerKind },
- ExpectedNonPtr { value: String },
MutableRefInConst,
NullFnPtr,
NeverVal,
@@ -394,10 +391,8 @@ pub enum ValidationErrorKind<'tcx> {
UnsafeCell,
UninhabitedVal { ty: Ty<'tcx> },
InvalidEnumTag { value: String },
- UninitEnumTag,
- UninitStr,
+ UninhabitedEnumVariant,
Uninit { expected: ExpectedKind },
- UninitVal,
InvalidVTablePtr { value: String },
InvalidMetaSliceTooLarge { ptr_kind: PointerKind },
InvalidMetaTooLarge { ptr_kind: PointerKind },
@@ -425,12 +420,12 @@ pub enum UnsupportedOpInfo {
//
/// 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
+ OverwritePartialPointer(Pointer<AllocId>),
+ /// Attempting to read or 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>),
- /// Encountered a pointer where we needed raw bytes.
- ReadPointerAsBytes,
+ ReadPartialPointer(Pointer<AllocId>),
+ /// Encountered a pointer where we needed an integer.
+ ReadPointerAsInt(Option<(AllocId, BadBytesAccess)>),
/// Accessing thread local statics
ThreadLocalStatic(DefId),
/// Accessing an unsupported extern static.
@@ -496,7 +491,7 @@ impl InterpError<'_> {
matches!(
self,
InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
- | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Validation { .. })
+ | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { .. })
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
)
}
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 2d2cfee1b..3543158bf 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -138,15 +138,15 @@ use rustc_target::abi::{AddressSpace, Endian, HasDataLayout};
use crate::mir;
use crate::ty::codec::{TyDecoder, TyEncoder};
-use crate::ty::subst::GenericArgKind;
+use crate::ty::GenericArgKind;
use crate::ty::{self, Instance, Ty, TyCtxt};
pub use self::error::{
- struct_error, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult,
- EvalToValTreeResult, ExpectedKind, InterpError, InterpErrorInfo, InterpResult, InvalidMetaKind,
- InvalidProgramInfo, MachineStopType, PointerKind, ReportedErrorInfo, ResourceExhaustionInfo,
- ScalarSizeMismatch, UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
- ValidationErrorInfo, ValidationErrorKind,
+ struct_error, BadBytesAccess, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult,
+ EvalToConstValueResult, EvalToValTreeResult, ExpectedKind, InterpError, InterpErrorInfo,
+ InterpResult, InvalidMetaKind, InvalidProgramInfo, MachineStopType, PointerKind,
+ ReportedErrorInfo, ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo,
+ UnsupportedOpInfo, ValidationErrorInfo, ValidationErrorKind,
};
pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar};
@@ -176,7 +176,7 @@ impl<'tcx> GlobalId<'tcx> {
pub fn display(self, tcx: TyCtxt<'tcx>) -> String {
let instance_name = with_no_trimmed_paths!(tcx.def_path_str(self.instance.def.def_id()));
if let Some(promoted) = self.promoted {
- format!("{}::{:?}", instance_name, promoted)
+ format!("{instance_name}::{promoted:?}")
} else {
instance_name
}
@@ -274,7 +274,7 @@ pub struct AllocDecodingState {
// For each `AllocId`, we keep track of which decoding state it's currently in.
decoding_state: Vec<Lock<State>>,
// The offsets of each allocation in the data stream.
- data_offsets: Vec<u32>,
+ data_offsets: Vec<u64>,
}
impl AllocDecodingState {
@@ -289,7 +289,7 @@ impl AllocDecodingState {
AllocDecodingSession { state: self, session_id }
}
- pub fn new(data_offsets: Vec<u32>) -> Self {
+ pub fn new(data_offsets: Vec<u64>) -> Self {
let decoding_state =
std::iter::repeat_with(|| Lock::new(State::Empty)).take(data_offsets.len()).collect();
@@ -559,7 +559,7 @@ impl<'tcx> TyCtxt<'tcx> {
// However, formatting code relies on function identity (see #58320), so we only do
// this for generic functions. Lifetime parameters are ignored.
let is_generic = instance
- .substs
+ .args
.into_iter()
.any(|kind| !matches!(kind.unpack(), GenericArgKind::Lifetime(_)));
if is_generic {
@@ -609,7 +609,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Panics in case the `AllocId` is dangling. Since that is impossible for `AllocId`s in
/// constants (as all constants must pass interning and validation that check for dangling
/// ids), this function is frequently used throughout rustc, but should not be used within
- /// the miri engine.
+ /// the interpreter.
pub fn global_alloc(self, id: AllocId) -> GlobalAlloc<'tcx> {
match self.try_get_global_alloc(id) {
Some(alloc) => alloc,
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 9c97431f3..fc659ce18 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -2,8 +2,8 @@ use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId}
use crate::mir;
use crate::query::{TyCtxtAt, TyCtxtEnsure};
-use crate::ty::subst::InternalSubsts;
use crate::ty::visit::TypeVisitableExt;
+use crate::ty::GenericArgs;
use crate::ty::{self, TyCtxt};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
@@ -20,8 +20,8 @@ impl<'tcx> TyCtxt<'tcx> {
// to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
// into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
// encountered.
- let substs = InternalSubsts::identity_for_item(self, def_id);
- let instance = ty::Instance::new(def_id, substs);
+ let args = GenericArgs::identity_for_item(self, def_id);
+ let instance = ty::Instance::new(def_id, args);
let cid = GlobalId { instance, promoted: None };
let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
self.const_eval_global_id(param_env, cid, None)
@@ -48,14 +48,14 @@ impl<'tcx> TyCtxt<'tcx> {
//
// When trying to evaluate constants containing inference variables,
// use `Infcx::const_eval_resolve` instead.
- if ct.substs.has_non_region_infer() {
+ if ct.args.has_non_region_infer() {
bug!("did not expect inference variables here");
}
match ty::Instance::resolve(
self, param_env,
// FIXME: maybe have a separate version for resolving mir::UnevaluatedConst?
- ct.def, ct.substs,
+ ct.def, ct.args,
) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: ct.promoted };
@@ -79,11 +79,11 @@ impl<'tcx> TyCtxt<'tcx> {
//
// When trying to evaluate constants containing inference variables,
// use `Infcx::const_eval_resolve` instead.
- if ct.substs.has_non_region_infer() {
+ if ct.args.has_non_region_infer() {
bug!("did not expect inference variables here");
}
- match ty::Instance::resolve(self, param_env, ct.def, ct.substs) {
+ match ty::Instance::resolve(self, param_env, ct.def, ct.args) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: None };
self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| {
@@ -94,7 +94,7 @@ impl<'tcx> TyCtxt<'tcx> {
// @lcnr believes that successfully evaluating even though there are
// used generic parameters is a bug of evaluation, so checking for it
// here does feel somewhat sensible.
- if !self.features().generic_const_exprs && ct.substs.has_non_region_param() {
+ if !self.features().generic_const_exprs && ct.args.has_non_region_param() {
let def_kind = self.def_kind(instance.def_id());
assert!(
matches!(
@@ -139,7 +139,6 @@ impl<'tcx> TyCtxt<'tcx> {
cid: GlobalId<'tcx>,
span: Option<Span>,
) -> EvalToConstValueResult<'tcx> {
- let param_env = param_env.with_const();
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
// improve caching of queries.
let inputs = self.erase_regions(param_env.and(cid));
@@ -158,8 +157,6 @@ impl<'tcx> TyCtxt<'tcx> {
cid: GlobalId<'tcx>,
span: Option<Span>,
) -> EvalToValTreeResult<'tcx> {
- let param_env = param_env.with_const();
- debug!(?param_env);
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
// improve caching of queries.
let inputs = self.erase_regions(param_env.and(cid));
@@ -204,7 +201,6 @@ impl<'tcx> TyCtxtAt<'tcx> {
gid: GlobalId<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Result<mir::ConstAllocation<'tcx>, ErrorHandled> {
- let param_env = param_env.with_const();
trace!("eval_to_allocation: Need to compute {:?}", gid);
let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?;
Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory())
@@ -221,11 +217,10 @@ impl<'tcx> TyCtxtEnsure<'tcx> {
// to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
// into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
// encountered.
- let substs = InternalSubsts::identity_for_item(self.tcx, def_id);
- let instance = ty::Instance::new(def_id, substs);
+ let args = GenericArgs::identity_for_item(self.tcx, def_id);
+ let instance = ty::Instance::new(def_id, args);
let cid = GlobalId { instance, promoted: None };
- let param_env =
- self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx).with_const();
+ let param_env = self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx);
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
// improve caching of queries.
let inputs = self.tcx.erase_regions(param_env.and(cid));
@@ -238,7 +233,7 @@ impl<'tcx> TyCtxtEnsure<'tcx> {
assert!(self.tcx.is_static(def_id));
let instance = ty::Instance::mono(self.tcx, def_id);
let gid = GlobalId { instance, promoted: None };
- let param_env = ty::ParamEnv::reveal_all().with_const();
+ let param_env = ty::ParamEnv::reveal_all();
trace!("eval_to_allocation: Need to compute {:?}", gid);
self.eval_to_allocation_raw(param_env.and(gid))
}
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 0416411df..5345a6588 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -135,8 +135,8 @@ static_assert_size!(Scalar, 24);
impl<Prov: Provenance> fmt::Debug for Scalar<Prov> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- Scalar::Ptr(ptr, _size) => write!(f, "{:?}", ptr),
- Scalar::Int(int) => write!(f, "{:?}", int),
+ Scalar::Ptr(ptr, _size) => write!(f, "{ptr:?}"),
+ Scalar::Int(int) => write!(f, "{int:?}"),
}
}
}
@@ -144,8 +144,8 @@ impl<Prov: Provenance> fmt::Debug for Scalar<Prov> {
impl<Prov: Provenance> fmt::Display for Scalar<Prov> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr),
- Scalar::Int(int) => write!(f, "{}", int),
+ Scalar::Ptr(ptr, _size) => write!(f, "pointer to {ptr:?}"),
+ Scalar::Int(int) => write!(f, "{int}"),
}
}
}
@@ -153,8 +153,8 @@ impl<Prov: Provenance> fmt::Display for Scalar<Prov> {
impl<Prov: Provenance> fmt::LowerHex for Scalar<Prov> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr),
- Scalar::Int(int) => write!(f, "{:#x}", int),
+ Scalar::Ptr(ptr, _size) => write!(f, "pointer to {ptr:?}"),
+ Scalar::Int(int) => write!(f, "{int:#x}"),
}
}
}
@@ -320,6 +320,14 @@ impl<Prov> Scalar<Prov> {
}
})
}
+
+ #[inline]
+ pub fn size(self) -> Size {
+ match self {
+ Scalar::Int(int) => int.size(),
+ Scalar::Ptr(_ptr, sz) => Size::from_bytes(sz),
+ }
+ }
}
impl<'tcx, Prov: Provenance> Scalar<Prov> {
@@ -370,15 +378,16 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
#[inline]
pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
- self.try_to_int().map_err(|_| err_unsup!(ReadPointerAsBytes))?.to_bits(target_size).map_err(
- |size| {
+ self.try_to_int()
+ .map_err(|_| err_unsup!(ReadPointerAsInt(None)))?
+ .to_bits(target_size)
+ .map_err(|size| {
err_ub!(ScalarSizeMismatch(ScalarSizeMismatch {
target_size: target_size.bytes(),
data_size: size.bytes(),
}))
.into()
- },
- )
+ })
}
#[inline(always)]