Skip to content

Commit

Permalink
Merge pull request rust-lang#281 from RalfJung/unsized
Browse files Browse the repository at this point in the history
fix size_of_val on unsized tuples
  • Loading branch information
RalfJung authored Aug 3, 2017
2 parents 8deb938 + 5d27b94 commit 5aed318
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 4 deletions.
21 changes: 17 additions & 4 deletions src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,9 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
self.tcx.erase_regions(&value)
}

/// Return the size and aligment of the value at the given type.
/// Note that the value does not matter if the type is sized. For unsized types,
/// the value has to be a fat pointer, and we only care about the "extra" data in it.
pub fn size_and_align_of_dst(
&mut self,
ty: ty::Ty<'tcx>,
Expand All @@ -286,7 +289,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
Ok((size as u64, self.type_align(ty)? as u64))
} else {
match ty.sty {
ty::TyAdt(def, substs) => {
ty::TyAdt(..) | ty::TyTuple(..) => {
// First get the size of all statically known fields.
// Don't use type_of::sizing_type_of because that expects t to be sized,
// and it also rounds up to alignment, which we want to avoid,
Expand All @@ -309,9 +312,19 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {

// Recurse to get the size of the dynamically sized field (must be
// the last field).
let last_field = def.struct_variant().fields.last().unwrap();
let field_ty = self.field_ty(substs, last_field);
let (unsized_size, unsized_align) = self.size_and_align_of_dst(field_ty, value)?;
let (unsized_size, unsized_align) = match ty.sty {
ty::TyAdt(def, substs) => {
let last_field = def.struct_variant().fields.last().unwrap();
let field_ty = self.field_ty(substs, last_field);
self.size_and_align_of_dst(field_ty, value)?
}
ty::TyTuple(ref types, _) => {
let field_ty = types.last().unwrap();
let field_ty = self.tcx.normalize_associated_type(field_ty);
self.size_and_align_of_dst(field_ty, value)?
}
_ => bug!("We already checked that we know this type"),
};

// FIXME (#26403, #27023): We should be adding padding
// to `sized_size` (to accommodate the `unsized_align`
Expand Down
2 changes: 2 additions & 0 deletions tests/run-pass-fullmir/unsized-tuple-impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// except according to those terms.

#![feature(unsized_tuple_coercion)]
use std::mem;

fn main() {
let x : &(i32, i32, [i32]) = &(0, 1, [2, 3]);
Expand All @@ -18,4 +19,5 @@ fn main() {
assert_eq!(a, [x, y]);

assert_eq!(&format!("{:?}", a), "[(0, 1, [2, 3]), (0, 1, [2, 3, 4])]");
assert_eq!(mem::size_of_val(x), 16);
}

0 comments on commit 5aed318

Please sign in to comment.