summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/mir/interpret
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src/mir/interpret')
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs32
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs53
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs8
-rw-r--r--compiler/rustc_middle/src/mir/interpret/pointer.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs23
5 files changed, 95 insertions, 23 deletions
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 dcb56a175..d4dd56a42 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
@@ -5,7 +5,9 @@ use std::hash;
use std::iter;
use std::ops::Range;
+use rustc_serialize::{Decodable, Encodable};
use rustc_target::abi::Size;
+use rustc_type_ir::{TyDecoder, TyEncoder};
use super::AllocRange;
@@ -182,11 +184,39 @@ impl InitMask {
/// The actual materialized blocks of the bitmask, when we can't keep the `InitMask` lazy.
// Note: for performance reasons when interning, some of the fields can be partially
// hashed. (see the `Hash` impl below for more details), so the impl is not derived.
-#[derive(Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, HashStable)]
+#[derive(Clone, Debug, Eq, PartialEq, HashStable)]
struct InitMaskMaterialized {
blocks: Vec<Block>,
}
+// `Block` is a `u64`, but it is a bitmask not a numeric value. If we were to just derive
+// Encodable and Decodable we would apply varint encoding to the bitmasks, which is slower
+// and also produces more output when the high bits of each `u64` are occupied.
+// Note: There is probably a remaining optimization for masks that do not use an entire
+// `Block`.
+impl<E: TyEncoder> Encodable<E> for InitMaskMaterialized {
+ fn encode(&self, encoder: &mut E) {
+ encoder.emit_usize(self.blocks.len());
+ for block in &self.blocks {
+ encoder.emit_raw_bytes(&block.to_le_bytes());
+ }
+ }
+}
+
+// This implementation is deliberately not derived, see the matching `Encodable` impl.
+impl<D: TyDecoder> Decodable<D> for InitMaskMaterialized {
+ fn decode(decoder: &mut D) -> Self {
+ let num_blocks = decoder.read_usize();
+ let mut blocks = Vec::with_capacity(num_blocks);
+ for _ in 0..num_blocks {
+ let bytes = decoder.read_raw_bytes(8);
+ let block = u64::from_le_bytes(bytes.try_into().unwrap());
+ blocks.push(block);
+ }
+ InitMaskMaterialized { blocks }
+ }
+}
+
// Const allocations are only hashed for interning. However, they can be large, making the hashing
// expensive especially since it uses `FxHash`: it's better suited to short keys, not potentially
// big buffers like the allocation's init mask. We can partially hash some fields when they're
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index c5137cf06..055d8e9a3 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -1,7 +1,8 @@
use super::{AllocId, AllocRange, ConstAlloc, Pointer, Scalar};
use crate::mir::interpret::ConstValue;
-use crate::ty::{layout, query::TyCtxtAt, tls, Ty, ValTree};
+use crate::query::TyCtxtAt;
+use crate::ty::{layout, tls, Ty, ValTree};
use rustc_data_structures::sync::Lock;
use rustc_errors::{pluralize, struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
@@ -15,15 +16,49 @@ use std::{any::Any, backtrace::Backtrace, fmt};
pub enum ErrorHandled {
/// Already reported an error for this evaluation, and the compilation is
/// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`.
- Reported(ErrorGuaranteed),
+ Reported(ReportedErrorInfo),
/// Don't emit an error, the evaluation failed because the MIR was generic
/// and the substs didn't fully monomorphize it.
TooGeneric,
}
impl From<ErrorGuaranteed> for ErrorHandled {
- fn from(err: ErrorGuaranteed) -> ErrorHandled {
- ErrorHandled::Reported(err)
+ #[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
}
}
@@ -89,7 +124,7 @@ fn print_backtrace(backtrace: &Backtrace) {
impl From<ErrorGuaranteed> for InterpErrorInfo<'_> {
fn from(err: ErrorGuaranteed) -> Self {
- InterpError::InvalidProgram(InvalidProgramInfo::AlreadyReported(err)).into()
+ InterpError::InvalidProgram(InvalidProgramInfo::AlreadyReported(err.into())).into()
}
}
@@ -125,7 +160,7 @@ pub enum InvalidProgramInfo<'tcx> {
/// Resolution can fail if we are in a too generic context.
TooGeneric,
/// Abort in case errors are already reported.
- AlreadyReported(ErrorGuaranteed),
+ AlreadyReported(ReportedErrorInfo),
/// An error occurred during layout computation.
Layout(layout::LayoutError<'tcx>),
/// An error occurred during FnAbi computation: the passed --target lacks FFI support
@@ -134,6 +169,9 @@ pub enum InvalidProgramInfo<'tcx> {
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,
}
impl fmt::Display for InvalidProgramInfo<'_> {
@@ -141,7 +179,7 @@ impl fmt::Display for InvalidProgramInfo<'_> {
use InvalidProgramInfo::*;
match self {
TooGeneric => write!(f, "encountered overly generic constant"),
- AlreadyReported(ErrorGuaranteed { .. }) => {
+ AlreadyReported(_) => {
write!(
f,
"an error has already been reported elsewhere (this should not usually be printed)"
@@ -150,6 +188,7 @@ impl fmt::Display for InvalidProgramInfo<'_> {
Layout(ref err) => write!(f, "{err}"),
FnAbiAdjustForForeignAbi(ref err) => write!(f, "{err}"),
SizeOfUnsizedType(ty) => write!(f, "size_of called on unsized type `{ty}`"),
+ UninitUnsizedLocal => write!(f, "unsized local is used while uninitialized"),
}
}
}
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 1f8b650e3..3620385fa 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -120,8 +120,8 @@ use crate::ty::{self, Instance, Ty, TyCtxt};
pub use self::error::{
struct_error, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult,
EvalToValTreeResult, InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo,
- MachineStopType, ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo,
- UninitBytesAccess, UnsupportedOpInfo,
+ MachineStopType, ReportedErrorInfo, ResourceExhaustionInfo, ScalarSizeMismatch,
+ UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
};
pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar};
@@ -227,7 +227,9 @@ pub fn specialized_encode_alloc_id<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>>(
// References to statics doesn't need to know about their allocations,
// just about its `DefId`.
AllocDiscriminant::Static.encode(encoder);
- did.encode(encoder);
+ // Cannot use `did.encode(encoder)` because of a bug around
+ // specializations and method calls.
+ Encodable::<E>::encode(&did, encoder);
}
}
}
diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs
index 60927eed8..65d049193 100644
--- a/compiler/rustc_middle/src/mir/interpret/pointer.rs
+++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs
@@ -102,7 +102,7 @@ impl<T: HasDataLayout> PointerArithmetic for T {}
/// This trait abstracts over the kind of provenance that is associated with a `Pointer`. It is
/// mostly opaque; the `Machine` trait extends it with some more operations that also have access to
/// some global state.
-/// The `Debug` rendering is used to distplay bare provenance, and for the default impl of `fmt`.
+/// The `Debug` rendering is used to display bare provenance, and for the default impl of `fmt`.
pub trait Provenance: Copy + fmt::Debug {
/// Says whether the `offset` field of `Pointer`s with this provenance is the actual physical address.
/// - If `false`, the offset *must* be relative. This means the bytes representing a pointer are
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 856d821a5..f53dc8cb0 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -1,9 +1,10 @@
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::{self, query::TyCtxtAt, query::TyCtxtEnsure, TyCtxt};
+use crate::ty::{self, TyCtxt};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_session::lint;
@@ -42,7 +43,7 @@ impl<'tcx> TyCtxt<'tcx> {
span: Option<Span>,
) -> EvalToConstValueResult<'tcx> {
// Cannot resolve `Unevaluated` constants that contain inference
- // variables. We reject those here since `resolve_opt_const_arg`
+ // variables. We reject those here since `resolve`
// would fail otherwise.
//
// When trying to evaluate constants containing inference variables,
@@ -51,7 +52,7 @@ impl<'tcx> TyCtxt<'tcx> {
bug!("did not expect inference variables here");
}
- match ty::Instance::resolve_opt_const_arg(
+ match ty::Instance::resolve(
self, param_env,
// FIXME: maybe have a separate version for resolving mir::UnevaluatedConst?
ct.def, ct.substs,
@@ -61,7 +62,7 @@ impl<'tcx> TyCtxt<'tcx> {
self.const_eval_global_id(param_env, cid, span)
}
Ok(None) => Err(ErrorHandled::TooGeneric),
- Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),
+ Err(err) => Err(ErrorHandled::Reported(err.into())),
}
}
@@ -73,7 +74,7 @@ impl<'tcx> TyCtxt<'tcx> {
span: Option<Span>,
) -> EvalToValTreeResult<'tcx> {
// Cannot resolve `Unevaluated` constants that contain inference
- // variables. We reject those here since `resolve_opt_const_arg`
+ // variables. We reject those here since `resolve`
// would fail otherwise.
//
// When trying to evaluate constants containing inference variables,
@@ -82,7 +83,7 @@ impl<'tcx> TyCtxt<'tcx> {
bug!("did not expect inference variables here");
}
- match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
+ match ty::Instance::resolve(self, param_env, ct.def, ct.substs) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: None };
self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| {
@@ -94,14 +95,14 @@ impl<'tcx> TyCtxt<'tcx> {
// 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() {
- assert!(matches!(self.def_kind(ct.def.did), DefKind::AnonConst));
- let mir_body = self.mir_for_ctfe_opt_const_arg(ct.def);
+ assert!(matches!(self.def_kind(ct.def), DefKind::AnonConst));
+ let mir_body = self.mir_for_ctfe(ct.def);
if mir_body.is_polymorphic {
- let Some(local_def_id) = ct.def.did.as_local() else { return };
+ let Some(local_def_id) = ct.def.as_local() else { return };
self.struct_span_lint_hir(
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
self.hir().local_def_id_to_hir_id(local_def_id),
- self.def_span(ct.def.did),
+ self.def_span(ct.def),
"cannot use constants which depend on generic parameters in types",
|err| err,
)
@@ -110,7 +111,7 @@ impl<'tcx> TyCtxt<'tcx> {
})
}
Ok(None) => Err(ErrorHandled::TooGeneric),
- Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),
+ Err(err) => Err(ErrorHandled::Reported(err.into())),
}
}