Skip to content

Commit 82217a6

Browse files
committed
create leafs for slices
1 parent fcc4d8c commit 82217a6

File tree

6 files changed

+64
-145
lines changed

6 files changed

+64
-145
lines changed

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+2
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ pub(super) fn op_to_const<'tcx>(
188188
}
189189
}
190190

191+
#[instrument(skip(tcx), level = "debug")]
191192
fn turn_into_const_value<'tcx>(
192193
tcx: TyCtxt<'tcx>,
193194
constant: ConstAlloc<'tcx>,
@@ -206,6 +207,7 @@ fn turn_into_const_value<'tcx>(
206207
!is_static || cid.promoted.is_some(),
207208
"the `eval_to_const_value_raw` query should not be used for statics, use `eval_to_allocation` instead"
208209
);
210+
209211
// Turn this into a proper constant.
210212
op_to_const(&ecx, &mplace.into())
211213
}

compiler/rustc_const_eval/src/const_eval/mod.rs

+57-71
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ use rustc_hir::Mutability;
66
use rustc_middle::ty::{self, TyCtxt};
77
use rustc_middle::{
88
mir::{self, interpret::ConstAlloc},
9-
ty::{ScalarInt, Ty},
9+
ty::ScalarInt,
1010
};
1111
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
1212
use rustc_target::abi::VariantIdx;
1313

1414
use crate::interpret::{
15-
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MPlaceTy,
16-
MemPlaceMeta, Scalar,
15+
intern_const_alloc_recursive, ConstValue, Immediate, InternKind, InterpCx, InterpResult,
16+
MPlaceTy, MemPlaceMeta, Scalar,
1717
};
1818

1919
mod error;
@@ -80,19 +80,28 @@ fn branches<'tcx>(
8080
Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
8181
}
8282

