handle arrays and slices uniformly in valtree creation
This commit is contained in:
parent
4b126b805b
commit
d8205cd3fe
@ -3,6 +3,7 @@
|
|||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use rustc_hir::Mutability;
|
use rustc_hir::Mutability;
|
||||||
|
use rustc_middle::ty::layout::HasTyCtxt;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_middle::{
|
use rustc_middle::{
|
||||||
mir::{self, interpret::ConstAlloc},
|
mir::{self, interpret::ConstAlloc},
|
||||||
@ -74,7 +75,7 @@ fn branches<'tcx>(
|
|||||||
let field = ecx.mplace_field(&place, i).unwrap();
|
let field = ecx.mplace_field(&place, i).unwrap();
|
||||||
const_to_valtree_inner(ecx, &field)
|
const_to_valtree_inner(ecx, &field)
|
||||||
});
|
});
|
||||||
// For enums, we preped their variant index before the variant's fields so we can figure out
|
// For enums, we prepend their variant index before the variant's fields so we can figure out
|
||||||
// the variant again when just seeing a valtree.
|
// the variant again when just seeing a valtree.
|
||||||
let branches = variant.into_iter().chain(fields);
|
let branches = variant.into_iter().chain(fields);
|
||||||
Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
|
Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
|
||||||
@ -83,17 +84,13 @@ fn branches<'tcx>(
|
|||||||
fn slice_branches<'tcx>(
|
fn slice_branches<'tcx>(
|
||||||
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
|
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
|
||||||
place: &MPlaceTy<'tcx>,
|
place: &MPlaceTy<'tcx>,
|
||||||
n: u64,
|
|
||||||
) -> Option<ty::ValTree<'tcx>> {
|
) -> Option<ty::ValTree<'tcx>> {
|
||||||
let elems = (0..n).map(|i| {
|
let n = place.len(&ecx.tcx()).expect(&format!("expected to use len of place {:?}", place));
|
||||||
|
let branches = (0..n).map(|i| {
|
||||||
let place_elem = ecx.mplace_index(place, i).unwrap();
|
let place_elem = ecx.mplace_index(place, i).unwrap();
|
||||||
const_to_valtree_inner(ecx, &place_elem)
|
const_to_valtree_inner(ecx, &place_elem)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Need `len` for the ValTree -> ConstValue conversion
|
|
||||||
let len = Some(Some(ty::ValTree::Leaf(ScalarInt::from(n))));
|
|
||||||
let branches = len.into_iter().chain(elems);
|
|
||||||
|
|
||||||
Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
|
Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,33 +113,19 @@ fn const_to_valtree_inner<'tcx>(
|
|||||||
// agree with runtime equality tests.
|
// agree with runtime equality tests.
|
||||||
ty::FnPtr(_) | ty::RawPtr(_) => None,
|
ty::FnPtr(_) | ty::RawPtr(_) => None,
|
||||||
|
|
||||||
ty::Ref(_, inner_ty, _) => {
|
ty::Ref(_, _, _) => {
|
||||||
match inner_ty.kind() {
|
let derefd_place = ecx.deref_operand(&place.into()).unwrap_or_else(|e| bug!("couldn't deref {:?}, error: {:?}", place, e));
|
||||||
ty::Slice(_) | ty::Str => {
|
debug!(?derefd_place);
|
||||||
let derefd = ecx.deref_operand(&place.into()).unwrap();
|
|
||||||
debug!(?derefd);
|
|
||||||
let len = derefd.len(&ecx.tcx.tcx).unwrap();
|
|
||||||
let valtree = slice_branches(ecx, &derefd, len);
|
|
||||||
debug!(?valtree);
|
|
||||||
|
|
||||||
valtree
|
const_to_valtree_inner(ecx, &derefd_place)
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let derefd_place = ecx.deref_operand(&place.into()).unwrap_or_else(|e| bug!("couldn't deref {:?}, error: {:?}", place, e));
|
|
||||||
debug!(?derefd_place);
|
|
||||||
|
|
||||||
const_to_valtree_inner(ecx, &derefd_place)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Str => {
|
ty::Str | ty::Slice(_) | ty::Array(_, _) => {
|
||||||
bug!("ty::Str should have been handled in ty::Ref branch that uses raw bytes");
|
let valtree = slice_branches(ecx, place);
|
||||||
}
|
debug!(?valtree);
|
||||||
ty::Slice(_) => {
|
|
||||||
bug!("should have been handled in the Ref arm");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
valtree
|
||||||
|
}
|
||||||
// Trait objects are not allowed in type level constants, as we have no concept for
|
// Trait objects are not allowed in type level constants, as we have no concept for
|
||||||
// resolving their backing type, even if we can do that at const eval time. We may
|
// resolving their backing type, even if we can do that at const eval time. We may
|
||||||
// hypothetically be able to allow `dyn StructuralEq` trait objects in the future,
|
// hypothetically be able to allow `dyn StructuralEq` trait objects in the future,
|
||||||
@ -150,7 +133,6 @@ fn const_to_valtree_inner<'tcx>(
|
|||||||
ty::Dynamic(..) => None,
|
ty::Dynamic(..) => None,
|
||||||
|
|
||||||
ty::Tuple(substs) => branches(ecx, place, substs.len(), None),
|
ty::Tuple(substs) => branches(ecx, place, substs.len(), None),
|
||||||
ty::Array(_, len) => branches(ecx, place, usize::try_from(len.eval_usize(ecx.tcx.tcx, ecx.param_env)).unwrap(), None),
|
|
||||||
|
|
||||||
ty::Adt(def, _) => {
|
ty::Adt(def, _) => {
|
||||||
if def.variants().is_empty() {
|
if def.variants().is_empty() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user