move ConstValue into mir

this way we have mir::ConstValue and ty::ValTree as reasonably parallel
This commit is contained in:
Ralf Jung 2023-09-16 09:36:22 +02:00
parent be8f5f6e7f
commit 5a0a1ff0cd
34 changed files with 245 additions and 254 deletions

View File

@ -2,7 +2,8 @@
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::{read_target_uint, AllocId, ConstValue, GlobalAlloc, Scalar};
use rustc_middle::mir::interpret::{read_target_uint, AllocId, GlobalAlloc, Scalar};
use rustc_middle::mir::ConstValue;
use cranelift_module::*;

View File

@ -1,7 +1,7 @@
#![allow(non_camel_case_types)]
use rustc_hir::LangItem;
use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::mir;
use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
use rustc_span::Span;
@ -194,10 +194,10 @@ pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
pub fn asm_const_to_str<'tcx>(
tcx: TyCtxt<'tcx>,
sp: Span,
const_value: ConstValue<'tcx>,
const_value: mir::ConstValue<'tcx>,
ty_and_layout: TyAndLayout<'tcx>,
) -> String {
let ConstValue::Scalar(scalar) = const_value else {
let mir::ConstValue::Scalar(scalar) = const_value else {
span_bug!(sp, "expected Scalar for promoted asm const, but got {:#?}", const_value)
};
let value = scalar.assert_bits(ty_and_layout.size);

View File

@ -2,7 +2,7 @@
use crate::mir::operand::OperandRef;
use crate::traits::*;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::{self, Ty};
use rustc_target::abi::Abi;
@ -20,7 +20,7 @@ pub fn eval_mir_constant_to_operand(
OperandRef::from_const(bx, val, ty)
}
pub fn eval_mir_constant(&self, constant: &mir::Constant<'tcx>) -> ConstValue<'tcx> {
pub fn eval_mir_constant(&self, constant: &mir::Constant<'tcx>) -> mir::ConstValue<'tcx> {
self.monomorphize(constant.literal)
.eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), Some(constant.span))
.expect("erroneous constant not captured by required_consts")

View File

@ -6,8 +6,8 @@
use crate::traits::*;
use crate::MemFlags;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{alloc_range, ConstValue, Pointer, Scalar};
use rustc_middle::mir::interpret::{alloc_range, Pointer, Scalar};
use rustc_middle::mir::{self, ConstValue};
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::Ty;
use rustc_target::abi::{self, Abi, Align, Size};
@ -86,7 +86,7 @@ pub fn zero_sized(layout: TyAndLayout<'tcx>) -> OperandRef<'tcx, V> {
pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
bx: &mut Bx,
val: ConstValue<'tcx>,
val: mir::ConstValue<'tcx>,
ty: Ty<'tcx>,
) -> Self {
let layout = bx.layout_of(ty);

View File

@ -4,9 +4,9 @@
use either::{Left, Right};
use rustc_hir::def::DefKind;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{ErrorHandled, InterpErrorInfo};
use rustc_middle::mir::pretty::write_allocation_bytes;
use rustc_middle::mir::{self, ConstAlloc, ConstValue};
use rustc_middle::traits::Reveal;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::print::with_no_trimmed_paths;
@ -18,9 +18,8 @@
use crate::errors;
use crate::interpret::eval_nullary_intrinsic;
use crate::interpret::{
intern_const_alloc_recursive, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId, Immediate,
InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking,
StackPopCleanup,
intern_const_alloc_recursive, CtfeValidationMode, GlobalId, Immediate, InternKind, InterpCx,
InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, StackPopCleanup,
};
// Returns a pointer to where the result lives

View File

@ -1,7 +1,7 @@
// Not in interpret to make sure we do not use private implementation details
use crate::errors::MaxNumNodesInConstErr;
use crate::interpret::{intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, Scalar};
use crate::interpret::{intern_const_alloc_recursive, InternKind, InterpCx, Scalar};
use rustc_middle::mir;
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
use rustc_middle::ty::{self, Ty, TyCtxt};
@ -22,7 +22,7 @@
pub(crate) fn const_caller_location(
tcx: TyCtxt<'_>,
(file, line, col): (Symbol, u32, u32),
) -> ConstValue<'_> {
) -> mir::ConstValue<'_> {
trace!("const_caller_location: {}:{}:{}", file, line, col);
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), CanAccessStatics::No);
@ -30,7 +30,7 @@ pub(crate) fn const_caller_location(
if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
bug!("intern_const_alloc_recursive should not error in this case")
}
ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr(), &tcx))
mir::ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr(), &tcx))
}
// We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes.
@ -87,7 +87,7 @@ pub(crate) fn eval_to_valtree<'tcx>(
#[instrument(skip(tcx), level = "debug")]
pub(crate) fn try_destructure_mir_constant_for_diagnostics<'tcx>(
tcx: TyCtxt<'tcx>,
val: ConstValue<'tcx>,
val: mir::ConstValue<'tcx>,
ty: Ty<'tcx>,
) -> Option<mir::DestructuredConstant<'tcx>> {
let param_env = ty::ParamEnv::reveal_all();