83+
fn slice_branches<'tcx>(
84+
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
85+
place: &MPlaceTy<'tcx>,
86+
n: u64,
87+
) -> Option<ty::ValTree<'tcx>> {
88+
let elems = (0..n).map(|i| {
89+
let place_elem = ecx.mplace_index(place, i).unwrap();
90+
const_to_valtree_inner(ecx, &place_elem)
91+
});
92+
93+
// Need `len` for the ValTree -> ConstValue conversion
94+
let len = Some(Some(ty::ValTree::Leaf(ScalarInt::from(n))));
95+
let branches = len.into_iter().chain(elems);
96+
97+
Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
98+
}
99+
83100
#[instrument(skip(ecx), level = "debug")]
84101
fn const_to_valtree_inner<'tcx>(
85102
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
86103
place: &MPlaceTy<'tcx>,
87104
) -> Option<ty::ValTree<'tcx>> {
88-
// We only want to use raw bytes in ValTrees for string slices or &[<integer_ty>]
89-
let use_bytes_for_ref = |ty: Ty<'tcx>| -> bool {
90-
match ty.kind() {
91-
ty::Str | ty::Char | ty::Uint(_) | ty::Int(_) | ty::Bool => true,
92-
_ => false,
93-
}
94-
};
95-
96105
match place.layout.ty.kind() {
97106
ty::FnDef(..) => Some(ty::ValTree::zst()),
98107
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
@@ -107,75 +116,52 @@ fn const_to_valtree_inner<'tcx>(
107116
// agree with runtime equality tests.
108117
ty::FnPtr(_) | ty::RawPtr(_) => None,
109118

110-
ty::Ref(_, ref_ty, _) if place.layout.ty.is_slice() => {
111-
match ecx.try_read_immediate_from_mplace(&place) {
112-
Ok(Some(imm)) => {
113-
// `imm` is a ScalarPair. We try to get the underlying bytes behind that
114-
// fat pointer for string slices and slices of integer types. For any other
115-
// slice types we use `branches` to recursively construct the Valtree.
116-
117-
if use_bytes_for_ref(*ref_ty) {
118-
let (alloc, range) = ecx.get_alloc_from_imm_scalar_pair(imm);
119-
let alloc_bytes = match alloc.get_bytes(&ecx.tcx, range) {
120-
Ok(bytes) => bytes,
121-
Err(_e) => return None,
122-
};
123-
debug!(?alloc_bytes);
124-
125-
let bytes = ecx.tcx.arena.alloc_slice(alloc_bytes);
126-
let len = bytes.len();
127-
debug!(?bytes, ?len);
128-
129-
let slice = ty::ValSlice { bytes};
130-
131-
Some(ty::ValTree::SliceOrStr(slice))
132-
} else {
133-
let derefd = ecx.deref_operand(&imm.into()).expect(&format!("couldnt deref {:?}", imm));
134-
debug!("derefd: {:?}", derefd);
135-
136-
let derefd_imm = match ecx.try_read_immediate_from_mplace(&derefd) {
137-
Ok(Some(imm)) => imm,
138-
_ => return None,
139-
};
140-
debug!(?derefd_imm);
141-
142-
let tcx = ecx.tcx.tcx;
143-
let scalar_len= derefd.meta.unwrap_meta();
144-
let len = match scalar_len {
145-
Scalar::Int(int) => {
146-
int.try_to_machine_usize(tcx).expect(&format!("Expected a valid ScalarInt in {:?}", scalar_len))
147-
}
148-
_ => bug!("expected a ScalarInt in meta data for {:?}", place),
149-
};
150-
debug!(?len);
151-
152-
let valtree = branches(ecx, place, len.try_into().expect("BLA"), None);
153-
debug!(?valtree);
154-
155-
valtree
119+
ty::Ref(_, inner_ty, _) => {
120+
match inner_ty.kind() {
121+
ty::Slice(_) | ty::Str => {
122+
match ecx.try_read_immediate_from_mplace(&place) {
123+
Ok(Some(imm)) => {
124+
let mplace_ref = ecx.ref_to_mplace(&imm).unwrap();
125+
let derefd = ecx.deref_operand(&place.into()).expect(&format!("couldnt deref {:?}", imm));
126+
debug!(?mplace_ref, ?derefd);
127+
128+
let len = match imm.imm {
129+
Immediate::ScalarPair(_, b) => {
130+
let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap();
131+
len
132+
}
133+
_ => bug!("expected ScalarPair for &[T] or &str"),
134+
};
135+
debug!(?len);
136+
137+
let valtree = slice_branches(ecx, &derefd, len);
138+
debug!(?valtree);
139+
140+
valtree
141+
}
142+
_ => {
143+
None
144+
}
156145
}
157146
}
158147
_ => {
159-
None
160-
}
161-
}
162-
}
148+
let imm = ecx.try_read_immediate_from_mplace(&place).unwrap_or_else(|e| bug!("couldnt read immediate from {:?}, error: {:?}", place, e));
163149

164-
ty::Ref(_, inner_ty, _) => {
165-
debug!("Ref with inner_ty: {:?}", inner_ty);
166-
let imm = ecx.try_read_immediate_from_mplace(&place).unwrap_or_else(|e| bug!("couldnt read immediate from {:?}, error: {:?}", place, e));
167-
match imm {
168-
Some(imm) => {
169-
debug!(?imm);
150+
match imm {
151+
Some(imm) => {
152+
debug!(?imm);
170153

171-
let derefd_place = ecx.deref_mplace(place).unwrap_or_else(|e| bug!("couldn't deref {:?}, error: {:?}", place, e));
172-
debug!(?derefd_place);
154+
let derefd_place = ecx.deref_operand(&place.into()).unwrap_or_else(|e| bug!("couldn't deref {:?}, error: {:?}", place, e));
155+
debug!(?derefd_place);
173156

174-
const_to_valtree_inner(ecx, &derefd_place)
157+
const_to_valtree_inner(ecx, &derefd_place)
158+
}
159+
None => bug!("couldn't read immediate from {:?}", place),
160+
}
175161
}
176-
None => None,
177162
}
178163
}
164+
179165
ty::Str => {
180166
bug!("ty::Str should have been handled in ty::Ref branch that uses raw bytes");
181167
}

compiler/rustc_const_eval/src/interpret/operand.rs

+4-33
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ use rustc_target::abi::{Abi, HasDataLayout, Size, TagEncoding};
1414
use rustc_target::abi::{VariantIdx, Variants};
1515

1616
use super::{
17-
alloc_range, from_known_layout, mir_assign_valid_types, AllocId, AllocRange, Allocation,
18-
ConstValue, GlobalId, InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, Place, PlaceTy,
19-
Pointer, Provenance, Scalar, ScalarMaybeUninit,
17+
alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, GlobalId,
18+
InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, Place, PlaceTy, Pointer, Provenance,
19+
Scalar, ScalarMaybeUninit,
2020
};
2121

2222
/// An `Immediate` represents a single immediate self-contained Rust value.
@@ -98,7 +98,7 @@ impl<'tcx, Tag: Provenance> Immediate<Tag> {
9898
// as input for binary and cast operations.
9999
#[derive(Copy, Clone, Debug)]
100100
pub struct ImmTy<'tcx, Tag: Provenance = AllocId> {
101-
imm: Immediate<Tag>,
101+
pub(crate) imm: Immediate<Tag>,
102102
pub layout: TyAndLayout<'tcx>,
103103
}
104104

@@ -777,32 +777,3 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
777777
})
778778
}
779779
}
780-
781-
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx, PointerTag = AllocId>> InterpCx<'mir, 'tcx, M> {
782-
pub fn get_alloc_from_imm_scalar_pair(
783-
&self,
784-
imm: ImmTy<'tcx, M::PointerTag>,
785-
) -> (&Allocation, AllocRange) {
786-
match imm.imm {
787-
Immediate::ScalarPair(a, b) => {
788-
// We know `offset` is relative to the allocation, so we can use `into_parts`.
789-
let (data, start) = match self.scalar_to_ptr(a.check_init().unwrap()).into_parts() {
790-
(Some(alloc_id), offset) => {
791-
(self.tcx.global_alloc(alloc_id).unwrap_memory(), offset.bytes())
792-
}
793-
(None, _offset) => (
794-
self.tcx.intern_const_alloc(Allocation::from_bytes_byte_aligned_immutable(
795-
b"" as &[u8],
796-
)),
797-
0,
798-
),
799-
};
800-
let len = b.to_machine_usize(self).unwrap();
801-
let size = Size::from_bytes(len);
802-
let start = Size::from_bytes(start);
803-
(data.inner(), AllocRange { start, size })
804-
}
805-
_ => bug!("{:?} not a ScalarPair", imm),
806-
}
807-
}
808-
}

