diff options
| author | b-naber <bn263@gmx.de> | 2022-04-26 10:58:45 +0200 |
|---|---|---|
| committer | b-naber <bn263@gmx.de> | 2022-04-26 18:40:15 +0200 |
| commit | bfefb4d74cbd1520afaa97db1eba59c06283c696 (patch) | |
| tree | 3bc8e0ed4f06aa3f5bf61b641973f3b3b9fe0c6a /compiler/rustc_const_eval/src/const_eval | |
| parent | 6fc3e630fb98cc6200f60ebbb7c7f826b2d48407 (diff) | |
| download | rust-bfefb4d74cbd1520afaa97db1eba59c06283c696.tar.gz rust-bfefb4d74cbd1520afaa97db1eba59c06283c696.zip | |
account for custom DSTs in valtree -> constvalue conversion
Diffstat (limited to 'compiler/rustc_const_eval/src/const_eval')
| -rw-r--r-- | compiler/rustc_const_eval/src/const_eval/eval_queries.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/const_eval/valtrees.rs | 118 |
2 files changed, 117 insertions, 9 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 52b65c41b4f..6112c4ffbfa 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -215,6 +215,10 @@ fn turn_into_const_value<'tcx>( "the `eval_to_const_value_raw` query should not be used for statics, use `eval_to_allocation` instead" ); + // Turn this into a proper constant. + let const_val = op_to_const(&ecx, &mplace.into()); + debug!(?const_val); + if cfg!(debug_assertions) { if let Some(valtree) = const_to_valtree(tcx, key.param_env, constant) { let const_val = tcx.valtree_to_const_val((constant.ty, valtree)); @@ -222,10 +226,6 @@ fn turn_into_const_value<'tcx>( } } - // Turn this into a proper constant. - let const_val = op_to_const(&ecx, &mplace.into()); - debug!(?const_val); - const_val } diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index f35b28e187a..389301300ea 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -1,13 +1,13 @@ use super::eval_queries::{mk_eval_cx, op_to_const}; use super::machine::CompileTimeEvalContext; use crate::interpret::{ - intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemoryKind, PlaceTy, - Scalar, ScalarMaybeUninit, + intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemPlaceMeta, + MemoryKind, PlaceTy, Scalar, ScalarMaybeUninit, }; use rustc_middle::mir::interpret::ConstAlloc; use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; use rustc_span::source_map::DUMMY_SP; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{Align, VariantIdx}; use crate::interpret::MPlaceTy; use crate::interpret::Value; @@ -108,7 +108,9 @@ fn const_to_valtree_inner<'tcx>( ty::Tuple(substs) => branches(ecx, place, substs.len(), None), ty::Adt(def, _) => { - if def.variants().is_empty() { + if def.is_union() { + return None + } else if def.variants().is_empty() { bug!("uninhabited types should have errored and never gotten converted to valtree") } @@ -149,6 +151,41 @@ fn create_mplace_from_layout<'tcx>( ecx.allocate(layout, MemoryKind::Stack).unwrap() } +// Walks custom DSTs and gets the type of the unsized field and the number of elements +// in the unsized field. +fn get_info_on_unsized_field<'tcx>( + ty: Ty<'tcx>, + valtree: ty::ValTree<'tcx>, + tcx: TyCtxt<'tcx>, +) -> (Ty<'tcx>, usize) { + let mut last_valtree = valtree; + let tail = tcx.struct_tail_with_normalize( + ty, + |ty| ty, + || { + let branches = last_valtree.unwrap_branch(); + last_valtree = branches[branches.len() - 1]; + debug!(?branches, ?last_valtree); + }, + ); + let unsized_inner_ty = match tail.kind() { + ty::Slice(t) => *t, + ty::Str => tail, + _ => bug!("expected Slice or Str"), + }; + + // Have to adjust type for ty::Str + let unsized_inner_ty = match unsized_inner_ty.kind() { + ty::Str => tcx.mk_ty(ty::Uint(ty::UintTy::U8)), + _ => unsized_inner_ty, + }; + + // Get the number of elements in the unsized field + let num_elems = last_valtree.unwrap_branch().len(); + + (unsized_inner_ty, num_elems) +} + #[instrument(skip(ecx), level = "debug")] fn create_pointee_place<'tcx>( ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>, @@ -173,6 +210,33 @@ fn create_pointee_place<'tcx>( place } + ty::Adt(_, _) if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty()) => { + // We need to create `Allocation`s for custom DSTs + + let layout = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap(); + let sized_fields_size = layout.layout.size(); + let (unsized_inner_ty, num_elems) = get_info_on_unsized_field(ty, valtree, tcx); + let unsized_inner_ty_size = + tcx.layout_of(ty::ParamEnv::empty().and(unsized_inner_ty)).unwrap().layout.size(); + debug!(?unsized_inner_ty, ?unsized_inner_ty_size, ?num_elems); + + // Get the size of the array behind the DST + let dst_size = unsized_inner_ty_size.checked_mul(num_elems as u64, &tcx).unwrap(); + + let ptr = ecx + .allocate_ptr( + sized_fields_size.checked_add(dst_size, &tcx).unwrap(), + Align::from_bytes(1).unwrap(), + MemoryKind::Stack, + ) + .unwrap(); + debug!(?ptr); + + let place = MPlaceTy::from_aligned_ptr(ptr.into(), layout); + debug!(?place); + + place + } _ => create_mplace_from_layout(ecx, ty), } } @@ -270,6 +334,13 @@ fn fill_place_recursively<'tcx>( let ty = place.layout.ty; match ty.kind() { + ty::FnDef(_, _) => { + ecx.write_immediate( + Immediate::Scalar(ScalarMaybeUninit::Scalar(Scalar::ZST)), + &(*place).into(), + ) + .unwrap(); + } ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => { let scalar_int = valtree.unwrap_leaf(); debug!("writing trivial valtree {:?} to place {:?}", scalar_int, place); @@ -306,6 +377,9 @@ fn fill_place_recursively<'tcx>( ty::Adt(_, _) | ty::Tuple(_) | ty::Array(_, _) | ty::Str => { let branches = valtree.unwrap_branch(); + // Need to collect the length of the unsized field for meta info + let mut unsized_meta_info = None; + // Need to downcast place for enums let (place_adjusted, branches, variant_idx) = match ty.kind() { ty::Adt(def, _) if def.is_enum() => { @@ -329,6 +403,35 @@ fn fill_place_recursively<'tcx>( for (i, inner_valtree) in branches.iter().enumerate() { debug!(?i, ?inner_valtree); + if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty()) && i == branches.len() - 1 { + // Note: For custom DSTs we need to manually process the last unsized field. + // We created a `Pointer` for the `Allocation` of the complete sized version of + // the Adt in `create_pointee_place` and now we fill that `Allocation` with the + // values in the ValTree. For the unsized field we have to additionally add the meta + // data. + + let offset = place.layout.fields.offset(i); + let (unsized_inner_ty, num_elems) = get_info_on_unsized_field(ty, valtree, tcx); + unsized_meta_info = Some(num_elems); + + // We create an array type to allow the recursive call to fill the place + // corresponding to the array + let arr_ty = tcx.mk_array(unsized_inner_ty, num_elems as u64); + debug!(?arr_ty); + let arr_layout = tcx.layout_of(ty::ParamEnv::empty().and(arr_ty)).unwrap(); + let mut place_arr = + place.offset(offset, MemPlaceMeta::None, arr_layout, &tcx).unwrap(); + debug!(?place_arr); + + fill_place_recursively(ecx, &mut place_arr, *inner_valtree); + dump_place(&ecx, place_arr.into()); + + // Add the meta information for the unsized type + place_arr.meta = MemPlaceMeta::Meta(Scalar::from_u64(num_elems as u64)); + + break; + } + let mut place_inner = match *ty.kind() { ty::Adt(_, _) | ty::Tuple(_) => ecx.mplace_field(&place_adjusted, i).unwrap(), ty::Array(_, _) | ty::Str => { @@ -338,7 +441,6 @@ fn fill_place_recursively<'tcx>( }; debug!(?place_inner); - // insert valtree corresponding to tuple element into place fill_place_recursively(ecx, &mut place_inner, *inner_valtree); dump_place(&ecx, place_inner.into()); } @@ -351,6 +453,12 @@ fn fill_place_recursively<'tcx>( ecx.write_discriminant(variant_idx, &(*place).into()).unwrap(); } + // add meta information for unsized type + if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty()) { + place.meta = + MemPlaceMeta::Meta(Scalar::from_u64(unsized_meta_info.unwrap() as u64)); + } + dump_place(ecx, (*place).into()); } _ => bug!("shouldn't have created a ValTree for {:?}", ty), |
