Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 41d92c4

Browse files
committedJun 20, 2023
Remove ConstValue::Slice
1 parent 4d8eaca commit 41d92c4

File tree

23 files changed

+194
-198
lines changed

23 files changed

+194
-198
lines changed
 

‎Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3821,6 +3821,7 @@ dependencies = [
38213821
"rustc_apfloat",
38223822
"rustc_arena",
38233823
"rustc_ast",
3824+
"rustc_const_eval",
38243825
"rustc_data_structures",
38253826
"rustc_errors",
38263827
"rustc_fluent_macro",

‎compiler/rustc_codegen_cranelift/src/constant.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -227,16 +227,6 @@ pub(crate) fn codegen_const_value<'tcx>(
227227
.offset_i64(fx, i64::try_from(offset.bytes()).unwrap()),
228228
layout,
229229
),
230-
ConstValue::Slice { data, start, end } => {
231-
let ptr = pointer_for_allocation(fx, data)
232-
.offset_i64(fx, i64::try_from(start).unwrap())
233-
.get_addr(fx);
234-
let len = fx
235-
.bcx
236-
.ins()
237-
.iconst(fx.pointer_type, i64::try_from(end.checked_sub(start).unwrap()).unwrap());
238-
CValue::by_val_pair(ptr, len, layout)
239-
}
240230
}
241231
}
242232

‎compiler/rustc_codegen_ssa/src/mir/operand.rs

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::traits::*;
88
use crate::MemFlags;
99

1010
use rustc_middle::mir;
11-
use rustc_middle::mir::interpret::{alloc_range, ConstValue, Pointer, Scalar};
11+
use rustc_middle::mir::interpret::{alloc_range, ConstValue};
1212
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
1313
use rustc_middle::ty::Ty;
1414
use rustc_target::abi::{self, Abi, Align, Size};
@@ -100,22 +100,6 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
100100
OperandValue::Immediate(llval)
101101
}
102102
ConstValue::ZeroSized => return OperandRef::zero_sized(layout),
103-
ConstValue::Slice { data, start, end } => {
104-
let Abi::ScalarPair(a_scalar, _) = layout.abi else {
105-
bug!("from_const: invalid ScalarPair layout: {:#?}", layout);
106-
};
107-
let a = Scalar::from_pointer(
108-
Pointer::new(bx.tcx().create_memory_alloc(data), Size::from_bytes(start)),
109-
&bx.tcx(),
110-
);
111-
let a_llval = bx.scalar_to_backend(
112-
a,
113-
a_scalar,
114-
bx.scalar_pair_element_backend_type(layout, 0, true),
115-
);
116-
let b_llval = bx.const_usize((end - start) as u64);
117-
OperandValue::Pair(a_llval, b_llval)
118-
}
119103
ConstValue::ByRef { alloc, offset } => {
120104
return Self::from_const_alloc(bx, layout, alloc, offset);
121105
}

‎compiler/rustc_const_eval/src/const_eval/eval_queries.rs

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ use super::{CompileTimeEvalContext, CompileTimeInterpreter};
1818
use crate::errors;
1919
use crate::interpret::eval_nullary_intrinsic;
2020
use crate::interpret::{
21-
intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId,
22-
Immediate, InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy,
23-
RefTracking, StackPopCleanup,
21+
intern_const_alloc_recursive, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId, Immediate,
22+
InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking,
23+
StackPopCleanup,
2424
};
2525

2626
// Returns a pointer to where the result lives
@@ -108,7 +108,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
108108
/// type system.
109109
#[instrument(skip(ecx), level = "debug")]
110110
pub(super) fn op_to_const<'tcx>(
111-
ecx: &CompileTimeEvalContext<'_, 'tcx>,
111+
ecx: &mut CompileTimeEvalContext<'_, 'tcx>,
112112
op: &OpTy<'tcx>,
113113
) -> ConstValue<'tcx> {
114114
// We do not have value optimizations for everything.
@@ -143,12 +143,14 @@ pub(super) fn op_to_const<'tcx>(
143143

144144
debug!(?immediate);
145145

