Skip to content

Commit ef5f072

Browse files
committed
combine all unsized types and add another recursive call to process nested unsized types correctly
1 parent bfefb4d commit ef5f072

File tree

3 files changed

+79
-97
lines changed

3 files changed

+79
-97
lines changed

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{const_to_valtree, CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr};
1+
use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr};
22
use crate::interpret::eval_nullary_intrinsic;
33
use crate::interpret::{
44
intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId,
@@ -219,13 +219,6 @@ fn turn_into_const_value<'tcx>(
219219
let const_val = op_to_const(&ecx, &mplace.into());
220220
debug!(?const_val);
221221

222-
if cfg!(debug_assertions) {
223-
if let Some(valtree) = const_to_valtree(tcx, key.param_env, constant) {
224-
let const_val = tcx.valtree_to_const_val((constant.ty, valtree));
225-
debug!(?const_val);
226-
}
227-
}
228-
229222
const_val
230223
}
231224

compiler/rustc_const_eval/src/const_eval/valtrees.rs

+77-88
Original file line numberDiff line numberDiff line change
@@ -194,55 +194,48 @@ fn create_pointee_place<'tcx>(
194194
) -> MPlaceTy<'tcx> {
195195
let tcx = ecx.tcx.tcx;
196196

197-
match ty.kind() {
198-
ty::Slice(_) | ty::Str => {
199-
let slice_ty = match ty.kind() {
200-
ty::Slice(slice_ty) => *slice_ty,
201-
ty::Str => tcx.mk_ty(ty::Uint(ty::UintTy::U8)),
202-
_ => bug!("expected ty::Slice | ty::Str"),
203-
};
204-
205-
// Create a place for the underlying array
206-
let len = valtree.unwrap_branch().len() as u64;
207-
let arr_ty = tcx.mk_array(slice_ty, len as u64);
208-
let place = create_mplace_from_layout(ecx, arr_ty);
209-
debug!(?place);
197+
if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty()) {
198+
// We need to create `Allocation`s for custom DSTs
199+
200+
let (unsized_inner_ty, num_elems) = get_info_on_unsized_field(ty, valtree, tcx);
201+
let unsized_inner_ty = match unsized_inner_ty.kind() {
202+
ty::Str => tcx.mk_ty(ty::Uint(ty::UintTy::U8)),
203+
_ => unsized_inner_ty,
204+
};
205+
let unsized_inner_ty_size =
206+
tcx.layout_of(ty::ParamEnv::empty().and(unsized_inner_ty)).unwrap().layout.size();
207+
debug!(?unsized_inner_ty, ?unsized_inner_ty_size, ?num_elems);
208+
209+
// for custom DSTs only the last field/element is unsized, but we need to also allocate
210+
// space for the other fields/elements
211+
let layout = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap();
212+
let size_of_sized_part = layout.layout.size();
213+
214+
// Get the size of the memory behind the DST
215+
let dst_size = unsized_inner_ty_size.checked_mul(num_elems as u64, &tcx).unwrap();
216+
217+
let ptr = ecx
218+
.allocate_ptr(
219+
size_of_sized_part.checked_add(dst_size, &tcx).unwrap(),
220+
Align::from_bytes(1).unwrap(),
221+
MemoryKind::Stack,
222+
)
223+
.unwrap();
224+
debug!(?ptr);
210225

211-
place
212-
}
213-
ty::Adt(_, _) if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty()) => {
214-
// We need to create `Allocation`s for custom DSTs
215-
216-
let layout = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap();
217-
let sized_fields_size = layout.layout.size();
218-
let (unsized_inner_ty, num_elems) = get_info_on_unsized_field(ty, valtree, tcx);
219-
let unsized_inner_ty_size =
220-
tcx.layout_of(ty::ParamEnv::empty().and(unsized_inner_ty)).unwrap().layout.size();
221-
debug!(?unsized_inner_ty, ?unsized_inner_ty_size, ?num_elems);
222-
223-
// Get the size of the array behind the DST
224-
let dst_size = unsized_inner_ty_size.checked_mul(num_elems as u64, &tcx).unwrap();
225-
226-
let ptr = ecx
227-
.allocate_ptr(
228-
sized_fields_size.checked_add(dst_size, &tcx).unwrap(),
229-
Align::from_bytes(1).unwrap(),
230-
MemoryKind::Stack,
231-
)
232-
.unwrap();
233-
debug!(?ptr);
234-
235-
let place = MPlaceTy::from_aligned_ptr(ptr.into(), layout);
236-
debug!(?place);
226+
let mut place = MPlaceTy::from_aligned_ptr(ptr.into(), layout);
227+
place.meta = MemPlaceMeta::Meta(Scalar::from_u64(num_elems as u64));
228+
debug!(?place);
237229

238-
place
239-
}
240-
_ => create_mplace_from_layout(ecx, ty),
230+
place
231+
} else {
232+
create_mplace_from_layout(ecx, ty)
241233
}
242234
}
243235

244236
/// Converts a `ValTree` to a `ConstValue`, which is needed after mir
245237
/// construction has finished.
238+
// FIXME Merge `valtree_to_const_value` and `fill_place_recursively` into one function
246239
#[instrument(skip(tcx), level = "debug")]
247240
pub fn valtree_to_const_value<'tcx>(
248241
tcx: TyCtxt<'tcx>,
@@ -374,12 +367,9 @@ fn fill_place_recursively<'tcx>(
374367