View File

@ -4,9 +4,10 @@
use crate::const_eval::CanAccessStatics;
use crate::interpret::MPlaceTy;
use crate::interpret::{
intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemPlaceMeta,
MemoryKind, PlaceTy, Projectable, Scalar,
intern_const_alloc_recursive, ImmTy, Immediate, InternKind, MemPlaceMeta, MemoryKind, PlaceTy,
Projectable, Scalar,
};
use rustc_middle::mir;
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
use rustc_span::source_map::DUMMY_SP;
@ -206,7 +207,7 @@ pub fn valtree_to_const_value<'tcx>(
tcx: TyCtxt<'tcx>,
param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
valtree: ty::ValTree<'tcx>,
) -> ConstValue<'tcx> {
) -> mir::ConstValue<'tcx> {
// Basic idea: We directly construct `Scalar` values from trivial `ValTree`s
// (those for constants with type bool, int, uint, float or char).
// For all other types we create an `MPlace` and fill that by walking
@ -219,10 +220,10 @@ pub fn valtree_to_const_value<'tcx>(
match ty.kind() {
ty::FnDef(..) => {
assert!(valtree.unwrap_branch().is_empty());
ConstValue::ZeroSized
mir::ConstValue::ZeroSized
}
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => match valtree {
ty::ValTree::Leaf(scalar_int) => ConstValue::Scalar(Scalar::Int(scalar_int)),
ty::ValTree::Leaf(scalar_int) => mir::ConstValue::Scalar(Scalar::Int(scalar_int)),
ty::ValTree::Branch(_) => bug!(
"ValTrees for Bool, Int, Uint, Float or Char should have the form ValTree::Leaf"
),
@ -237,7 +238,7 @@ pub fn valtree_to_const_value<'tcx>(
let layout = tcx.layout_of(param_env_ty).unwrap();
if layout.is_zst() {
// Fast path to avoid some allocations.
return ConstValue::ZeroSized;
return mir::ConstValue::ZeroSized;
}
if layout.abi.is_scalar()
&& (matches!(ty.kind(), ty::Tuple(_))

View File

@ -5,10 +5,8 @@
use rustc_hir::def_id::DefId;
use rustc_middle::mir::{
self,
interpret::{
Allocation, ConstAllocation, ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar,
},
BinOp, NonDivergingIntrinsic,
interpret::{Allocation, ConstAllocation, GlobalId, InterpResult, PointerArithmetic, Scalar},
BinOp, ConstValue, NonDivergingIntrinsic,
};
use rustc_middle::ty;
use rustc_middle::ty::layout::{LayoutOf as _, ValidityRequirement};

View File

@ -13,9 +13,8 @@
use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size};
use super::{
alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, Frame, InterpCx,
InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, PlaceTy, Pointer, Projectable,
Provenance, Scalar,
alloc_range, from_known_layout, mir_assign_valid_types, AllocId, Frame, InterpCx, InterpResult,
MPlaceTy, Machine, MemPlace, MemPlaceMeta, PlaceTy, Pointer, Projectable, Provenance, Scalar,
};
/// An `Immediate` represents a single immediate self-contained Rust value.
@ -702,7 +701,7 @@ pub fn eval_operand(
pub(crate) fn const_val_to_op(
&self,
val_val: ConstValue<'tcx>,
val_val: mir::ConstValue<'tcx>,
ty: Ty<'tcx>,
layout: Option<TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
@ -715,15 +714,15 @@ pub(crate) fn const_val_to_op(
};
let layout = from_known_layout(self.tcx, self.param_env, layout, || self.layout_of(ty))?;
let op = match val_val {
ConstValue::Indirect { alloc_id, offset } => {
mir::ConstValue::Indirect { alloc_id, offset } => {
// We rely on mutability being set correctly in that allocation to prevent writes
// where none should happen.
let ptr = self.global_base_pointer(Pointer::new(alloc_id, offset))?;
Operand::Indirect(MemPlace::from_ptr(ptr.into()))
}
ConstValue::Scalar(x) => Operand::Immediate(adjust_scalar(x)?.into()),
ConstValue::ZeroSized => Operand::Immediate(Immediate::Uninit),
ConstValue::Slice { data, start, end } => {
mir::ConstValue::Scalar(x) => Operand::Immediate(adjust_scalar(x)?.into()),
mir::ConstValue::ZeroSized => Operand::Immediate(Immediate::Uninit),
mir::ConstValue::Slice { data, start, end } => {
// We rely on mutability being set correctly in `data` to prevent writes
// where none should happen.
let ptr = Pointer::new(

View File

@ -9,16 +9,15 @@
use rustc_ast::Mutability;
use rustc_index::IndexSlice;
use rustc_middle::mir;
use rustc_middle::mir::interpret::PointerArithmetic;
use rustc_middle::ty;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::Ty;
use rustc_target::abi::{Abi, Align, FieldIdx, HasDataLayout, Size, FIRST_VARIANT};
use super::{
alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg,
ConstAlloc, ImmTy, Immediate, InterpCx, InterpResult, Machine, MemoryKind, OpTy, Operand,
Pointer, Projectable, Provenance, Readable, Scalar,
alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg, ImmTy,
Immediate, InterpCx, InterpResult, Machine, MemoryKind, OpTy, Operand, Pointer,
PointerArithmetic, Projectable, Provenance, Readable, Scalar,
};
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
@ -1037,7 +1036,7 @@ pub fn write_aggregate(
pub fn raw_const_to_mplace(
&self,
raw: ConstAlloc<'tcx>,
raw: mir::ConstAlloc<'tcx>,
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
// This must be an allocation in `tcx`
let _ = self.tcx.global_alloc(raw.alloc_id);

View File

@ -4,14 +4,169 @@
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir};
use rustc_span::Span;
use rustc_target::abi::Size;
use rustc_target::abi::{HasDataLayout, Size};
use crate::mir::interpret::{ConstValue, ErrorHandled, GlobalAlloc, Scalar};
use crate::mir::{interpret, pretty_print_const_value, Promoted};
use crate::mir::interpret::{
alloc_range, AllocId, ConstAllocation, ErrorHandled, GlobalAlloc, Scalar,
};
use crate::mir::{pretty_print_const_value, Promoted};
use crate::ty::{self, print::pretty_print_const, List, Ty, TyCtxt};
use crate::ty::{GenericArgs, GenericArgsRef};
use crate::ty::{ScalarInt, UserTypeAnnotationIndex};
///////////////////////////////////////////////////////////////////////////
/// Evaluated Constants
/// Represents the result of const evaluation via the `eval_to_allocation` query.
/// Not to be confused with `ConstAllocation`, which directly refers to the underlying data!
/// Here we indirect via an `AllocId`.
#[derive(Copy, Clone, HashStable, TyEncodable, TyDecodable, Debug, Hash, Eq, PartialEq)]
pub struct ConstAlloc<'tcx> {
/// The value lives here, at offset 0, and that allocation definitely is an `AllocKind::Memory`
/// (so you can use `AllocMap::unwrap_memory`).
pub alloc_id: AllocId,
pub ty: Ty<'tcx>,
}
/// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations for
/// array length computations, enum discriminants and the pattern matching logic.
#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash)]
#[derive(HashStable, Lift)]
pub enum ConstValue<'tcx> {
/// Used for types with `layout::abi::Scalar` ABI.
///
/// Not using the enum `Value` to encode that this must not be `Uninit`.
Scalar(Scalar),
/// Only for ZSTs.
ZeroSized,
/// Used for `&[u8]` and `&str`.
///
/// This is worth an optimized representation since Rust has literals of these types.
/// Not having to indirect those through an `AllocId` (or two, if we used `Indirect`) has shown
/// measurable performance improvements on stress tests.
Slice { data: ConstAllocation<'tcx>, start: usize, end: usize },
/// A value not representable by the other variants; needs to be stored in-memory.
///
/// Must *not* be used for scalars or ZST, but having `&str` or other slices in this variant is fine.
Indirect {
/// The backing memory of the value. May contain more memory than needed for just the value
/// if this points into some other larger ConstValue.
///
/// We use an `AllocId` here instead of a `ConstAllocation<'tcx>` to make sure that when a
/// raw constant (which is basically just an `AllocId`) is turned into a `ConstValue` and
/// back, we can preserve the original `AllocId`.
alloc_id: AllocId,
/// Offset into `alloc`
offset: Size,
},
}
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(ConstValue<'_>, 32);
impl<'tcx> ConstValue<'tcx> {
#[inline]
pub fn try_to_scalar(&self) -> Option<Scalar<AllocId>> {
match *self {
ConstValue::Indirect { .. } | ConstValue::Slice { .. } | ConstValue::ZeroSized => None,
ConstValue::Scalar(val) => Some(val),
}
}
pub fn try_to_scalar_int(&self) -> Option<ScalarInt> {
self.try_to_scalar()?.try_to_int().ok()
}
pub fn try_to_bits(&self, size: Size) -> Option<u128> {
self.try_to_scalar_int()?.to_bits(size).ok()
}
pub fn try_to_bool(&self) -> Option<bool> {
self.try_to_scalar_int()?.try_into().ok()
}
pub fn try_to_target_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_scalar_int()?.try_to_target_usize(tcx).ok()
}
pub fn try_to_bits_for_ty(
&self,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>,
) -> Option<u128> {
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
self.try_to_bits(size)
}
pub fn from_bool(b: bool) -> Self {
ConstValue::Scalar(Scalar::from_bool(b))
}
pub fn from_u64(i: u64) -> Self {
ConstValue::Scalar(Scalar::from_u64(i))
}
pub fn from_u128(i: u128) -> Self {
ConstValue::Scalar(Scalar::from_u128(i))
}
pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
ConstValue::Scalar(Scalar::from_target_usize(i, cx))
}
/// Must only be called on constants of type `&str` or `&[u8]`!
pub fn try_get_slice_bytes_for_diagnostics(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx [u8]> {
let (data, start, end) = match self {
ConstValue::Scalar(_) | ConstValue::ZeroSized => {
bug!("`try_get_slice_bytes` on non-slice constant")
}
&ConstValue::Slice { data, start, end } => (data, start, end),
&ConstValue::Indirect { alloc_id, offset } => {
// The reference itself is stored behind an indirection.
// Load the reference, and then load the actual slice contents.
let a = tcx.global_alloc(alloc_id).unwrap_memory().inner();
let ptr_size = tcx.data_layout.pointer_size;
if a.size() < offset + 2 * ptr_size {
// (partially) dangling reference
return None;
}
// Read the wide pointer components.
let ptr = a
.read_scalar(
&tcx,
alloc_range(offset, ptr_size),
/* read_provenance */ true,
)
.ok()?;
let ptr = ptr.to_pointer(&tcx).ok()?;
let len = a
.read_scalar(
&tcx,
alloc_range(offset + ptr_size, ptr_size),
/* read_provenance */ false,
)
.ok()?;
let len = len.to_target_usize(&tcx).ok()?;
let len: usize = len.try_into().ok()?;
if len == 0 {
return Some(&[]);
}
// Non-empty slice, must have memory. We know this is a relative pointer.
let (inner_alloc_id, offset) = ptr.into_parts();
let data = tcx.global_alloc(inner_alloc_id?).unwrap_memory();
(data, offset.bytes_usize(), offset.bytes_usize() + len)
}
};
// This is for diagnostics only, so we are okay to use `inspect_with_uninit_and_ptr_outside_interpreter`.
Some(data.inner().inspect_with_uninit_and_ptr_outside_interpreter(start..end))
}
}
///////////////////////////////////////////////////////////////////////////
/// Constants
///
@ -49,7 +204,7 @@ pub enum ConstantKind<'tcx> {
/// This constant cannot go back into the type system, as it represents
/// something the type system cannot handle (e.g. pointers).
Val(interpret::ConstValue<'tcx>, Ty<'tcx>),
Val(ConstValue<'tcx>, Ty<'tcx>),
}
impl<'tcx> Constant<'tcx> {
@ -116,7 +271,7 @@ pub fn eval(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
span: Option<Span>,
) -> Result<interpret::ConstValue<'tcx>, ErrorHandled> {
) -> Result<ConstValue<'tcx>, ErrorHandled> {
match self {
ConstantKind::Ty(c) => {
// We want to consistently have a "clean" value for type system constants (i.e., no

View File

@ -1,7 +1,7 @@
use super::{AllocId, AllocRange, ConstAlloc, Pointer, Scalar};
use super::{AllocId, AllocRange, Pointer, Scalar};
use crate::error;
use crate::mir::interpret::ConstValue;
use crate::mir::{ConstAlloc, ConstValue};
use crate::query::TyCtxtAt;
use crate::ty::{layout, tls, Ty, TyCtxt, ValTree};

View File

@ -149,7 +149,7 @@ macro_rules! throw_ub_custom {
UnsupportedOpInfo, ValidationErrorInfo, ValidationErrorKind,
};
pub use self::value::{ConstAlloc, ConstValue, Scalar};
pub use self::value::Scalar;
pub use self::allocation::{
alloc_range, AllocBytes, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation,

View File

@ -9,163 +9,9 @@
use rustc_macros::HashStable;
use rustc_target::abi::{HasDataLayout, Size};
use crate::{
mir::interpret::alloc_range,
ty::{ParamEnv, ScalarInt, Ty, TyCtxt},
};
use crate::ty::ScalarInt;
use super::{
AllocId, ConstAllocation, InterpResult, Pointer, PointerArithmetic, Provenance,
ScalarSizeMismatch,
};
/// Represents the result of const evaluation via the `eval_to_allocation` query.
#[derive(Copy, Clone, HashStable, TyEncodable, TyDecodable, Debug, Hash, Eq, PartialEq)]
pub struct ConstAlloc<'tcx> {
/// The value lives here, at offset 0, and that allocation definitely is an `AllocKind::Memory`
/// (so you can use `AllocMap::unwrap_memory`).
pub alloc_id: AllocId,
pub ty: Ty<'tcx>,
}
/// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations for
/// array length computations, enum discriminants and the pattern matching logic.
#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash)]
#[derive(HashStable, Lift)]
pub enum ConstValue<'tcx> {
/// Used for types with `layout::abi::Scalar` ABI.
///
/// Not using the enum `Value` to encode that this must not be `Uninit`.
Scalar(Scalar),
/// Only for ZSTs.
ZeroSized,
/// Used for `&[u8]` and `&str`.
///
/// This is worth an optimized representation since Rust has literals of these types.
/// Not having to indirect those through an `AllocId` (or two, if we used `Indirect`) has shown
/// measurable performance improvements on stress tests.
Slice { data: ConstAllocation<'tcx>, start: usize, end: usize },
/// A value not representable by the other variants; needs to be stored in-memory.
///
/// Must *not* be used for scalars or ZST, but having `&str` or other slices in this variant is fine.
Indirect {
/// The backing memory of the value. May contain more memory than needed for just the value
/// if this points into some other larger ConstValue.
///
/// We use an `AllocId` here instead of a `ConstAllocation<'tcx>` to make sure that when a
/// raw constant (which is basically just an `AllocId`) is turned into a `ConstValue` and
/// back, we can preserve the original `AllocId`.
alloc_id: AllocId,
/// Offset into `alloc`
offset: Size,
},
}
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(ConstValue<'_>, 32);
impl<'tcx> ConstValue<'tcx> {
#[inline]
pub fn try_to_scalar(&self) -> Option<Scalar<AllocId>> {
match *self {
ConstValue::Indirect { .. } | ConstValue::Slice { .. } | ConstValue::ZeroSized => None,
ConstValue::Scalar(val) => Some(val),
}
}
pub fn try_to_scalar_int(&self) -> Option<ScalarInt> {
self.try_to_scalar()?.try_to_int().ok()
}
pub fn try_to_bits(&self, size: Size) -> Option<u128> {
self.try_to_scalar_int()?.to_bits(size).ok()
}
pub fn try_to_bool(&self) -> Option<bool> {
self.try_to_scalar_int()?.try_into().ok()
}
pub fn try_to_target_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_scalar_int()?.try_to_target_usize(tcx).ok()
}
pub fn try_to_bits_for_ty(
&self,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
ty: Ty<'tcx>,
) -> Option<u128> {
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
self.try_to_bits(size)
}
pub fn from_bool(b: bool) -> Self {
ConstValue::Scalar(Scalar::from_bool(b))
}
pub fn from_u64(i: u64) -> Self {
ConstValue::Scalar(Scalar::from_u64(i))
}
pub fn from_u128(i: u128) -> Self {
ConstValue::Scalar(Scalar::from_u128(i))
}
pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
ConstValue::Scalar(Scalar::from_target_usize(i, cx))
}
/// Must only be called on constants of type `&str` or `&[u8]`!
pub fn try_get_slice_bytes_for_diagnostics(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx [u8]> {
let (data, start, end) = match self {
ConstValue::Scalar(_) | ConstValue::ZeroSized => {
bug!("`try_get_slice_bytes` on non-slice constant")
}
&ConstValue::Slice { data, start, end } => (data, start, end),
&ConstValue::Indirect { alloc_id, offset } => {
// The reference itself is stored behind an indirection.
// Load the reference, and then load the actual slice contents.
let a = tcx.global_alloc(alloc_id).unwrap_memory().inner();
let ptr_size = tcx.data_layout.pointer_size;
if a.size() < offset + 2 * ptr_size {
// (partially) dangling reference
return None;
}
// Read the wide pointer components.
let ptr = a
.read_scalar(
&tcx,
alloc_range(offset, ptr_size),
/* read_provenance */ true,
)
.ok()?;
let ptr = ptr.to_pointer(&tcx).ok()?;
let len = a
.read_scalar(
&tcx,
alloc_range(offset + ptr_size, ptr_size),
/* read_provenance */ false,
)
.ok()?;
let len = len.to_target_usize(&tcx).ok()?;
let len: usize = len.try_into().ok()?;
if len == 0 {
return Some(&[]);
}
// Non-empty slice, must have memory. We know this is a relative pointer.
let (inner_alloc_id, offset) = ptr.into_parts();
let data = tcx.global_alloc(inner_alloc_id?).unwrap_memory();
(data, offset.bytes_usize(), offset.bytes_usize() + len)
}
};
// This is for diagnostics only, so we are okay to use `inspect_with_uninit_and_ptr_outside_interpreter`.
Some(data.inner().inspect_with_uninit_and_ptr_outside_interpreter(start..end))
}
}
use super::{AllocId, InterpResult, Pointer, PointerArithmetic, Provenance, ScalarSizeMismatch};
/// A `Scalar` represents an immediate, primitive value existing outside of a
/// `memory::Allocation`. It is in many ways like a small chunk of an `Allocation`, up to 16 bytes in

View File

@ -2,7 +2,7 @@
//!
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
use crate::mir::interpret::{AllocRange, ErrorHandled, ConstAllocation, ConstValue, Scalar};
use crate::mir::interpret::{AllocRange, ConstAllocation, ErrorHandled, Scalar};
use crate::mir::visit::MirVisitable;
use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};

View File

@ -12,8 +12,8 @@
use rustc_hir::def_id::DefId;
use rustc_index::Idx;
use rustc_middle::mir::interpret::{
alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, ConstAllocation, ConstValue,
GlobalAlloc, Pointer, Provenance,
alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, ConstAllocation, GlobalAlloc,
Pointer, Provenance,
};
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;

View File

@ -1,6 +1,5 @@
//! Values computed by queries that use MIR.
use crate::mir::interpret::ConstValue;
use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::unord::UnordSet;
@ -16,7 +15,7 @@
use std::cell::Cell;
use std::fmt::{self, Debug};
use super::SourceInfo;
use super::{ConstValue, SourceInfo};
#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
pub enum UnsafetyViolationKind {

View File

@ -121,16 +121,12 @@ impl EraseType for Result<mir::ConstantKind<'_>, mir::interpret::LitToConstError
[u8; size_of::<Result<mir::ConstantKind<'static>, mir::interpret::LitToConstError>>()];
}
impl EraseType for Result<mir::interpret::ConstAlloc<'_>, mir::interpret::ErrorHandled> {
type Result = [u8; size_of::<
Result<mir::interpret::ConstAlloc<'static>, mir::interpret::ErrorHandled>,
>()];
impl EraseType for Result<mir::ConstAlloc<'_>, mir::interpret::ErrorHandled> {
type Result = [u8; size_of::<Result<mir::ConstAlloc<'static>, mir::interpret::ErrorHandled>>()];
}
impl EraseType for Result<mir::interpret::ConstValue<'_>, mir::interpret::ErrorHandled> {
type Result = [u8; size_of::<
Result<mir::interpret::ConstValue<'static>, mir::interpret::ErrorHandled>,
>()];
impl EraseType for Result<mir::ConstValue<'_>, mir::interpret::ErrorHandled> {
type Result = [u8; size_of::<Result<mir::ConstValue<'static>, mir::interpret::ErrorHandled>>()];
}
impl EraseType for Result<Option<ty::ValTree<'_>>, mir::interpret::ErrorHandled> {
@ -317,8 +313,8 @@ impl<'tcx> EraseType for $($fake_path)::+<'tcx> {
rustc_middle::middle::exported_symbols::ExportedSymbol,
rustc_middle::mir::ConstantKind,
rustc_middle::mir::DestructuredConstant,
rustc_middle::mir::interpret::ConstAlloc,
rustc_middle::mir::interpret::ConstValue,
rustc_middle::mir::ConstAlloc,
rustc_middle::mir::ConstValue,
rustc_middle::mir::interpret::GlobalId,
rustc_middle::mir::interpret::LitToConstInput,
rustc_middle::traits::query::MethodAutoderefStepsResult,

View File

@ -2,7 +2,6 @@
use crate::infer::canonical::Canonical;
use crate::mir;
use crate::mir::interpret::ConstValue;
use crate::traits;
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::layout::{TyAndLayout, ValidityRequirement};
@ -369,7 +368,7 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
}
}
impl<'tcx> Key for (ConstValue<'tcx>, Ty<'tcx>) {
impl<'tcx> Key for (mir::ConstValue<'tcx>, Ty<'tcx>) {
type CacheSelector = DefaultCacheSelector<Self>;
fn default_span(&self, _: TyCtxt<'_>) -> Span {
@ -377,7 +376,7 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
}
}
impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> {
impl<'tcx> Key for mir::ConstAlloc<'tcx> {
type CacheSelector = DefaultCacheSelector<Self>;
fn default_span(&self, _: TyCtxt<'_>) -> Span {

View File

@ -21,7 +21,7 @@
use crate::mir;
use crate::mir::interpret::GlobalId;
use crate::mir::interpret::{
ConstValue, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult,
EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult,
};
use crate::mir::interpret::{LitToConstError, LitToConstInput};
use crate::mir::mono::CodegenUnit;
@ -1091,7 +1091,7 @@
}
/// Converts a type level constant value into `ConstValue`
query valtree_to_const_val(key: (Ty<'tcx>, ty::ValTree<'tcx>)) -> ConstValue<'tcx> {
query valtree_to_const_val(key: (Ty<'tcx>, ty::ValTree<'tcx>)) -> mir::ConstValue<'tcx> {
desc { "converting type-level constant value to mir constant value"}
}
@ -1104,14 +1104,14 @@
/// Tries to destructure an `mir::ConstantKind` ADT or array into its variant index
/// and its field values. This should only be used for pretty printing.
query try_destructure_mir_constant_for_diagnostics(
key: (ConstValue<'tcx>, Ty<'tcx>)
key: (mir::ConstValue<'tcx>, Ty<'tcx>)
) -> Option<mir::DestructuredConstant<'tcx>> {
desc { "destructuring MIR constant"}
no_hash
eval_always
}
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> mir::ConstValue<'tcx> {
desc { "getting a &core::panic::Location referring to a span" }
}

View File

@ -1,4 +1,4 @@
use rustc_middle::mir::interpret::{ConstValue, Scalar};
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::ty::cast::mir_cast_kind;
use rustc_middle::{mir::*, thir::*, ty};

View File

@ -3,9 +3,7 @@
use crate::build::{parse_float_into_constval, Builder};
use rustc_ast as ast;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{
Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
};
use rustc_middle::mir::interpret::{Allocation, LitToConstError, LitToConstInput, Scalar};
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use rustc_middle::ty::{

View File

@ -15,7 +15,6 @@
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
use rustc_middle::middle::region;
use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::*;
use rustc_middle::thir::{

View File

@ -18,7 +18,7 @@
use rustc_hir::RangeEnd;
use rustc_index::Idx;
use rustc_middle::mir::interpret::{
ConstValue, ErrorHandled, GlobalId, LitToConstError, LitToConstInput, Scalar,
ErrorHandled, GlobalId, LitToConstError, LitToConstInput, Scalar,
};
use rustc_middle::mir::{self, ConstantKind, UserTypeProjection};
use rustc_middle::mir::{BorrowKind, Mutability};
@ -855,8 +855,8 @@ pub(crate) fn compare_const_vals<'tcx>(
ty::Float(_) | ty::Int(_) => {} // require special handling, see below
_ => match (a, b) {
(
mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(a)), _a_ty),
mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(b)), _b_ty),
mir::ConstantKind::Val(mir::ConstValue::Scalar(Scalar::Int(a)), _a_ty),
mir::ConstantKind::Val(mir::ConstValue::Scalar(Scalar::Int(b)), _b_ty),
) => return Some(a.cmp(&b)),
(mir::ConstantKind::Ty(a), mir::ConstantKind::Ty(b)) => {
return Some(a.kind().cmp(&b.kind()));

View File

@ -4,7 +4,7 @@
use rustc_index::IndexVec;
use rustc_middle::mir::*;
use rustc_middle::mir::{
interpret::{ConstValue, Scalar},
interpret::Scalar,
visit::{PlaceContext, Visitor},
};
use rustc_middle::ty::{Ty, TyCtxt, TypeAndMut};

View File

@ -22,8 +22,8 @@
use crate::dataflow_const_prop::Patch;
use crate::MirPass;
use rustc_const_eval::interpret::{
self, compile_time_machine, AllocId, ConstAllocation, ConstValue, FnArg, Frame, ImmTy,
Immediate, InterpCx, InterpResult, MemoryKind, OpTy, PlaceTy, Pointer, Scalar, StackPopCleanup,
self, compile_time_machine, AllocId, ConstAllocation, FnArg, Frame, ImmTy, Immediate, InterpCx,
InterpResult, MemoryKind, OpTy, PlaceTy, Pointer, Scalar, StackPopCleanup,
};
/// The maximum number of bytes that we'll allocate space for a local or the return value.

View File

@ -6,7 +6,7 @@
use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::DefKind;
use rustc_middle::mir::interpret::{AllocId, ConstAllocation, ConstValue, InterpResult, Scalar};
use rustc_middle::mir::interpret::{AllocId, ConstAllocation, InterpResult, Scalar};
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::layout::TyAndLayout;

View File

@ -153,7 +153,7 @@ fn optim<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
span,
user_ty: None,
literal: ConstantKind::Val(
interpret::ConstValue::Indirect { alloc_id, offset: Size::ZERO },
ConstValue::Indirect { alloc_id, offset: Size::ZERO },
tmp_ty,
),
};

View File

@ -1,7 +1,6 @@
//! Removes operations on ZST places, and convert ZST operands to constants.
use crate::MirPass;
use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt};

View File

@ -170,8 +170,7 @@
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_middle::mir::interpret::{AllocId, ConstValue};
use rustc_middle::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar};
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, GlobalAlloc, Scalar};
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
use rustc_middle::mir::visit::Visitor as MirVisitor;
use rustc_middle::mir::{self, Local, Location};
@ -1442,13 +1441,15 @@ fn collect_used_items<'tcx>(
#[instrument(skip(tcx, output), level = "debug")]
fn collect_const_value<'tcx>(
tcx: TyCtxt<'tcx>,
value: ConstValue<'tcx>,
value: mir::ConstValue<'tcx>,
output: &mut MonoItems<'tcx>,
) {
match value {
ConstValue::Scalar(Scalar::Ptr(ptr, _size)) => collect_alloc(tcx, ptr.provenance, output),
ConstValue::Indirect { alloc_id, .. } => collect_alloc(tcx, alloc_id, output),
ConstValue::Slice { data, start: _, end: _ } => {
mir::ConstValue::Scalar(Scalar::Ptr(ptr, _size)) => {
collect_alloc(tcx, ptr.provenance, output)
}
mir::ConstValue::Indirect { alloc_id, .. } => collect_alloc(tcx, alloc_id, output),
mir::ConstValue::Slice { data, start: _, end: _ } => {
for &id in data.inner().provenance().ptrs().values() {
collect_alloc(tcx, id, output);
}

View File

@ -1,4 +1,7 @@
use rustc_middle::mir::interpret::{alloc_range, AllocRange, ConstValue, Pointer};
use rustc_middle::mir::{
interpret::{alloc_range, AllocRange, Pointer},
ConstValue,
};
use crate::{
rustc_smir::{Stable, Tables},

View File

@ -16,7 +16,6 @@
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
use rustc_metadata::rendered_const;
use rustc_middle::mir;
use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, TyCtxt};
use rustc_span::symbol::{kw, sym, Symbol};
use std::fmt::Write as _;
@ -282,8 +281,8 @@ pub(crate) fn print_evaluated_const(
let ty = tcx.type_of(def_id).instantiate_identity();
match (val, ty.kind()) {
(_, &ty::Ref(..)) => None,
(ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
(ConstValue::Scalar(_), _) => {
(mir::ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
(mir::ConstValue::Scalar(_), _) => {
let const_ = mir::ConstantKind::from_value(val, ty);
Some(print_const_with_custom_print_scalar(tcx, const_, underscores_and_type))
}
@ -326,14 +325,14 @@ fn print_const_with_custom_print_scalar<'tcx>(
// Use a slightly different format for integer types which always shows the actual value.
// For all other types, fallback to the original `pretty_print_const`.
match (ct, ct.ty().kind()) {
(mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Uint(ui)) => {
(mir::ConstantKind::Val(mir::ConstValue::Scalar(int), _), ty::Uint(ui)) => {
if underscores_and_type {
format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
} else {
int.to_string()
}
}
(mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Int(i)) => {
(mir::ConstantKind::Val(mir::ConstValue::Scalar(int), _), ty::Int(i)) => {
let ty = ct.ty();
let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
let data = int.assert_bits(size);

View File

@ -656,7 +656,7 @@ fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Cons
}
pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'tcx>) -> Option<Constant<'tcx>> {
use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::mir::ConstValue;
match result {
mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() {
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),

View File

@ -13,7 +13,7 @@
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::LateContext;
use rustc_middle::mir::interpret::{ConstValue, Scalar};
use rustc_middle::mir::{ConstValue, interpret::Scalar};
use rustc_middle::traits::EvaluationResult;
use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::{