Skip to content

Commit d8205cd

Browse files
committed
handle arrays and slices uniformly in valtree creation
1 parent 4b126b8 commit d8205cd

File tree

1 file changed

+13
-31
lines changed
  • compiler/rustc_const_eval/src/const_eval

1 file changed

+13
-31
lines changed

compiler/rustc_const_eval/src/const_eval/mod.rs

+13-31
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::convert::TryFrom;
44

55
use rustc_hir::Mutability;
6+
use rustc_middle::ty::layout::HasTyCtxt;
67
use rustc_middle::ty::{self, TyCtxt};
78
use rustc_middle::{
89
mir::{self, interpret::ConstAlloc},
@@ -74,7 +75,7 @@ fn branches<'tcx>(
7475
let field = ecx.mplace_field(&place, i).unwrap();
7576
const_to_valtree_inner(ecx, &field)
7677
});
77-
// For enums, we preped their variant index before the variant's fields so we can figure out
78+
// For enums, we prepend their variant index before the variant's fields so we can figure out
7879
// the variant again when just seeing a valtree.
7980
let branches = variant.into_iter().chain(fields);
8081
Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
@@ -83,17 +84,13 @@ fn branches<'tcx>(
8384
fn slice_branches<'tcx>(
8485
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
8586
place: &MPlaceTy<'tcx>,
86-
n: u64,
8787
) -> Option<ty::ValTree<'tcx>> {
88-
let elems = (0..n).map(|i| {
88+
let n = place.len(&ecx.tcx()).expect(&format!("expected to use len of place {:?}", place));
89+
let branches = (0..n).map(|i| {
8990
let place_elem = ecx.mplace_index(place, i).unwrap();
9091
const_to_valtree_inner(ecx, &place_elem)
9192
});
9293

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-
9794
Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
9895
}
9996

@@ -116,41 +113,26 @@ fn const_to_valtree_inner<'tcx>(
116113
// agree with runtime equality tests.
117114
ty::FnPtr(_) | ty::RawPtr(_) => None,
118115

119-
ty::Ref(_, inner_ty, _) => {
120-
match inner_ty.kind() {
121-
ty::Slice(_) | ty::Str => {
122-
let derefd = ecx.deref_operand(&place.into()).unwrap();
123-
debug!(?derefd);
124-
let len = derefd.len(&ecx.tcx.tcx).unwrap();
125-
let valtree = slice_branches(ecx, &derefd, len);
126-
debug!(?valtree);
127-
128-
valtree
129-
}
130-
_ => {
131-
let derefd_place = ecx.deref_operand(&place.into()).unwrap_or_else(|e| bug!("couldn't deref {:?}, error: {:?}", place, e));
132-
debug!(?derefd_place);
116+
ty::Ref(_, _, _) => {
117+
let derefd_place = ecx.deref_operand(&place.into()).unwrap_or_else(|e| bug!("couldn't deref {:?}, error: {:?}", place, e));
118+
debug!(?derefd_place);
133119

134-
const_to_valtree_inner(ecx, &derefd_place)
135-
}
136-
}
120+
const_to_valtree_inner(ecx, &derefd_place)
137121
}
138122

139-
ty::Str => {
140-
bug!("ty::Str should have been handled in ty::Ref branch that uses raw bytes");
141-
}
142-
ty::Slice(_) => {
143-
bug!("should have been handled in the Ref arm");
144-
}
123+
ty::Str | ty::Slice(_) | ty::Array(_, _) => {
124+
let valtree = slice_branches(ecx, place);
125+
debug!(?valtree);
145126

127+
valtree
128+
}
146129
// Trait objects are not allowed in type level constants, as we have no concept for
147130
// resolving their backing type, even if we can do that at const eval time. We may
148131
// hypothetically be able to allow `dyn StructuralEq` trait objects in the future,
149132
// but it is unclear if this is useful.
150133
ty::Dynamic(..) => None,
151134

152135
ty::Tuple(substs) => branches(ecx, place, substs.len(), None),
153-
ty::Array(_, len) => branches(ecx, place, usize::try_from(len.eval_usize(ecx.tcx.tcx, ecx.param_env)).unwrap(), None),
154136

155137
ty::Adt(def, _) => {
156138
if def.variants().is_empty() {

0 commit comments

Comments
 (0)