146+
let tcx = ecx.tcx;
147+
146148
// We know `offset` is relative to the allocation, so we can use `into_parts`.
147149
let to_const_value = |mplace: &MPlaceTy<'_>| {
148150
debug!("to_const_value(mplace: {:?})", mplace);
149151
match mplace.ptr.into_parts() {
150152
(Some(alloc_id), offset) => {
151-
let alloc = ecx.tcx.global_alloc(alloc_id).unwrap_memory();
153+
let alloc = tcx.global_alloc(alloc_id).unwrap_memory();
152154
ConstValue::ByRef { alloc, offset }
153155
}
154156
(None, offset) => {
@@ -169,24 +171,12 @@ pub(super) fn op_to_const<'tcx>(
169171
Right(imm) => match *imm {
170172
_ if imm.layout.is_zst() => ConstValue::ZeroSized,
171173
Immediate::Scalar(x) => ConstValue::Scalar(x),
172-
Immediate::ScalarPair(a, b) => {
173-
debug!("ScalarPair(a: {:?}, b: {:?})", a, b);
174-
// We know `offset` is relative to the allocation, so we can use `into_parts`.
175-
let (data, start) = match a.to_pointer(ecx).unwrap().into_parts() {
176-
(Some(alloc_id), offset) => {
177-
(ecx.tcx.global_alloc(alloc_id).unwrap_memory(), offset.bytes())
178-
}
179-
(None, _offset) => (
180-
ecx.tcx.mk_const_alloc(Allocation::from_bytes_byte_aligned_immutable(
181-
b"" as &[u8],
182-
)),
183-
0,
184-
),
185-
};
186-
let len = b.to_target_usize(ecx).unwrap();
187-
let start = start.try_into().unwrap();
188-
let len: usize = len.try_into().unwrap();
189-
ConstValue::Slice { data, start, end: start + len }
174+
Immediate::ScalarPair(..) => {
175+
let place = ecx.allocate(imm.layout, MemoryKind::Stack).unwrap();
176+
ecx.write_immediate(*imm, &place.into()).unwrap();
177+
intern_const_alloc_recursive(ecx, InternKind::Constant, &place).unwrap();
178+
179+
to_const_value(&place)
190180
}
191181
Immediate::Uninit => to_const_value(&op.assert_mem_place()),
192182
},
@@ -202,8 +192,7 @@ pub(crate) fn turn_into_const_value<'tcx>(
202192
let cid = key.value;
203193
let def_id = cid.instance.def.def_id();
204194
let is_static = tcx.is_static(def_id);
205-
// This is just accessing an already computed constant, so no need to check alignment here.
206-
let ecx = mk_eval_cx(
195+
let mut ecx = mk_eval_cx(
207196
tcx,
208197
tcx.def_span(key.value.instance.def_id()),
209198
key.param_env,
@@ -220,7 +209,7 @@ pub(crate) fn turn_into_const_value<'tcx>(
220209
);
221210

222211
// Turn this into a proper constant.
223-
op_to_const(&ecx, &mplace.into())
212+
op_to_const(&mut ecx, &mplace.into())
224213
}
225214

226215
#[instrument(skip(tcx), level = "debug")]

‎compiler/rustc_const_eval/src/const_eval/mod.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
use crate::errors::MaxNumNodesInConstErr;
44
use crate::interpret::{
5-
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, Scalar,
5+
intern_const_alloc_recursive, ConstValue, ImmTy, InternKind, InterpCx, InterpResult, Scalar,
66
};
77
use rustc_middle::mir;
8-
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
8+
use rustc_middle::mir::interpret::{ConstAllocation, EvalToValTreeResult, GlobalId};
99
use rustc_middle::ty::{self, TyCtxt};
1010
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
1111

@@ -91,7 +91,7 @@ pub(crate) fn try_destructure_mir_constant<'tcx>(
9191
val: mir::ConstantKind<'tcx>,
9292
) -> InterpResult<'tcx, mir::DestructuredConstant<'tcx>> {
9393
trace!("destructure_mir_constant: {:?}", val);
94-
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
94+
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
9595
let op = ecx.eval_mir_constant(&val, None, None)?;
9696

9797
// We go to `usize` as we cannot allocate anything bigger anyway.
@@ -112,11 +112,30 @@ pub(crate) fn try_destructure_mir_constant<'tcx>(
112112
let fields_iter = (0..field_count)
113113
.map(|i| {
114114
let field_op = ecx.operand_field(&down, i)?;
115-
let val = op_to_const(&ecx, &field_op);
115+
let val = op_to_const(&mut ecx, &field_op);
116116
Ok(mir::ConstantKind::Val(val, field_op.layout.ty))
117117
})
118118
.collect::<InterpResult<'tcx, Vec<_>>>()?;
119119
let fields = tcx.arena.alloc_from_iter(fields_iter);
120120

121121
Ok(mir::DestructuredConstant { variant, fields })
122122
}
123+
124+
/// Creates an `&[u8]` slice pointing to the given allocation
125+
/// (covering it entirely, i.e., the length is the allocation size).
126+
pub fn slice_for_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc: ConstAllocation<'tcx>) -> ConstValue<'tcx> {
127+
let alloc_id = tcx.create_memory_alloc(alloc);
128+
129+
let a = Scalar::from_pointer(alloc_id.into(), &tcx);
130+
let b = Scalar::from_target_usize(alloc.0.size().bytes(), &tcx);
131+
let imm = crate::interpret::Immediate::ScalarPair(a, b);
132+
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);
133+
134+
let layout = tcx
135+
.layout_of(
136+
ty::ParamEnv::reveal_all()
137+
.and(tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_slice(tcx.types.u8))),
138+
)
139+
.unwrap();
140+
op_to_const(&mut ecx, &ImmTy::from_immediate(imm, layout).into())
141+
}

