Skip to content

Commit 5aed318

Browse files
authored
Merge pull request rust-lang#281 from RalfJung/unsized
fix size_of_val on unsized tuples
2 parents 8deb938 + 5d27b94 commit 5aed318

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

src/librustc_mir/interpret/eval_context.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
277277
self.tcx.erase_regions(&value)
278278
}
279279

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

310313
// Recurse to get the size of the dynamically sized field (must be
311314
// the last field).
312-
let last_field = def.struct_variant().fields.last().unwrap();
313-
let field_ty = self.field_ty(substs, last_field);
314-
let (unsized_size, unsized_align) = self.size_and_align_of_dst(field_ty, value)?;
315+
let (unsized_size, unsized_align) = match ty.sty {
316+
ty::TyAdt(def, substs) => {
317+
let last_field = def.struct_variant().fields.last().unwrap();
318+
let field_ty = self.field_ty(substs, last_field);
319+
self.size_and_align_of_dst(field_ty, value)?
320+
}
321+
ty::TyTuple(ref types, _) => {
322+
let field_ty = types.last().unwrap();
323+
let field_ty = self.tcx.normalize_associated_type(field_ty);
324+
self.size_and_align_of_dst(field_ty, value)?
325+
}
326+
_ => bug!("We already checked that we know this type"),
327+
};
315328

316329
// FIXME (#26403, #27023): We should be adding padding
317330
// to `sized_size` (to accommodate the `unsized_align`

tests/run-pass-fullmir/unsized-tuple-impls.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
#![feature(unsized_tuple_coercion)]
12+
use std::mem;
1213

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

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

0 commit comments

Comments
 (0)