Skip to content

Commit 61e7ba1

Browse files
committed
fix dynamically determining size and alignment
1 parent e314a4e commit 61e7ba1

File tree

1 file changed

+20
-17
lines changed

1 file changed

+20
-17
lines changed

src/librustc_mir/interpret/eval_context.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use syntax::source_map::{self, Span};
2424
use syntax::ast::Mutability;
2525

2626
use super::{
27-
Value, ValTy, Operand, MemPlace, MPlaceTy, Place, PlaceExtra,
27+
Value, Operand, MemPlace, MPlaceTy, Place, PlaceExtra,
2828
Memory, Machine
2929
};
3030

@@ -466,18 +466,19 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
466466
self.layout_of(local_ty)
467467
}
468468

469-
/// Return the size and alignment of the value at the given type.
469+
/// Return the actual dynamic size and alignment of the place at the given type.
470470
/// Note that the value does not matter if the type is sized. For unsized types,
471471
/// the value has to be a fat pointer, and we only care about the "extra" data in it.
472-
pub fn size_and_align_of_val(
472+
pub fn size_and_align_of_mplace(
473473
&self,
474-
val: ValTy<'tcx>,
474+
mplace: MPlaceTy<'tcx>,
475475
) -> EvalResult<'tcx, (Size, Align)> {
476-
let pointee_ty = val.layout.ty.builtin_deref(true).unwrap().ty;
477-
let layout = self.layout_of(pointee_ty)?;
478-
if !layout.is_unsized() {
479-
Ok(layout.size_and_align())
476+
if let PlaceExtra::None = mplace.extra {
477+
assert!(!mplace.layout.is_unsized());
478+
Ok(mplace.layout.size_and_align())
480479
} else {
480+
let layout = mplace.layout;
481+
assert!(layout.is_unsized());
481482
match layout.ty.sty {
482483
ty::TyAdt(..) | ty::TyTuple(..) => {
483484
// First get the size of all statically known fields.
@@ -498,12 +499,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
498499

499500
// Recurse to get the size of the dynamically sized field (must be
500501
// the last field).
501-
let field_layout = layout.field(self, layout.fields.count() - 1)?;
502-
let (unsized_size, unsized_align) =
503-
self.size_and_align_of_val(ValTy {
504-
value: val.value,
505-
layout: field_layout
506-
})?;
502+
let field = self.mplace_field(mplace, layout.fields.count() as u64 - 1)?;
503+
let (unsized_size, unsized_align) = self.size_and_align_of_mplace(field)?;
507504

508505
// FIXME (#26403, #27023): We should be adding padding
509506
// to `sized_size` (to accommodate the `unsized_align`
@@ -533,18 +530,24 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
533530
Ok((size.abi_align(align), align))
534531
}
535532
ty::TyDynamic(..) => {
536-
let (_, vtable) = val.to_scalar_dyn_trait()?;
533+
let vtable = match mplace.extra {
534+
PlaceExtra::Vtable(vtable) => vtable,
535+
_ => bug!("Expected vtable"),
536+
};
537537
// the second entry in the vtable is the dynamic size of the object.
538538
self.read_size_and_align_from_vtable(vtable)
539539
}
540540

541541
ty::TySlice(_) | ty::TyStr => {
542+
let len = match mplace.extra {
543+
PlaceExtra::Length(len) => len,
544+
_ => bug!("Expected length"),
545+
};
542546
let (elem_size, align) = layout.field(self, 0)?.size_and_align();
543-
let (_, len) = val.to_scalar_slice(self)?;
544547
Ok((elem_size * len, align))
545548
}
546549

547-
_ => bug!("size_of_val::<{:?}>", layout.ty),
550+
_ => bug!("size_of_val::<{:?}> not supported", layout.ty),
548551
}
549552
}
550553
}

0 commit comments

Comments
 (0)