‎compiler/rustc_const_eval/src/const_eval/valtrees.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,9 @@ pub fn valtree_to_const_value<'tcx>(
296296
let imm =
297297
ImmTy::from_immediate(ref_place, tcx.layout_of(param_env_ty).unwrap());
298298

299-
op_to_const(&ecx, &imm.into())
299+
op_to_const(&mut ecx, &imm.into())
300300
}
301-
_ => op_to_const(&ecx, &place.into()),
301+
_ => op_to_const(&mut ecx, &place.into()),
302302
}
303303
}
304304
ty::Never

‎compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
use rustc_hir::def_id::DefId;
66
use rustc_middle::mir::{
77
self,
8-
interpret::{
9-
Allocation, ConstAllocation, ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar,
10-
},
8+
interpret::{Allocation, ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar},
119
BinOp, NonDivergingIntrinsic,
1210
};
1311
use rustc_middle::ty;
@@ -17,6 +15,8 @@ use rustc_middle::ty::{Ty, TyCtxt};
1715
use rustc_span::symbol::{sym, Symbol};
1816
use rustc_target::abi::{Abi, Align, Primitive, Size};
1917

18+
use crate::const_eval::slice_for_alloc;
19+
2020
use super::{
2121
util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy,
2222
Pointer,
@@ -44,10 +44,10 @@ fn numeric_intrinsic<Prov>(name: Symbol, bits: u128, kind: Primitive) -> Scalar<
4444
}
4545

4646
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
47-
pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> {
47+
pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstValue<'tcx> {
4848
let path = crate::util::type_name(tcx, ty);
4949
let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes());
50-
tcx.mk_const_alloc(alloc)
50+
slice_for_alloc(tcx, tcx.mk_const_alloc(alloc))
5151
}
5252

5353
/// 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>(
6363
Ok(match name {
6464
sym::type_name => {
6565
ensure_monomorphic_enough(tcx, tp_ty)?;
66-
let alloc = alloc_type_name(tcx, tp_ty);
67-
ConstValue::Slice { data: alloc, start: 0, end: alloc.inner().len() }
66+
alloc_type_name(tcx, tp_ty)
6867
}
6968
sym::needs_drop => {
7069
ensure_monomorphic_enough(tcx, tp_ty)?;

‎compiler/rustc_const_eval/src/interpret/operand.rs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -657,19 +657,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
657657
}
658658
ConstValue::Scalar(x) => Operand::Immediate(adjust_scalar(x)?.into()),
659659
ConstValue::ZeroSized => Operand::Immediate(Immediate::Uninit),
660-
ConstValue::Slice { data, start, end } => {
661-
// We rely on mutability being set correctly in `data` to prevent writes
662-
// where none should happen.
663-
let ptr = Pointer::new(
664-
self.tcx.create_memory_alloc(data),
665-
Size::from_bytes(start), // offset: `start`
666-
);
667-
Operand::Immediate(Immediate::new_slice(
668-
Scalar::from_pointer(self.global_base_pointer(ptr)?, &*self.tcx),
669-
u64::try_from(end.checked_sub(start).unwrap()).unwrap(), // len: `end - start`
670-
self,
671-
))
672-
}
673660
};
674661
Ok(OpTy { op, layout, align: Some(layout.align.abi) })
675662
}

‎compiler/rustc_middle/src/mir/interpret/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ pub use self::error::{
149149
ValidationErrorInfo, ValidationErrorKind,
150150
};
151151

152-
pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar};
152+
pub use self::value::{ConstAlloc, ConstValue, Scalar};
153153

154154
pub use self::allocation::{
155155
alloc_range, AllocBytes, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation,

‎compiler/rustc_middle/src/mir/interpret/value.rs

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ use rustc_apfloat::{
77
Float,
88
};
99
use rustc_macros::HashStable;
10+
use rustc_span::Span;
1011
use rustc_target::abi::{HasDataLayout, Size};
1112

1213
use crate::ty::{ParamEnv, ScalarInt, Ty, TyCtxt};
1314

1415
use super::{
15-
AllocId, AllocRange, ConstAllocation, InterpResult, Pointer, PointerArithmetic, Provenance,
16+
AllocId, ConstAllocation, InterpResult, Pointer, PointerArithmetic, Provenance,
1617
ScalarSizeMismatch,
1718
};
1819

@@ -25,7 +26,7 @@ pub struct ConstAlloc<'tcx> {
2526
pub ty: Ty<'tcx>,
2627
}
2728

