Skip to content

Commit 41d92c4

Browse files
committed
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

+1
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

-10
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

+1-17
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

+15-26
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

+23-4
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

+2-2
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

+6-7
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

-13
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

+1-1
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

+45-22
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-
}

0 commit comments

Comments
 (0)