375368
ecx.write_immediate(imm, &(*place).into()).unwrap();
376369
}
377-
ty::Adt(_, _) | ty::Tuple(_) | ty::Array(_, _) | ty::Str => {
370+
ty::Adt(_, _) | ty::Tuple(_) | ty::Array(_, _) | ty::Str | ty::Slice(_) => {
378371
let branches = valtree.unwrap_branch();
379372

380-
// Need to collect the length of the unsized field for meta info
381-
let mut unsized_meta_info = None;
382-
383373
// Need to downcast place for enums
384374
let (place_adjusted, branches, variant_idx) = match ty.kind() {
385375
ty::Adt(def, _) if def.is_enum() => {
@@ -399,48 +389,52 @@ fn fill_place_recursively<'tcx>(
399389
};
400390
debug!(?place_adjusted, ?branches);
401391

402-
// Create the places for the fields and fill them recursively
392+
// Create the places (by indexing into `place`) for the fields and fill
393+
// them recursively
403394
for (i, inner_valtree) in branches.iter().enumerate() {
404395
debug!(?i, ?inner_valtree);
405396

406-
if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty()) && i == branches.len() - 1 {
407-
// Note: For custom DSTs we need to manually process the last unsized field.
408-
// We created a `Pointer` for the `Allocation` of the complete sized version of
409-
// the Adt in `create_pointee_place` and now we fill that `Allocation` with the
410-
// values in the ValTree. For the unsized field we have to additionally add the meta
411-
// data.
412-
413-
let offset = place.layout.fields.offset(i);
414-
let (unsized_inner_ty, num_elems) = get_info_on_unsized_field(ty, valtree, tcx);
415-
unsized_meta_info = Some(num_elems);
416-
417-
// We create an array type to allow the recursive call to fill the place
418-
// corresponding to the array
419-
let arr_ty = tcx.mk_array(unsized_inner_ty, num_elems as u64);
420-
debug!(?arr_ty);
421-
let arr_layout = tcx.layout_of(ty::ParamEnv::empty().and(arr_ty)).unwrap();
422-
let mut place_arr =
423-
place.offset(offset, MemPlaceMeta::None, arr_layout, &tcx).unwrap();
424-
debug!(?place_arr);
425-
426-
fill_place_recursively(ecx, &mut place_arr, *inner_valtree);
427-
dump_place(&ecx, place_arr.into());
428-
429-
// Add the meta information for the unsized type
430-
place_arr.meta = MemPlaceMeta::Meta(Scalar::from_u64(num_elems as u64));
431-
432-
break;
433-
}
434-
435-
let mut place_inner = match *ty.kind() {
436-
ty::Adt(_, _) | ty::Tuple(_) => ecx.mplace_field(&place_adjusted, i).unwrap(),
437-
ty::Array(_, _) | ty::Str => {
438-
ecx.mplace_index(&place_adjusted, i as u64).unwrap()
397+
let mut place_inner = match ty.kind() {
398+
ty::Str | ty::Slice(_) => ecx.mplace_index(&place, i as u64).unwrap(),
399+
_ if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty())
400+
&& i == branches.len() - 1 =>
401+
{
402+
// Note: For custom DSTs we need to manually process the last unsized field.
403+
// We created a `Pointer` for the `Allocation` of the complete sized version of
404+
// the Adt in `create_pointee_place` and now we fill that `Allocation` with the
405+
// values in the ValTree. For the unsized field we have to additionally add the meta
406+
// data.
407+
408+
let (unsized_inner_ty, num_elems) =
409+
get_info_on_unsized_field(ty, valtree, tcx);
410+
debug!(?unsized_inner_ty);
411+
412+
let inner_ty = match ty.kind() {
413+
ty::Adt(def, substs) => {
414+
def.variant(VariantIdx::from_u32(0)).fields[i].ty(tcx, substs)
415+
}
416+
ty::Tuple(inner_tys) => inner_tys[i],
417+
_ => bug!("unexpected unsized type {:?}", ty),
418+
};
419+
420+
let inner_layout =
421+
tcx.layout_of(ty::ParamEnv::empty().and(inner_ty)).unwrap();
422+
debug!(?inner_layout);
423+
424+
let offset = place_adjusted.layout.fields.offset(i);
425+
place
426+
.offset(
427+
offset,
428+
MemPlaceMeta::Meta(Scalar::from_u64(num_elems as u64)),
429+
inner_layout,
430+
&tcx,
431+
)
432+
.unwrap()
439433
}
440-
_ => bug!(),
434+
_ => ecx.mplace_field(&place_adjusted, i).unwrap(),
441435
};
442-
debug!(?place_inner);
443436

437+
debug!(?place_inner);
444438
fill_place_recursively(ecx, &mut place_inner, *inner_valtree);
445439
dump_place(&ecx, place_inner.into());
446440
}
@@ -453,12 +447,7 @@ fn fill_place_recursively<'tcx>(
453447
ecx.write_discriminant(variant_idx, &(*place).into()).unwrap();
454448
}
455449

456-
// add meta information for unsized type
457-
if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty()) {
458-
place.meta =
459-
MemPlaceMeta::Meta(Scalar::from_u64(unsized_meta_info.unwrap() as u64));
460-
}
461-
450+
debug!("dump of place after writing discriminant:");
462451
dump_place(ecx, (*place).into());
463452
}
464453
_ => bug!("shouldn't have created a ValTree for {:?}", ty),

compiler/rustc_middle/src/ty/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ impl<'tcx> TyCtxt<'tcx> {
220220
self,
221221
mut ty: Ty<'tcx>,
222222
mut normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
223-
// This is a hack that is currently used to allow us to walk a ValTree
223+
// This is currently used to allow us to walk a ValTree
224224
// in lockstep with the type in order to get the ValTree branch that
225225
// corresponds to an unsized field.
226226
mut f: impl FnMut() -> (),

0 commit comments

Comments
 (0)