28-
/// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations for
29+
/// Represents a constant value in Rust. `Scalar` is an optimization for
2930
/// array length computations, enum discriminants and the pattern matching logic.
3031
#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash)]
3132
#[derive(HashStable, Lift)]
@@ -38,9 +39,6 @@ pub enum ConstValue<'tcx> {
3839
/// Only used for ZSTs.
3940
ZeroSized,
4041

41-
/// Used only for `&[u8]` and `&str`
42-
Slice { data: ConstAllocation<'tcx>, start: usize, end: usize },
43-
4442
/// A value not represented/representable by `Scalar` or `Slice`
4543
ByRef {
4644
/// The backing memory of the value, may contain more memory than needed for just the value
@@ -52,13 +50,46 @@ pub enum ConstValue<'tcx> {
5250
}
5351

5452
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
55-
static_assert_size!(ConstValue<'_>, 32);
53+
static_assert_size!(ConstValue<'_>, 24);
5654

5755
impl<'tcx> ConstValue<'tcx> {
56+
pub fn expect_slice(self, tcx: TyCtxt<'tcx>, span: Span) -> &'tcx [u8] {
57+
let ConstValue::ByRef { alloc, offset } = self else {
58+
span_bug!(span, "invalid string constant: {self:?}")
59+
};
60+
assert_eq!(offset, Size::ZERO);
61+
let ptr_size = tcx.data_layout.pointer_size;
62+
let (alloc_id, offset) = alloc
63+
.0
64+
.read_scalar(&tcx, Size::ZERO..ptr_size, true)
65+
.unwrap()
66+
.to_pointer(&tcx)
67+
.unwrap()
68+
.into_parts();
69+
let len = alloc
70+
.0
71+
.read_scalar(&tcx, ptr_size..(ptr_size * 2), true)
72+
.unwrap()
73+
.assert_bits(ptr_size);
74+
match (alloc_id, len) {
75+
(_, 0) => b"",
76+
(None, _) => {
77+
span_bug!(span, "string with {len} bytes but no alloc id")
78+
}
79+
(Some(alloc_id), _) => {
80+
let alloc = tcx.global_alloc(alloc_id).unwrap_memory();
81+
alloc
82+
.inner()
83+
.get_bytes_strip_provenance(&tcx, offset..(offset + Size::from_bytes(len)))
84+
.unwrap()
85+
}
86+
}
87+
}
88+
5889
#[inline]
5990
pub fn try_to_scalar(&self) -> Option<Scalar<AllocId>> {
6091
match *self {
61-
ConstValue::ByRef { .. } | ConstValue::Slice { .. } | ConstValue::ZeroSized => None,
92+
ConstValue::ByRef { .. } | ConstValue::ZeroSized => None,
6293
ConstValue::Scalar(val) => Some(val),
6394
}
6495
}
@@ -323,6 +354,13 @@ impl<Prov> Scalar<Prov> {
323354
}
324355

325356
impl<'tcx, Prov: Provenance> Scalar<Prov> {
357+
pub fn size(self) -> Size {
358+
match self {
359+
Scalar::Int(s) => s.size(),
360+
Scalar::Ptr(_, size) => Size::from_bytes(size),
361+
}
362+
}
363+
326364
pub fn to_pointer(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, Pointer<Option<Prov>>> {
327365
match self
328366
.to_bits_or_ptr_internal(cx.pointer_size())
@@ -496,18 +534,3 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
496534
Ok(Double::from_bits(self.to_u64()?.into()))
497535
}
498536
}
499-
500-
/// Gets the bytes of a constant slice value.
501-
pub fn get_slice_bytes<'tcx>(cx: &impl HasDataLayout, val: ConstValue<'tcx>) -> &'tcx [u8] {
502-
if let ConstValue::Slice { data, start, end } = val {
503-
let len = end - start;
504-
data.inner()
505-
.get_bytes_strip_provenance(
506-
cx,
507-
AllocRange { start: Size::from_bytes(start), size: Size::from_bytes(len) },
508-
)
509-
.unwrap_or_else(|err| bug!("const slice is invalid: {:?}", err))
510-
} else {
511-
bug!("expected const slice, but found another const value");
512-
}
513-
}

‎compiler/rustc_middle/src/mir/mod.rs

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2842,33 +2842,21 @@ fn pretty_print_const_value<'tcx>(
28422842
let u8_type = tcx.types.u8;
28432843
match (ct, ty.kind()) {
28442844
// Byte/string slices, printed as (byte) string literals.
2845-
(ConstValue::Slice { data, start, end }, ty::Ref(_, inner, _)) => {
2846-
match inner.kind() {
2847-
ty::Slice(t) => {
2848-
if *t == u8_type {
2849-
// The `inspect` here is okay since we checked the bounds, and `u8` carries
2850-
// no provenance (we have an active slice reference here). We don't use
2851-
// this result to affect interpreter execution.
2852-
let byte_str = data
2853-
.inner()
2854-
.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
2855-
pretty_print_byte_str(fmt, byte_str)?;
2856-
return Ok(());
2857-
}
2858-
}
2859-
ty::Str => {
2860-
// The `inspect` here is okay since we checked the bounds, and `str` carries
2861-
// no provenance (we have an active `str` reference here). We don't use this
2862-
// result to affect interpreter execution.
2863-
let slice = data
2864-
.inner()
2865-
.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
2866-
fmt.write_str(&format!("{:?}", String::from_utf8_lossy(slice)))?;
2845+
(ConstValue::ByRef { .. }, ty::Ref(_, inner, _)) => match inner.kind() {
2846+
ty::Slice(t) => {
2847+
if *t == u8_type {
2848+
let byte_str = ct.expect_slice(tcx, DUMMY_SP);
2849+
pretty_print_byte_str(fmt, byte_str)?;
28672850
return Ok(());
28682851
}
2869-
_ => {}
28702852
}
2871-
}
2853+
ty::Str => {
2854+
let slice = ct.expect_slice(tcx, DUMMY_SP);
2855+
fmt.write_str(&format!("{:?}", String::from_utf8_lossy(slice)))?;
2856+
return Ok(());
2857+
}
2858+
_ => {}
2859+
},
28722860
(ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
28732861
let n = n.kind().try_to_bits(tcx.data_layout.pointer_size).unwrap();
28742862
// cast is ok because we already checked for pointer size (32 or 64 bit) above

‎compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,6 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
464464
let fmt_val = |val: &ConstValue<'tcx>| match val {
465465
ConstValue::ZeroSized => "<ZST>".to_string(),
466466
ConstValue::Scalar(s) => format!("Scalar({:?})", s),
467-
ConstValue::Slice { .. } => "Slice(..)".to_string(),
468467
ConstValue::ByRef { .. } => "ByRef(..)".to_string(),
469468
};
470469

@@ -700,7 +699,7 @@ pub fn write_mir_intro<'tcx>(
700699
/// allocations.
701700
pub fn write_allocations<'tcx>(
702701
tcx: TyCtxt<'tcx>,
703-
body: &Body<'_>,
702+
body: &Body<'tcx>,
704703
w: &mut dyn Write,
705704
) -> io::Result<()> {
706705
fn alloc_ids_from_alloc(
@@ -718,31 +717,35 @@ pub fn write_allocations<'tcx>(
718717
Either::Left(Either::Right(std::iter::empty()))
719718
}
720719
ConstValue::ZeroSized => Either::Left(Either::Right(std::iter::empty())),
721-
ConstValue::ByRef { alloc, .. } | ConstValue::Slice { data: alloc, .. } => {
722-
Either::Right(alloc_ids_from_alloc(alloc))
723-
}
720+
ConstValue::ByRef { alloc, .. } => Either::Right(alloc_ids_from_alloc(alloc)),
724721
}
725722
}
726-
struct CollectAllocIds(BTreeSet<AllocId>);
723+
struct CollectAllocIds<'tcx> {
724+
seen: BTreeSet<AllocId>,
725+
tcx: TyCtxt<'tcx>,
726+
}
727727

728-
impl<'tcx> Visitor<'tcx> for CollectAllocIds {
728+
impl<'tcx> Visitor<'tcx> for CollectAllocIds<'tcx> {
729729
fn visit_constant(&mut self, c: &Constant<'tcx>, _: Location) {
730730
match c.literal {
731731
ConstantKind::Ty(_) | ConstantKind::Unevaluated(..) => {}
732-
ConstantKind::Val(val, _) => {
733-
self.0.extend(alloc_ids_from_const_val(val));
734-
}
732+
ConstantKind::Val(val, _) => match *c.ty().kind() {
733+
// Don't dump the content of string slices, they are rendered
734+
// inline in MIR already.
735+
ty::Ref(_, ty, _) if ty == self.tcx.types.str_ => {}
736+
_ => self.seen.extend(alloc_ids_from_const_val(val)),
737+
},
735738
}
736739
}
737740
}
738741

739-
let mut visitor = CollectAllocIds(Default::default());
742+
let mut visitor = CollectAllocIds { seen: Default::default(), tcx };
740743
visitor.visit_body(body);
741744

742745
// `seen` contains all seen allocations, including the ones we have *not* printed yet.
743746
// The protocol is to first `insert` into `seen`, and only if that returns `true`
744747
// then push to `todo`.
745-
let mut seen = visitor.0;
748+
let mut seen = visitor.seen;
746749
let mut todo: Vec<_> = seen.iter().copied().collect();
747750
while let Some(id) = todo.pop() {
748751
let mut write_allocation_track_relocs =

‎compiler/rustc_mir_build/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ rustc_serialize = { path = "../rustc_serialize" }
2222
rustc_session = { path = "../rustc_session" }
2323
rustc_span = { path = "../rustc_span" }
2424
rustc_target = { path = "../rustc_target" }
25+
rustc_const_eval = { path = "../rustc_const_eval" }
2526
rustc_trait_selection = { path = "../rustc_trait_selection" }
2627
rustc_ast = { path = "../rustc_ast" }
2728
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }

‎compiler/rustc_mir_build/src/build/expr/as_constant.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use crate::build::{parse_float_into_constval, Builder};
44
use rustc_ast as ast;
5+
use rustc_const_eval::const_eval::slice_for_alloc;
56
use rustc_middle::mir;
67
use rustc_middle::mir::interpret::{
78
Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
@@ -132,15 +133,13 @@ fn lit_to_mir_constant<'tcx>(
132133
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
133134
let s = s.as_str();
134135
let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
135-
let allocation = tcx.mk_const_alloc(allocation);
136-
ConstValue::Slice { data: allocation, start: 0, end: s.len() }
136+
slice_for_alloc(tcx, tcx.mk_const_alloc(allocation))
137137
}
138138
(ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
139139
if matches!(inner_ty.kind(), ty::Slice(_)) =>
140140
{
141141
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
142-
let allocation = tcx.mk_const_alloc(allocation);
143-
ConstValue::Slice { data: allocation, start: 0, end: data.len() }
142+
slice_for_alloc(tcx, tcx.mk_const_alloc(allocation))
144143
}
145144
(ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
146145
let id = tcx.allocate_bytes(data);
@@ -149,8 +148,7 @@ fn lit_to_mir_constant<'tcx>(
149148
(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()) =>
150149
{
151150
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
152-
let allocation = tcx.mk_const_alloc(allocation);
153-
ConstValue::Slice { data: allocation, start: 0, end: data.len() }
151+
slice_for_alloc(tcx, tcx.mk_const_alloc(allocation))
154152
}
155153
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
156154
ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))

‎compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -812,9 +812,11 @@ impl<'tcx> Constructor<'tcx> {
812812
}
813813
}
814814
(Str(self_val), Str(other_val)) => {
815-
// FIXME Once valtrees are available we can directly use the bytes
816-
// in the `Str` variant of the valtree for the comparison here.
817-
self_val == other_val
815+
let get_const = |val| match val {
816+
&mir::ConstantKind::Ty(ct) => ct,
817+
_ => span_bug!(pcx.span, "str constant is not a valtree: {val:#?}"),
818+
};
819+
get_const(self_val) == get_const(other_val)
818820
}
819821
(Slice(self_slice), Slice(other_slice)) => self_slice.is_covered_by(*other_slice),
820822

‎compiler/rustc_monomorphize/src/collector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1383,7 +1383,7 @@ fn collect_const_value<'tcx>(
13831383
) {
13841384
match value {
13851385
ConstValue::Scalar(Scalar::Ptr(ptr, _size)) => collect_miri(tcx, ptr.provenance, output),
1386-
ConstValue::Slice { data: alloc, start: _, end: _ } | ConstValue::ByRef { alloc, .. } => {
1386+
ConstValue::ByRef { alloc, .. } => {
13871387
for &id in alloc.inner().provenance().ptrs().values() {
13881388
collect_miri(tcx, id, output);
13891389
}

‎src/tools/clippy/clippy_utils/src/consts.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -662,20 +662,16 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -
662662
_ => None,
663663
}
664664
},
665-
mir::ConstantKind::Val(ConstValue::Slice { data, start, end }, _) => match result.ty().kind() {
665+
mir::ConstantKind::Val(val @ ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() {
666666
ty::Ref(_, tam, _) => match tam.kind() {
667667
ty::Str => String::from_utf8(
668-
data.inner()
669-
.inspect_with_uninit_and_ptr_outside_interpreter(start..end)
668+
val.expect_slice(tcx, rustc_span::DUMMY_SP)
670669
.to_owned(),
671670
)
672671
.ok()
673672
.map(Constant::Str),
674673
_ => None,
675674
},
676-
_ => None,
677-
},
678-
mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() {
679675
ty::Array(sub_type, len) => match sub_type.kind() {
680676
ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(tcx) {
681677
Some(len) => alloc

‎tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn main() -> () {
88
bb0: {
99
StorageLive(_1);
1010
StorageLive(_2);
11-
_2 = const {alloc1: &&[(Option<i32>, &[&str])]};
11+
_2 = const {alloc11: &&[(Option<i32>, &[&str])]};
1212
_1 = (*_2);
1313
StorageDead(_2);
1414
StorageDead(_1);
@@ -17,43 +17,43 @@ fn main() -> () {
1717
}
1818
}
1919

20-
alloc1 (static: FOO, size: 8, align: 4) {
21-
╾─alloc19─╼ 03 00 00 00 │ ╾──╼....
20+
alloc11 (static: FOO, size: 8, align: 4) {
21+
╾─alloc29─╼ 03 00 00 00 │ ╾──╼....
2222
}
2323

24-
alloc19 (size: 48, align: 4) {
25-
0x0000 00 00 00 __ __ __ __ ╾─alloc6──╼ 00 00 00 00 │ ....░░░░╾──╼....
26-
0x1000 00 00 00 __ __ __ __ ╾─alloc9──╼ 02 00 00 00 │ ....░░░░╾──╼....
27-
0x2001 00 00 00 2a 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ....*...╾──╼....
24+
alloc29 (size: 48, align: 4) {
25+
0x0000 00 00 00 __ __ __ __ ╾─alloc16─╼ 00 00 00 00 │ ....░░░░╾──╼....
26+
0x1000 00 00 00 __ __ __ __ ╾─alloc19─╼ 02 00 00 00 │ ....░░░░╾──╼....
27+
0x2001 00 00 00 2a 00 00 00 ╾─alloc24─╼ 03 00 00 00 │ ....*...╾──╼....
2828
}
2929

30-
alloc6 (size: 0, align: 4) {}
30+
alloc16 (size: 0, align: 4) {}
3131

32-
alloc9 (size: 16, align: 4) {
33-
╾─alloc10─03 00 00 00 ╾─alloc11─╼ 03 00 00 00 │ ╾──╼....╾──╼....
32+
alloc19 (size: 16, align: 4) {
33+
╾─alloc1──03 00 00 00 ╾─alloc3──╼ 03 00 00 00 │ ╾──╼....╾──╼....
3434
}
3535

36-
alloc10 (size: 3, align: 1) {
36+
alloc1 (size: 3, align: 1) {
3737
66 6f 6f │ foo
3838
}
3939

40-
alloc11 (size: 3, align: 1) {
40+
alloc3 (size: 3, align: 1) {
4141
62 61 72 │ bar
4242
}
4343

44-
alloc14 (size: 24, align: 4) {
45-
0x00 │ ╾─alloc15─03 00 00 00 ╾─alloc16─╼ 03 00 00 00 │ ╾──╼....╾──╼....
46-
0x10 │ ╾─alloc17─╼ 04 00 00 00 │ ╾──╼....
44+
alloc24 (size: 24, align: 4) {
45+
0x00 │ ╾─alloc5──03 00 00 00 ╾─alloc7──╼ 03 00 00 00 │ ╾──╼....╾──╼....
46+
0x10 │ ╾─alloc9──╼ 04 00 00 00 │ ╾──╼....
4747
}
4848

49-
alloc15 (size: 3, align: 1) {
49+
alloc5 (size: 3, align: 1) {
5050
6d 65 68 │ meh
5151
}
5252

53-
alloc16 (size: 3, align: 1) {
53+
alloc7 (size: 3, align: 1) {
5454
6d 6f 70 │ mop
5555
}
5656

57-
alloc17 (size: 4, align: 1) {
57+
alloc9 (size: 4, align: 1) {
5858
6d c3 b6 70 │ m..p
5959
}

‎tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn main() -> () {
88
bb0: {
99
StorageLive(_1);
1010
StorageLive(_2);
11-
_2 = const {alloc1: &&[(Option<i32>, &[&str])]};
11+
_2 = const {alloc11: &&[(Option<i32>, &[&str])]};
1212
_1 = (*_2);
1313
StorageDead(_2);
1414
StorageDead(_1);
@@ -17,47 +17,47 @@ fn main() -> () {
1717
}
1818
}
1919

20-
alloc1 (static: FOO, size: 16, align: 8) {
21-
╾───────alloc19───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
20+
alloc11 (static: FOO, size: 16, align: 8) {
21+
╾───────alloc29───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
2222
}
2323

24-
alloc19 (size: 72, align: 8) {
25-
0x0000 00 00 00 __ __ __ __ ╾───────alloc6────────╼ │ ....░░░░╾──────╼
24+
alloc29 (size: 72, align: 8) {
25+
0x0000 00 00 00 __ __ __ __ ╾───────alloc16───────╼ │ ....░░░░╾──────╼
2626
0x1000 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
27-
0x20 │ ╾───────alloc9────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
28-
0x3001 00 00 00 2a 00 00 00 ╾───────alloc14───────╼ │ ....*...╾──────╼
27+
0x20 │ ╾───────alloc19───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
28+
0x3001 00 00 00 2a 00 00 00 ╾───────alloc24───────╼ │ ....*...╾──────╼
2929
0x4003 00 00 00 00 00 00 00 │ ........
3030
}
3131

32-
alloc6 (size: 0, align: 8) {}
32+
alloc16 (size: 0, align: 8) {}
3333

34-
alloc9 (size: 32, align: 8) {
35-
0x00 │ ╾───────alloc10───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
36-
0x10 │ ╾───────alloc11───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
34+
alloc19 (size: 32, align: 8) {
35+
0x00 │ ╾───────alloc1────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
36+
0x10 │ ╾───────alloc3────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
3737
}
3838

39-
alloc10 (size: 3, align: 1) {
39+
alloc1 (size: 3, align: 1) {
4040
66 6f 6f │ foo
4141
}
4242

43-
alloc11 (size: 3, align: 1) {
43+
alloc3 (size: 3, align: 1) {
4444
62 61 72 │ bar
4545
}
4646

47-
alloc14 (size: 48, align: 8) {
48-
0x00 │ ╾───────alloc15───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
49-
0x10 │ ╾───────alloc16───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
50-
0x20 │ ╾───────alloc17───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
47+
alloc24 (size: 48, align: 8) {
48+
0x00 │ ╾───────alloc5────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
49+
0x10 │ ╾───────alloc7────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
50+
0x20 │ ╾───────alloc9────────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
5151
}
5252

53-
alloc15 (size: 3, align: 1) {
53+
alloc5 (size: 3, align: 1) {
5454
6d 65 68 │ meh
5555
}
5656

57-
alloc16 (size: 3, align: 1) {
57+
alloc7 (size: 3, align: 1) {
5858
6d 6f 70 │ mop
5959
}
6060

61-
alloc17 (size: 4, align: 1) {
61+
alloc9 (size: 4, align: 1) {
6262
6d c3 b6 70 │ m..p
6363
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#![feature(inline_const, strict_provenance)]
2+
3+
// check-pass
4+
5+
fn main() {
6+
assert_eq!(
7+
// as_ptr INside the `const{}`
8+
(const { (unsafe { std::slice::from_raw_parts(3 as *const u8, 0) }).as_ptr() }),
9+
std::ptr::invalid(3),
10+
); // PASSES
11+
assert_eq!(
12+
// as_ptr OUTside the `const{}`
13+
(const { (unsafe { std::slice::from_raw_parts(7 as *const u8, 0) }) }).as_ptr(),
14+
std::ptr::invalid(7),
15+
); // failed in https://github.com/rust-lang/rust/issues/105536 because 0x56229d3aa00b != 0x7
16+
}

‎tests/ui/consts/const-eval/issue-49296.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
22
--> $DIR/issue-49296.rs:9:16
33
|
44
LL | const X: u64 = *wat(42);
5-
| ^^^^^^^^ pointer to alloc3 was dereferenced after this allocation got freed
5+
| ^^^^^^^^ pointer to alloc7 was dereferenced after this allocation got freed
66

77
error: aborting due to previous error
88

‎tests/ui/consts/offset_from_ub.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,19 @@ error[E0080]: evaluation of constant value failed
3939
--> $DIR/offset_from_ub.rs:53:14
4040
|
4141
LL | unsafe { ptr_offset_from(end_ptr, start_ptr) }
42-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc17 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
42+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc18 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
4343

4444
error[E0080]: evaluation of constant value failed
4545
--> $DIR/offset_from_ub.rs:62:14
4646
|
4747
LL | unsafe { ptr_offset_from(start_ptr, end_ptr) }
48-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc20 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
48+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc21 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
4949

5050
error[E0080]: evaluation of constant value failed
5151
--> $DIR/offset_from_ub.rs:70:14
5252
|
5353
LL | unsafe { ptr_offset_from(end_ptr, end_ptr) }
54-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc23 has size 4, so pointer at offset 10 is out-of-bounds
54+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc24 has size 4, so pointer at offset 10 is out-of-bounds
5555

5656
error[E0080]: evaluation of constant value failed
5757
--> $DIR/offset_from_ub.rs:79:14

‎tests/ui/consts/ptr_comparisons.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
error[E0080]: evaluation of constant value failed
22
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
33
|
4-
= note: out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds
4+
= note: out-of-bounds pointer arithmetic: alloc15 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds
55
|
66
note: inside `ptr::const_ptr::<impl *const usize>::offset`
77
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -15,7 +15,7 @@ error[E0080]: evaluation of constant value failed
1515
--> $DIR/ptr_comparisons.rs:53:33
1616
|
1717
LL | unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
18-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: alloc3 has size $WORD, so pointer to 1000 bytes starting at offset 0 is out-of-bounds
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: alloc15 has size $WORD, so pointer to 1000 bytes starting at offset 0 is out-of-bounds
1919

2020
error[E0080]: evaluation of constant value failed
2121
--> $DIR/ptr_comparisons.rs:57:27

0 commit comments

Comments
 (0)
Please sign in to comment.