diff --git a/Cargo.lock b/Cargo.lock index 4eafda94037c3..702d5e84234f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3821,6 +3821,7 @@ dependencies = [ "rustc_apfloat", "rustc_arena", "rustc_ast", + "rustc_const_eval", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 427340c333e5a..ec7f9d3e9eed3 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -227,16 +227,6 @@ pub(crate) fn codegen_const_value<'tcx>( .offset_i64(fx, i64::try_from(offset.bytes()).unwrap()), layout, ), - ConstValue::Slice { data, start, end } => { - let ptr = pointer_for_allocation(fx, data) - .offset_i64(fx, i64::try_from(start).unwrap()) - .get_addr(fx); - let len = fx - .bcx - .ins() - .iconst(fx.pointer_type, i64::try_from(end.checked_sub(start).unwrap()).unwrap()); - CValue::by_val_pair(ptr, len, layout) - } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 31c293d7c298e..3bb7557d6544b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -8,7 +8,7 @@ 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, ConstValue}; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::Ty; use rustc_target::abi::{self, Abi, Align, Size}; @@ -100,22 +100,6 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { OperandValue::Immediate(llval) } ConstValue::ZeroSized => return OperandRef::zero_sized(layout), - ConstValue::Slice { data, start, end } => { - let Abi::ScalarPair(a_scalar, _) = layout.abi else { - bug!("from_const: invalid ScalarPair layout: {:#?}", layout); - }; - let a = Scalar::from_pointer( - Pointer::new(bx.tcx().create_memory_alloc(data), Size::from_bytes(start)), - &bx.tcx(), - ); - let a_llval = bx.scalar_to_backend( - a, - a_scalar, - bx.scalar_pair_element_backend_type(layout, 0, true), - ); - let b_llval = bx.const_usize((end - start) as u64); - OperandValue::Pair(a_llval, b_llval) - } ConstValue::ByRef { alloc, offset } => { return Self::from_const_alloc(bx, layout, alloc, offset); } diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 8b8e8ff58e907..8c742ffddcf34 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -18,9 +18,9 @@ use super::{CompileTimeEvalContext, CompileTimeInterpreter}; use crate::errors; use crate::interpret::eval_nullary_intrinsic; use crate::interpret::{ - intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId, - Immediate, InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, - RefTracking, StackPopCleanup, + intern_const_alloc_recursive, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId, Immediate, + InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, + StackPopCleanup, }; // Returns a pointer to where the result lives @@ -108,7 +108,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>( /// type system. #[instrument(skip(ecx), level = "debug")] pub(super) fn op_to_const<'tcx>( - ecx: &CompileTimeEvalContext<'_, 'tcx>, + ecx: &mut CompileTimeEvalContext<'_, 'tcx>, op: &OpTy<'tcx>, ) -> ConstValue<'tcx> { // We do not have value optimizations for everything. @@ -143,12 +143,14 @@ pub(super) fn op_to_const<'tcx>( debug!(?immediate); + let tcx = ecx.tcx; + // We know `offset` is relative to the allocation, so we can use `into_parts`. let to_const_value = |mplace: &MPlaceTy<'_>| { debug!("to_const_value(mplace: {:?})", mplace); match mplace.ptr.into_parts() { (Some(alloc_id), offset) => { - let alloc = ecx.tcx.global_alloc(alloc_id).unwrap_memory(); + let alloc = tcx.global_alloc(alloc_id).unwrap_memory(); ConstValue::ByRef { alloc, offset } } (None, offset) => { @@ -169,24 +171,12 @@ pub(super) fn op_to_const<'tcx>( Right(imm) => match *imm { _ if imm.layout.is_zst() => ConstValue::ZeroSized, Immediate::Scalar(x) => ConstValue::Scalar(x), - Immediate::ScalarPair(a, b) => { - debug!("ScalarPair(a: {:?}, b: {:?})", a, b); - // We know `offset` is relative to the allocation, so we can use `into_parts`. - let (data, start) = match a.to_pointer(ecx).unwrap().into_parts() { - (Some(alloc_id), offset) => { - (ecx.tcx.global_alloc(alloc_id).unwrap_memory(), offset.bytes()) - } - (None, _offset) => ( - ecx.tcx.mk_const_alloc(Allocation::from_bytes_byte_aligned_immutable( - b"" as &[u8], - )), - 0, - ), - }; - let len = b.to_target_usize(ecx).unwrap(); - let start = start.try_into().unwrap(); - let len: usize = len.try_into().unwrap(); - ConstValue::Slice { data, start, end: start + len } + Immediate::ScalarPair(..) => { + let place = ecx.allocate(imm.layout, MemoryKind::Stack).unwrap(); + ecx.write_immediate(*imm, &place.into()).unwrap(); + intern_const_alloc_recursive(ecx, InternKind::Constant, &place).unwrap(); + + to_const_value(&place) } Immediate::Uninit => to_const_value(&op.assert_mem_place()), }, @@ -202,8 +192,7 @@ pub(crate) fn turn_into_const_value<'tcx>( let cid = key.value; let def_id = cid.instance.def.def_id(); let is_static = tcx.is_static(def_id); - // This is just accessing an already computed constant, so no need to check alignment here. - let ecx = mk_eval_cx( + let mut ecx = mk_eval_cx( tcx, tcx.def_span(key.value.instance.def_id()), key.param_env, @@ -220,7 +209,7 @@ pub(crate) fn turn_into_const_value<'tcx>( ); // Turn this into a proper constant. - op_to_const(&ecx, &mplace.into()) + op_to_const(&mut ecx, &mplace.into()) } #[instrument(skip(tcx), level = "debug")] diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 6e462d3a1e983..7a2bd08d62b61 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -2,10 +2,10 @@ use crate::errors::MaxNumNodesInConstErr; use crate::interpret::{ - intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, Scalar, + intern_const_alloc_recursive, ConstValue, ImmTy, InternKind, InterpCx, InterpResult, Scalar, }; use rustc_middle::mir; -use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId}; +use rustc_middle::mir::interpret::{ConstAllocation, EvalToValTreeResult, GlobalId}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{source_map::DUMMY_SP, symbol::Symbol}; @@ -91,7 +91,7 @@ pub(crate) fn try_destructure_mir_constant<'tcx>( val: mir::ConstantKind<'tcx>, ) -> InterpResult<'tcx, mir::DestructuredConstant<'tcx>> { trace!("destructure_mir_constant: {:?}", val); - let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); + let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); let op = ecx.eval_mir_constant(&val, None, None)?; // We go to `usize` as we cannot allocate anything bigger anyway. @@ -112,7 +112,7 @@ pub(crate) fn try_destructure_mir_constant<'tcx>( let fields_iter = (0..field_count) .map(|i| { let field_op = ecx.operand_field(&down, i)?; - let val = op_to_const(&ecx, &field_op); + let val = op_to_const(&mut ecx, &field_op); Ok(mir::ConstantKind::Val(val, field_op.layout.ty)) }) .collect::>>()?; @@ -120,3 +120,22 @@ pub(crate) fn try_destructure_mir_constant<'tcx>( Ok(mir::DestructuredConstant { variant, fields }) } + +/// Creates an `&[u8]` slice pointing to the given allocation +/// (covering it entirely, i.e., the length is the allocation size). +pub fn slice_for_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc: ConstAllocation<'tcx>) -> ConstValue<'tcx> { + let alloc_id = tcx.create_memory_alloc(alloc); + + let a = Scalar::from_pointer(alloc_id.into(), &tcx); + let b = Scalar::from_target_usize(alloc.0.size().bytes(), &tcx); + let imm = crate::interpret::Immediate::ScalarPair(a, b); + let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false); + + let layout = tcx + .layout_of( + ty::ParamEnv::reveal_all() + .and(tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_slice(tcx.types.u8))), + ) + .unwrap(); + op_to_const(&mut ecx, &ImmTy::from_immediate(imm, layout).into()) +} diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index b10f2e9f862db..eca4c1c1427b4 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -296,9 +296,9 @@ pub fn valtree_to_const_value<'tcx>( let imm = ImmTy::from_immediate(ref_place, tcx.layout_of(param_env_ty).unwrap()); - op_to_const(&ecx, &imm.into()) + op_to_const(&mut ecx, &imm.into()) } - _ => op_to_const(&ecx, &place.into()), + _ => op_to_const(&mut ecx, &place.into()), } } ty::Never diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 8f4cf23770e3d..901da9594c2e2 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -5,9 +5,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::mir::{ self, - interpret::{ - Allocation, ConstAllocation, ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar, - }, + interpret::{Allocation, ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar}, BinOp, NonDivergingIntrinsic, }; use rustc_middle::ty; @@ -17,6 +15,8 @@ use rustc_middle::ty::{Ty, TyCtxt}; use rustc_span::symbol::{sym, Symbol}; use rustc_target::abi::{Abi, Align, Primitive, Size}; +use crate::const_eval::slice_for_alloc; + use super::{ util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy, Pointer, @@ -44,10 +44,10 @@ fn numeric_intrinsic(name: Symbol, bits: u128, kind: Primitive) -> Scalar< } /// Directly returns an `Allocation` containing an absolute path representation of the given type. -pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> { +pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstValue<'tcx> { let path = crate::util::type_name(tcx, ty); let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes()); - tcx.mk_const_alloc(alloc) + slice_for_alloc(tcx, tcx.mk_const_alloc(alloc)) } /// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated @@ -63,8 +63,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( Ok(match name { sym::type_name => { ensure_monomorphic_enough(tcx, tp_ty)?; - let alloc = alloc_type_name(tcx, tp_ty); - ConstValue::Slice { data: alloc, start: 0, end: alloc.inner().len() } + alloc_type_name(tcx, tp_ty) } sym::needs_drop => { ensure_monomorphic_enough(tcx, tp_ty)?; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index e30af165501e5..1c4325b7d0cc7 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -657,19 +657,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } ConstValue::Scalar(x) => Operand::Immediate(adjust_scalar(x)?.into()), ConstValue::ZeroSized => Operand::Immediate(Immediate::Uninit), - 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( - self.tcx.create_memory_alloc(data), - Size::from_bytes(start), // offset: `start` - ); - Operand::Immediate(Immediate::new_slice( - Scalar::from_pointer(self.global_base_pointer(ptr)?, &*self.tcx), - u64::try_from(end.checked_sub(start).unwrap()).unwrap(), // len: `end - start` - self, - )) - } }; Ok(OpTy { op, layout, align: Some(layout.align.abi) }) } diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index b8030d9db13c5..abd2451d0912e 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -416,7 +416,8 @@ impl Allocation /// even when new allocations are pushed to the `HashMap`. `mem_copy_repeatedly` relies /// on that. #[inline] - pub fn get_bytes_unchecked(&self, range: AllocRange) -> &[u8] { + pub fn get_bytes_unchecked(&self, range: impl Into) -> &[u8] { + let range = range.into(); &self.bytes[range.start.bytes_usize()..range.end().bytes_usize()] } @@ -430,8 +431,9 @@ impl Allocation pub fn get_bytes_strip_provenance( &self, cx: &impl HasDataLayout, - range: AllocRange, + range: impl Into, ) -> AllocResult<&[u8]> { + let range = range.into(); self.init_mask.is_range_initialized(range).map_err(|uninit_range| { AllocError::InvalidUninitBytes(Some(UninitBytesAccess { access: range, @@ -455,8 +457,9 @@ impl Allocation pub fn get_bytes_mut( &mut self, cx: &impl HasDataLayout, - range: AllocRange, + range: impl Into, ) -> AllocResult<&mut [u8]> { + let range = range.into(); self.mark_init(range, true); self.provenance.clear(range, cx)?; @@ -467,8 +470,9 @@ impl Allocation pub fn get_bytes_mut_ptr( &mut self, cx: &impl HasDataLayout, - range: AllocRange, + range: impl Into, ) -> AllocResult<*mut [u8]> { + let range = range.into(); self.mark_init(range, true); self.provenance.clear(range, cx)?; @@ -482,7 +486,8 @@ impl Allocation /// Reading and writing. impl Allocation { /// Sets the init bit for the given range. - fn mark_init(&mut self, range: AllocRange, is_init: bool) { + fn mark_init(&mut self, range: impl Into, is_init: bool) { + let range = range.into(); if range.size.bytes() == 0 { return; } @@ -503,9 +508,10 @@ impl Allocation pub fn read_scalar( &self, cx: &impl HasDataLayout, - range: AllocRange, + range: impl Into, read_provenance: bool, ) -> AllocResult> { + let range = range.into(); // First and foremost, if anything is uninit, bail. if self.init_mask.is_range_initialized(range).is_err() { return Err(AllocError::InvalidUninitBytes(None)); @@ -565,9 +571,10 @@ impl Allocation pub fn write_scalar( &mut self, cx: &impl HasDataLayout, - range: AllocRange, + range: impl Into, val: Scalar, ) -> AllocResult { + let range = range.into(); assert!(self.mutability == Mutability::Mut); // `to_bits_or_ptr_internal` is the right method because we just want to store this data @@ -594,7 +601,12 @@ impl Allocation } /// Write "uninit" to the given memory range. - pub fn write_uninit(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { + pub fn write_uninit( + &mut self, + cx: &impl HasDataLayout, + range: impl Into, + ) -> AllocResult { + let range = range.into(); self.mark_init(range, false); self.provenance.clear(range, cx)?; return Ok(()); @@ -614,7 +626,13 @@ impl Allocation /// /// This is dangerous to use as it can violate internal `Allocation` invariants! /// It only exists to support an efficient implementation of `mem_copy_repeatedly`. - pub fn init_mask_apply_copy(&mut self, copy: InitCopy, range: AllocRange, repeat: u64) { + pub fn init_mask_apply_copy( + &mut self, + copy: InitCopy, + range: impl Into, + repeat: u64, + ) { + let range = range.into(); self.init_mask.apply_copy(copy, range, repeat) } } diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 2d2cfee1b213b..4feb575bed240 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -149,7 +149,7 @@ pub use self::error::{ ValidationErrorInfo, ValidationErrorKind, }; -pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar}; +pub use self::value::{ConstAlloc, ConstValue, Scalar}; pub use self::allocation::{ alloc_range, AllocBytes, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation, diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 0416411dfe14a..4d0ce0dcfefc9 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -7,12 +7,13 @@ use rustc_apfloat::{ Float, }; use rustc_macros::HashStable; +use rustc_span::Span; use rustc_target::abi::{HasDataLayout, Size}; use crate::ty::{ParamEnv, ScalarInt, Ty, TyCtxt}; use super::{ - AllocId, AllocRange, ConstAllocation, InterpResult, Pointer, PointerArithmetic, Provenance, + AllocId, ConstAllocation, InterpResult, Pointer, PointerArithmetic, Provenance, ScalarSizeMismatch, }; @@ -25,7 +26,7 @@ pub struct ConstAlloc<'tcx> { pub ty: Ty<'tcx>, } -/// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations for +/// Represents a constant value in Rust. `Scalar` is an optimization for /// array length computations, enum discriminants and the pattern matching logic. #[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash)] #[derive(HashStable, Lift)] @@ -38,9 +39,6 @@ pub enum ConstValue<'tcx> { /// Only used for ZSTs. ZeroSized, - /// Used only for `&[u8]` and `&str` - Slice { data: ConstAllocation<'tcx>, start: usize, end: usize }, - /// A value not represented/representable by `Scalar` or `Slice` ByRef { /// The backing memory of the value, may contain more memory than needed for just the value @@ -52,13 +50,46 @@ pub enum ConstValue<'tcx> { } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(ConstValue<'_>, 32); +static_assert_size!(ConstValue<'_>, 24); impl<'tcx> ConstValue<'tcx> { + pub fn expect_slice(self, tcx: TyCtxt<'tcx>, span: Span) -> &'tcx [u8] { + let ConstValue::ByRef { alloc, offset } = self else { + span_bug!(span, "invalid string constant: {self:?}") + }; + assert_eq!(offset, Size::ZERO); + let ptr_size = tcx.data_layout.pointer_size; + let (alloc_id, offset) = alloc + .0 + .read_scalar(&tcx, Size::ZERO..ptr_size, true) + .unwrap() + .to_pointer(&tcx) + .unwrap() + .into_parts(); + let len = alloc + .0 + .read_scalar(&tcx, ptr_size..(ptr_size * 2), true) + .unwrap() + .assert_bits(ptr_size); + match (alloc_id, len) { + (_, 0) => b"", + (None, _) => { + span_bug!(span, "string with {len} bytes but no alloc id") + } + (Some(alloc_id), _) => { + let alloc = tcx.global_alloc(alloc_id).unwrap_memory(); + alloc + .inner() + .get_bytes_strip_provenance(&tcx, offset..(offset + Size::from_bytes(len))) + .unwrap() + } + } + } + #[inline] pub fn try_to_scalar(&self) -> Option> { match *self { - ConstValue::ByRef { .. } | ConstValue::Slice { .. } | ConstValue::ZeroSized => None, + ConstValue::ByRef { .. } | ConstValue::ZeroSized => None, ConstValue::Scalar(val) => Some(val), } } @@ -323,6 +354,13 @@ impl Scalar { } impl<'tcx, Prov: Provenance> Scalar { + pub fn size(self) -> Size { + match self { + Scalar::Int(s) => s.size(), + Scalar::Ptr(_, size) => Size::from_bytes(size), + } + } + pub fn to_pointer(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, Pointer>> { match self .to_bits_or_ptr_internal(cx.pointer_size()) @@ -496,18 +534,3 @@ impl<'tcx, Prov: Provenance> Scalar { Ok(Double::from_bits(self.to_u64()?.into())) } } - -/// Gets the bytes of a constant slice value. -pub fn get_slice_bytes<'tcx>(cx: &impl HasDataLayout, val: ConstValue<'tcx>) -> &'tcx [u8] { - if let ConstValue::Slice { data, start, end } = val { - let len = end - start; - data.inner() - .get_bytes_strip_provenance( - cx, - AllocRange { start: Size::from_bytes(start), size: Size::from_bytes(len) }, - ) - .unwrap_or_else(|err| bug!("const slice is invalid: {:?}", err)) - } else { - bug!("expected const slice, but found another const value"); - } -} diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 6aa20dbed9294..cd912edc22ce5 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2259,6 +2259,12 @@ pub enum ConstantKind<'tcx> { Val(interpret::ConstValue<'tcx>, Ty<'tcx>), } +impl<'tcx> From> for ConstantKind<'tcx> { + fn from(v: ty::Const<'tcx>) -> Self { + Self::Ty(v) + } +} + impl<'tcx> Constant<'tcx> { pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option { match self.literal.try_to_scalar() { @@ -2842,33 +2848,21 @@ fn pretty_print_const_value<'tcx>( let u8_type = tcx.types.u8; match (ct, ty.kind()) { // Byte/string slices, printed as (byte) string literals. - (ConstValue::Slice { data, start, end }, ty::Ref(_, inner, _)) => { - match inner.kind() { - ty::Slice(t) => { - if *t == u8_type { - // The `inspect` here is okay since we checked the bounds, and `u8` carries - // no provenance (we have an active slice reference here). We don't use - // this result to affect interpreter execution. - let byte_str = data - .inner() - .inspect_with_uninit_and_ptr_outside_interpreter(start..end); - pretty_print_byte_str(fmt, byte_str)?; - return Ok(()); - } - } - ty::Str => { - // The `inspect` here is okay since we checked the bounds, and `str` carries - // no provenance (we have an active `str` reference here). We don't use this - // result to affect interpreter execution. - let slice = data - .inner() - .inspect_with_uninit_and_ptr_outside_interpreter(start..end); - fmt.write_str(&format!("{:?}", String::from_utf8_lossy(slice)))?; + (ConstValue::ByRef { .. }, ty::Ref(_, inner, _)) => match inner.kind() { + ty::Slice(t) => { + if *t == u8_type { + let byte_str = ct.expect_slice(tcx, DUMMY_SP); + pretty_print_byte_str(fmt, byte_str)?; return Ok(()); } - _ => {} } - } + ty::Str => { + let slice = ct.expect_slice(tcx, DUMMY_SP); + fmt.write_str(&format!("{:?}", String::from_utf8_lossy(slice)))?; + return Ok(()); + } + _ => {} + }, (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => { let n = n.kind().try_to_bits(tcx.data_layout.pointer_size).unwrap(); // cast is ok because we already checked for pointer size (32 or 64 bit) above diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index ffa7a5400d358..3ff6d2cdac7ca 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -464,7 +464,6 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { let fmt_val = |val: &ConstValue<'tcx>| match val { ConstValue::ZeroSized => "".to_string(), ConstValue::Scalar(s) => format!("Scalar({:?})", s), - ConstValue::Slice { .. } => "Slice(..)".to_string(), ConstValue::ByRef { .. } => "ByRef(..)".to_string(), }; @@ -700,7 +699,7 @@ pub fn write_mir_intro<'tcx>( /// allocations. pub fn write_allocations<'tcx>( tcx: TyCtxt<'tcx>, - body: &Body<'_>, + body: &Body<'tcx>, w: &mut dyn Write, ) -> io::Result<()> { fn alloc_ids_from_alloc( @@ -718,31 +717,35 @@ pub fn write_allocations<'tcx>( Either::Left(Either::Right(std::iter::empty())) } ConstValue::ZeroSized => Either::Left(Either::Right(std::iter::empty())), - ConstValue::ByRef { alloc, .. } | ConstValue::Slice { data: alloc, .. } => { - Either::Right(alloc_ids_from_alloc(alloc)) - } + ConstValue::ByRef { alloc, .. } => Either::Right(alloc_ids_from_alloc(alloc)), } } - struct CollectAllocIds(BTreeSet); + struct CollectAllocIds<'tcx> { + seen: BTreeSet, + tcx: TyCtxt<'tcx>, + } - impl<'tcx> Visitor<'tcx> for CollectAllocIds { + impl<'tcx> Visitor<'tcx> for CollectAllocIds<'tcx> { fn visit_constant(&mut self, c: &Constant<'tcx>, _: Location) { match c.literal { ConstantKind::Ty(_) | ConstantKind::Unevaluated(..) => {} - ConstantKind::Val(val, _) => { - self.0.extend(alloc_ids_from_const_val(val)); - } + ConstantKind::Val(val, _) => match *c.ty().kind() { + // Don't dump the content of string slices, they are rendered + // inline in MIR already. + ty::Ref(_, ty, _) if ty == self.tcx.types.str_ => {} + _ => self.seen.extend(alloc_ids_from_const_val(val)), + }, } } } - let mut visitor = CollectAllocIds(Default::default()); + let mut visitor = CollectAllocIds { seen: Default::default(), tcx }; visitor.visit_body(body); // `seen` contains all seen allocations, including the ones we have *not* printed yet. // The protocol is to first `insert` into `seen`, and only if that returns `true` // then push to `todo`. - let mut seen = visitor.0; + let mut seen = visitor.seen; let mut todo: Vec<_> = seen.iter().copied().collect(); while let Some(id) = todo.pop() { let mut write_allocation_track_relocs = diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index 58449ee9eb48d..7cb545920fdcf 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -22,6 +22,7 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } +rustc_const_eval = { path = "../rustc_const_eval" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ast = { path = "../rustc_ast" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 73d5eb6275082..ba9a7e8a055cf 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -2,6 +2,7 @@ use crate::build::{parse_float_into_constval, Builder}; use rustc_ast as ast; +use rustc_const_eval::const_eval::slice_for_alloc; use rustc_middle::mir; use rustc_middle::mir::interpret::{ Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar, @@ -51,9 +52,7 @@ pub fn as_constant_inner<'tcx>( let literal = match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) { Ok(c) => c, - Err(LitToConstError::Reported(guar)) => { - ConstantKind::Ty(tcx.const_error(ty, guar)) - } + Err(LitToConstError::Reported(guar)) => tcx.const_error(ty, guar).into(), Err(LitToConstError::TypeError) => { bug!("encountered type error in `lit_to_mir_constant`") } @@ -84,8 +83,7 @@ pub fn as_constant_inner<'tcx>( Constant { user_ty, span, literal } } ExprKind::ConstParam { param, def_id: _ } => { - let const_param = tcx.mk_const(ty::ConstKind::Param(param), expr.ty); - let literal = ConstantKind::Ty(const_param); + let literal = tcx.mk_const(ty::ConstKind::Param(param), expr.ty).into(); Constant { user_ty: None, span, literal } } @@ -132,15 +130,13 @@ fn lit_to_mir_constant<'tcx>( (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { let s = s.as_str(); let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes()); - let allocation = tcx.mk_const_alloc(allocation); - ConstValue::Slice { data: allocation, start: 0, end: s.len() } + slice_for_alloc(tcx, tcx.mk_const_alloc(allocation)) } (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Slice(_)) => { let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]); - let allocation = tcx.mk_const_alloc(allocation); - ConstValue::Slice { data: allocation, start: 0, end: data.len() } + slice_for_alloc(tcx, tcx.mk_const_alloc(allocation)) } (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => { let id = tcx.allocate_bytes(data); @@ -149,8 +145,7 @@ fn lit_to_mir_constant<'tcx>( (ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().c_str()) => { let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]); - let allocation = tcx.mk_const_alloc(allocation); - ConstValue::Slice { data: allocation, start: 0, end: data.len() } + slice_for_alloc(tcx, tcx.mk_const_alloc(allocation)) } (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => { ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1))) diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index a2e00d3bfc57d..f00fb21a24143 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -380,7 +380,7 @@ impl<'tcx> ConstToPat<'tcx> { ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() { // `&str` is represented as a valtree, let's keep using this // optimization for now. - ty::Str => PatKind::Constant { value: mir::ConstantKind::Ty(tcx.mk_const(cv, ty)) }, + ty::Str => PatKind::Constant { value: tcx.mk_const(cv, ty).into() }, // Backwards compatibility hack: support references to non-structural types, // but hard error if we aren't behind a double reference. We could just use // the fallback code path below, but that would allow *more* of this fishy @@ -439,7 +439,7 @@ impl<'tcx> ConstToPat<'tcx> { } }, ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => { - PatKind::Constant { value: mir::ConstantKind::Ty(tcx.mk_const(cv, ty)) } + PatKind::Constant { value: tcx.mk_const(cv, ty).into() } } ty::FnPtr(..) | ty::RawPtr(..) => unreachable!(), _ => { diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index 9df6d2f43ad57..9a158764d6cd4 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -812,9 +812,11 @@ impl<'tcx> Constructor<'tcx> { } } (Str(self_val), Str(other_val)) => { - // FIXME Once valtrees are available we can directly use the bytes - // in the `Str` variant of the valtree for the comparison here. - self_val == other_val + let get_const = |val| match val { + &mir::ConstantKind::Ty(ct) => ct, + _ => span_bug!(pcx.span, "str constant is not a valtree: {val:#?}"), + }; + get_const(self_val) == get_const(other_val) } (Slice(self_slice), Slice(other_slice)) => self_slice.is_covered_by(*other_slice), diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 8eeb055ed82d0..86bd80b73c2db 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -20,7 +20,7 @@ use rustc_index::Idx; use rustc_middle::mir::interpret::{ ConstValue, ErrorHandled, GlobalId, LitToConstError, LitToConstInput, Scalar, }; -use rustc_middle::mir::{self, ConstantKind, UserTypeProjection}; +use rustc_middle::mir::{self, UserTypeProjection}; use rustc_middle::mir::{BorrowKind, Mutability}; use rustc_middle::thir::{Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange}; use rustc_middle::ty::subst::{GenericArg, SubstsRef}; @@ -525,7 +525,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { .tcx .const_eval_global_id_for_typeck(param_env_reveal_all, cid, Some(span)) .map(|val| match val { - Some(valtree) => mir::ConstantKind::Ty(self.tcx.mk_const(valtree, ty)), + Some(valtree) => self.tcx.mk_const(valtree, ty).into(), None => mir::ConstantKind::Val( self.tcx .const_eval_global_id(param_env_reveal_all, cid, Some(span)) @@ -608,7 +608,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }; if let Some(lit_input) = lit_input { match tcx.at(expr.span).lit_to_const(lit_input) { - Ok(c) => return self.const_to_pat(ConstantKind::Ty(c), id, span, None).kind, + Ok(c) => return self.const_to_pat(c.into(), id, span, None).kind, // If an error occurred, ignore that it's a literal // and leave reporting the error up to const eval of // the unevaluated constant below. @@ -631,7 +631,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if let Ok(Some(valtree)) = self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span)) { - self.const_to_pat(ConstantKind::Ty(self.tcx.mk_const(valtree, ty)), id, span, None).kind + self.const_to_pat(self.tcx.mk_const(valtree, ty).into(), id, span, None).kind } else { // If that fails, convert it to an opaque constant pattern. match tcx.const_eval_resolve(self.param_env, uneval, None) { @@ -671,9 +671,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let lit_input = LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; match self.tcx.at(expr.span).lit_to_const(lit_input) { - Ok(constant) => { - self.const_to_pat(ConstantKind::Ty(constant), expr.hir_id, lit.span, None).kind - } + Ok(constant) => self.const_to_pat(constant.into(), expr.hir_id, lit.span, None).kind, Err(LitToConstError::Reported(_)) => PatKind::Wild, Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 4a5953c11492c..5adf186dd6733 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1383,7 +1383,7 @@ fn collect_const_value<'tcx>( ) { match value { ConstValue::Scalar(Scalar::Ptr(ptr, _size)) => collect_miri(tcx, ptr.provenance, output), - ConstValue::Slice { data: alloc, start: _, end: _ } | ConstValue::ByRef { alloc, .. } => { + ConstValue::ByRef { alloc, .. } => { for &id in alloc.inner().provenance().ptrs().values() { collect_miri(tcx, id, output); } diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index cc3183759ae7a..c794cdd5c6f9c 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -662,20 +662,16 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) - _ => None, } }, - mir::ConstantKind::Val(ConstValue::Slice { data, start, end }, _) => match result.ty().kind() { + mir::ConstantKind::Val(val @ ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() { ty::Ref(_, tam, _) => match tam.kind() { ty::Str => String::from_utf8( - data.inner() - .inspect_with_uninit_and_ptr_outside_interpreter(start..end) + val.expect_slice(tcx, rustc_span::DUMMY_SP) .to_owned(), ) .ok() .map(Constant::Str), _ => None, }, - _ => None, - }, - mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() { ty::Array(sub_type, len) => match sub_type.kind() { ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(tcx) { Some(len) => alloc diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir index 3797dbabb3c1b..ca05bf55c2d27 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &&[(Option, &[&str])]}; + _2 = const {alloc11: &&[(Option, &[&str])]}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,43 +17,43 @@ fn main() -> () { } } -alloc1 (static: FOO, size: 8, align: 4) { - ╾─alloc19─╼ 03 00 00 00 │ ╾──╼.... +alloc11 (static: FOO, size: 8, align: 4) { + ╾─alloc29─╼ 03 00 00 00 │ ╾──╼.... } -alloc19 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc6──╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc9──╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ....*...╾──╼.... +alloc29 (size: 48, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc16─╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc19─╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc24─╼ 03 00 00 00 │ ....*...╾──╼.... } -alloc6 (size: 0, align: 4) {} +alloc16 (size: 0, align: 4) {} -alloc9 (size: 16, align: 4) { - ╾─alloc10─╼ 03 00 00 00 ╾─alloc11─╼ 03 00 00 00 │ ╾──╼....╾──╼.... +alloc19 (size: 16, align: 4) { + ╾─alloc1──╼ 03 00 00 00 ╾─alloc3──╼ 03 00 00 00 │ ╾──╼....╾──╼.... } -alloc10 (size: 3, align: 1) { +alloc1 (size: 3, align: 1) { 66 6f 6f │ foo } -alloc11 (size: 3, align: 1) { +alloc3 (size: 3, align: 1) { 62 61 72 │ bar } -alloc14 (size: 24, align: 4) { - 0x00 │ ╾─alloc15─╼ 03 00 00 00 ╾─alloc16─╼ 03 00 00 00 │ ╾──╼....╾──╼.... - 0x10 │ ╾─alloc17─╼ 04 00 00 00 │ ╾──╼.... +alloc24 (size: 24, align: 4) { + 0x00 │ ╾─alloc5──╼ 03 00 00 00 ╾─alloc7──╼ 03 00 00 00 │ ╾──╼....╾──╼.... + 0x10 │ ╾─alloc9──╼ 04 00 00 00 │ ╾──╼.... } -alloc15 (size: 3, align: 1) { +alloc5 (size: 3, align: 1) { 6d 65 68 │ meh } -alloc16 (size: 3, align: 1) { +alloc7 (size: 3, align: 1) { 6d 6f 70 │ mop } -alloc17 (size: 4, align: 1) { +alloc9 (size: 4, align: 1) { 6d c3 b6 70 │ m..p } diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir index dc16c064009d7..d4a0d200458b6 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir @@ -8,7 +8,7 @@ fn main() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = const {alloc1: &&[(Option, &[&str])]}; + _2 = const {alloc11: &&[(Option, &[&str])]}; _1 = (*_2); StorageDead(_2); StorageDead(_1); @@ -17,47 +17,47 @@ fn main() -> () { } } -alloc1 (static: FOO, size: 16, align: 8) { - ╾───────alloc19───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +alloc11 (static: FOO, size: 16, align: 8) { + ╾───────alloc29───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc19 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc6────────╼ │ ....░░░░╾──────╼ +alloc29 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc16───────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────alloc9────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc14───────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────alloc19───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc24───────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } -alloc6 (size: 0, align: 8) {} +alloc16 (size: 0, align: 8) {} -alloc9 (size: 32, align: 8) { - 0x00 │ ╾───────alloc10───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾───────alloc11───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +alloc19 (size: 32, align: 8) { + 0x00 │ ╾───────alloc1────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾───────alloc3────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc10 (size: 3, align: 1) { +alloc1 (size: 3, align: 1) { 66 6f 6f │ foo } -alloc11 (size: 3, align: 1) { +alloc3 (size: 3, align: 1) { 62 61 72 │ bar } -alloc14 (size: 48, align: 8) { - 0x00 │ ╾───────alloc15───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾───────alloc16───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x20 │ ╾───────alloc17───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ +alloc24 (size: 48, align: 8) { + 0x00 │ ╾───────alloc5────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾───────alloc7────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x20 │ ╾───────alloc9────────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc15 (size: 3, align: 1) { +alloc5 (size: 3, align: 1) { 6d 65 68 │ meh } -alloc16 (size: 3, align: 1) { +alloc7 (size: 3, align: 1) { 6d 6f 70 │ mop } -alloc17 (size: 4, align: 1) { +alloc9 (size: 4, align: 1) { 6d c3 b6 70 │ m..p } diff --git a/tests/ui/const_prop/slice_numbering.rs b/tests/ui/const_prop/slice_numbering.rs new file mode 100644 index 0000000000000..8434648cb5f9c --- /dev/null +++ b/tests/ui/const_prop/slice_numbering.rs @@ -0,0 +1,16 @@ +#![feature(inline_const, strict_provenance)] + +// check-pass + +fn main() { + assert_eq!( + // as_ptr INside the `const{}` + (const { (unsafe { std::slice::from_raw_parts(3 as *const u8, 0) }).as_ptr() }), + std::ptr::invalid(3), + ); // PASSES + assert_eq!( + // as_ptr OUTside the `const{}` + (const { (unsafe { std::slice::from_raw_parts(7 as *const u8, 0) }) }).as_ptr(), + std::ptr::invalid(7), + ); // failed in https://github.com/rust-lang/rust/issues/105536 because 0x56229d3aa00b != 0x7 +} diff --git a/tests/ui/consts/const-eval/issue-49296.stderr b/tests/ui/consts/const-eval/issue-49296.stderr index cc4f1594c32ec..bcc4e95ae237b 100644 --- a/tests/ui/consts/const-eval/issue-49296.stderr +++ b/tests/ui/consts/const-eval/issue-49296.stderr @@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/issue-49296.rs:9:16 | LL | const X: u64 = *wat(42); - | ^^^^^^^^ pointer to alloc3 was dereferenced after this allocation got freed + | ^^^^^^^^ pointer to alloc7 was dereferenced after this allocation got freed error: aborting due to previous error diff --git a/tests/ui/consts/offset_from_ub.stderr b/tests/ui/consts/offset_from_ub.stderr index 97ff6efdd791c..fdc93c28e13a6 100644 --- a/tests/ui/consts/offset_from_ub.stderr +++ b/tests/ui/consts/offset_from_ub.stderr @@ -39,19 +39,19 @@ error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:53:14 | LL | unsafe { ptr_offset_from(end_ptr, start_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc17 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc18 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:62:14 | LL | unsafe { ptr_offset_from(start_ptr, end_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc20 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc21 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:70:14 | LL | unsafe { ptr_offset_from(end_ptr, end_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc23 has size 4, so pointer at offset 10 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc24 has size 4, so pointer at offset 10 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:79:14 diff --git a/tests/ui/consts/ptr_comparisons.stderr b/tests/ui/consts/ptr_comparisons.stderr index fea924d12e54e..a66a6d32829f5 100644 --- a/tests/ui/consts/ptr_comparisons.stderr +++ b/tests/ui/consts/ptr_comparisons.stderr @@ -1,7 +1,7 @@ error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds + = note: out-of-bounds pointer arithmetic: alloc15 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds | note: inside `ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -15,7 +15,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/ptr_comparisons.rs:53:33 | LL | unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: alloc3 has size $WORD, so pointer to 1000 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: alloc15 has size $WORD, so pointer to 1000 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/ptr_comparisons.rs:57:27