From c533cf84969e7c04cc2616525e64bae2092884bd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 2 Aug 2017 15:29:13 -0700 Subject: [PATCH 1/2] fix size_of_val on unsized tuples --- src/librustc_mir/interpret/eval_context.rs | 20 ++++++++++++++----- tests/run-pass-fullmir/unsized-tuple-impls.rs | 2 ++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 86e5d855f44a..30a305a7b60b 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -280,13 +280,13 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { pub fn size_and_align_of_dst( &mut self, ty: ty::Ty<'tcx>, - value: Value, + value: Value, // This has to be a fat ptr; we only care about the "extra" data in it. ) -> EvalResult<'tcx, (u64, u64)> { if let Some(size) = self.type_size(ty)? { 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, @@ -309,9 +309,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` diff --git a/tests/run-pass-fullmir/unsized-tuple-impls.rs b/tests/run-pass-fullmir/unsized-tuple-impls.rs index d332f7be8330..ccb6883e8733 100644 --- a/tests/run-pass-fullmir/unsized-tuple-impls.rs +++ b/tests/run-pass-fullmir/unsized-tuple-impls.rs @@ -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]); @@ -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); } From 5d27b94b04b87f6ca65c770e8e788c17f7af7a13 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 3 Aug 2017 11:06:25 -0700 Subject: [PATCH 2/2] fix comment --- src/librustc_mir/interpret/eval_context.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 30a305a7b60b..16015c4bf3a2 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -277,10 +277,13 @@ 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>, - value: Value, // This has to be a fat ptr; we only care about the "extra" data in it. + value: Value, ) -> EvalResult<'tcx, (u64, u64)> { if let Some(size) = self.type_size(ty)? { Ok((size as u64, self.type_align(ty)? as u64))