compiler/rustc_const_eval/src/interpret/place.rs

-12
Original file line numberDiff line numberDiff line change
@@ -305,18 +305,6 @@ where
305305
Ok(mplace)
306306
}
307307

308-
#[instrument(skip(self), level = "debug")]
309-
pub fn deref_mplace(
310-
&self,
311-
src: &MPlaceTy<'tcx, M::PointerTag>,
312-
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
313-
let val = self.try_read_immediate_from_mplace(src)?;
314-
let mplace = self.ref_to_mplace(&val.unwrap())?;
315-
self.check_mplace_access(mplace, CheckInAllocMsg::DerefTest)?;
316-
317-
Ok(mplace)
318-
}
319-
320308
#[inline]
321309
pub(super) fn get_alloc(
322310
&self,
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use super::ScalarInt;
2-
use crate::ty::codec::TyDecoder;
32
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
4-
use rustc_serialize::{Decodable, Encodable, Encoder};
53

64
#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
75
#[derive(HashStable)]
@@ -22,7 +20,6 @@ pub enum ValTree<'tcx> {
2220
/// See the `ScalarInt` documentation for how `ScalarInt` guarantees that equal values
2321
/// of these types have the same representation.
2422
Leaf(ScalarInt),
25-
SliceOrStr(ValSlice<'tcx>),
2623
/// The fields of any kind of aggregate. Structs, tuples and arrays are represented by
2724
/// listing their fields' values in order.
2825
/// Enums are represented by storing their discriminant as a field, followed by all
@@ -35,28 +32,3 @@ impl<'tcx> ValTree<'tcx> {
3532
Self::Branch(&[])
3633
}
3734
}
38-
39-
#[derive(Copy, Clone, Debug, HashStable, Hash, Eq, PartialEq, PartialOrd, Ord)]
40-
pub struct ValSlice<'tcx> {
41-
pub bytes: &'tcx [u8],
42-
}
43-
44-
impl<'tcx, S: Encoder> Encodable<S> for ValSlice<'tcx> {
45-
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
46-
s.emit_usize(self.bytes.len())?;
47-
s.emit_raw_bytes(self.bytes)?;
48-
49-
Ok(())
50-
}
51-
}
52-
53-
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ValSlice<'tcx> {
54-
fn decode(d: &mut D) -> Self {
55-
let tcx = d.tcx();
56-
let len = d.read_usize();
57-
let bytes_raw = d.read_raw_bytes(len);
58-
let bytes = tcx.arena.alloc_slice(&bytes_raw[..]);
59-
60-
ValSlice { bytes }
61-
}
62-
}

compiler/rustc_middle/src/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ pub use self::closure::{
6262
CAPTURE_STRUCT_LOCAL,
6363
};
6464
pub use self::consts::{
65-
Const, ConstInt, ConstKind, ConstS, InferConst, ScalarInt, Unevaluated, ValSlice, ValTree,
65+
Const, ConstInt, ConstKind, ConstS, InferConst, ScalarInt, Unevaluated, ValTree,
6666
};
6767
pub use self::context::{
6868
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,

0 commit comments

Comments
 (0)