Skip to content

Commit 1dc672a

Browse files
authored
Rollup merge of #95426 - b-naber:valtrees-slice, r=RalfJung,oli-obk
Include Refs in Valtree Creation This adds references to `const_to_valtree`, which isn't used in the compiler yet, but after the previous changes we made to the thir and mir representations and this change we should be able to finally introduce them in the next PR. I wasn't able to properly test this code, except indirectly by including a call of `const_to_valtree` in the code that currently creates constants (`turn_into_const_value`). r? `@lcnr` cc `@oli-obk` `@RalfJung`
2 parents 3dced80 + d8205cd commit 1dc672a

File tree

4 files changed

+59
-27
lines changed

4 files changed

+59
-27
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

+55-25
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
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},
910
ty::ScalarInt,
1011
};
1112
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
13+
use rustc_target::abi::VariantIdx;
1214

1315
use crate::interpret::{
1416
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MPlaceTy,
@@ -55,28 +57,48 @@ pub(crate) fn const_to_valtree<'tcx>(
5557
const_to_valtree_inner(&ecx, &place)
5658
}
5759

58-
fn const_to_valtree_inner<'tcx>(
60+
#[instrument(skip(ecx), level = "debug")]
61+
fn branches<'tcx>(
5962
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
6063
place: &MPlaceTy<'tcx>,
64+
n: usize,
65+
variant: Option<VariantIdx>,
6166
) -> Option<ty::ValTree<'tcx>> {
62-
let branches = |n, variant| {
63-
let place = match variant {
64-
Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(),
65-
None => *place,
66-
};
67-
let variant =
68-
variant.map(|variant| Some(ty::ValTree::Leaf(ScalarInt::from(variant.as_u32()))));
69-
let fields = (0..n).map(|i| {
70-
let field = ecx.mplace_field(&place, i).unwrap();
71-
const_to_valtree_inner(ecx, &field)
72-
});
73-
// For enums, we preped their variant index before the variant's fields so we can figure out
74-
// the variant again when just seeing a valtree.
75-
let branches = variant.into_iter().chain(fields);
76-
Some(ty::ValTree::Branch(
77-
ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?),
78-
))
67+
let place = match variant {
68+
Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(),
69+
None => *place,
7970
};
71+
let variant = variant.map(|variant| Some(ty::ValTree::Leaf(ScalarInt::from(variant.as_u32()))));
72+
debug!(?place, ?variant);
73+
74+
let fields = (0..n).map(|i| {
75+
let field = ecx.mplace_field(&place, i).unwrap();
76+
const_to_valtree_inner(ecx, &field)
77+
});
78+
// For enums, we prepend their variant index before the variant's fields so we can figure out
79+
// the variant again when just seeing a valtree.
80+
let branches = variant.into_iter().chain(fields);
81+
Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
82+
}
83+
84+
fn slice_branches<'tcx>(
85+
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
86+
place: &MPlaceTy<'tcx>,
87+
) -> Option<ty::ValTree<'tcx>> {
88+
let n = place.len(&ecx.tcx()).expect(&format!("expected to use len of place {:?}", place));
89+
let branches = (0..n).map(|i| {
90+
let place_elem = ecx.mplace_index(place, i).unwrap();
91+
const_to_valtree_inner(ecx, &place_elem)
92+
});
93+
94+
Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
95+
}
96+
97+
#[instrument(skip(ecx), level = "debug")]
98+
fn const_to_valtree_inner<'tcx>(
99+
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
100+
place: &MPlaceTy<'tcx>,
101+
) -> Option<ty::ValTree<'tcx>> {
80102
match place.layout.ty.kind() {
81103
ty::FnDef(..) => Some(ty::ValTree::zst()),
82104
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
@@ -90,19 +112,27 @@ fn const_to_valtree_inner<'tcx>(
90112
// Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to
91113
// agree with runtime equality tests.
92114
ty::FnPtr(_) | ty::RawPtr(_) => None,
93-
ty::Ref(..) => unimplemented!("need to use deref_const"),
94115

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);
119+
120+
const_to_valtree_inner(ecx, &derefd_place)
121+
}
122+
123+
ty::Str | ty::Slice(_) | ty::Array(_, _) => {
124+
let valtree = slice_branches(ecx, place);
125+
debug!(?valtree);
126+
127+
valtree
128+
}
95129
// Trait objects are not allowed in type level constants, as we have no concept for
96130
// resolving their backing type, even if we can do that at const eval time. We may
97131
// hypothetically be able to allow `dyn StructuralEq` trait objects in the future,
98132
// but it is unclear if this is useful.
99133
ty::Dynamic(..) => None,
100134

101-
ty::Slice(_) | ty::Str => {
102-
unimplemented!("need to find the backing data of the slice/str and recurse on that")
103-
}
104-
ty::Tuple(substs) => branches(substs.len(), None),
105-
ty::Array(_, len) => branches(usize::try_from(len.eval_usize(ecx.tcx.tcx, ecx.param_env)).unwrap(), None),
135+
ty::Tuple(substs) => branches(ecx, place, substs.len(), None),
106136

107137
ty::Adt(def, _) => {
108138
if def.variants().is_empty() {
@@ -111,7 +141,7 @@ fn const_to_valtree_inner<'tcx>(
111141

112142
let variant = ecx.read_discriminant(&place.into()).unwrap().1;
113143

114-
branches(def.variant(variant).fields.len(), def.is_enum().then_some(variant))
144+
branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant))
115145
}
116146

117147
ty::Never

compiler/rustc_const_eval/src/interpret/place.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ impl<'tcx, Tag: Provenance> MPlaceTy<'tcx, Tag> {
191191
}
192192

193193
#[inline]
194-
pub(super) fn len(&self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
194+
pub(crate) fn len(&self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
195195
if self.layout.is_unsized() {
196196
// We need to consult `meta` metadata
197197
match self.layout.ty.kind() {

compiler/rustc_middle/src/ty/consts/valtree.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::ScalarInt;
2-
use rustc_macros::HashStable;
2+
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
33

44
#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
55
#[derive(HashStable)]

0 commit comments

Comments
 (0)