From b2d476eb387b739e37f28435613596e027241fc5 Mon Sep 17 00:00:00 2001 From: Oliver 'ker' Schneider Date: Fri, 11 Nov 2016 13:07:41 +0100 Subject: [PATCH] `type_size` now returns `None` for unsized types --- src/interpreter/mod.rs | 29 ++++++++++++++---------- src/interpreter/terminator/intrinsics.rs | 16 ++++++++----- src/interpreter/terminator/mod.rs | 6 ++--- src/interpreter/vtable.rs | 2 +- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index b15f8b2d2d..9c5dd30e37 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -182,7 +182,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ty: Ty<'tcx>, substs: &'tcx Substs<'tcx> ) -> EvalResult<'tcx, Pointer> { - let size = self.type_size_with_substs(ty, substs); + let size = self.type_size_with_substs(ty, substs).expect("cannot alloc memory for unsized type"); let align = self.type_align_with_substs(ty, substs); self.memory.allocate(size, align) } @@ -290,7 +290,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { self.tcx.normalize_associated_type(&substituted) } - fn type_size(&self, ty: Ty<'tcx>) -> usize { + fn type_size(&self, ty: Ty<'tcx>) -> Option { self.type_size_with_substs(ty, self.substs()) } @@ -298,8 +298,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { self.type_align_with_substs(ty, self.substs()) } - fn type_size_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> usize { - self.type_layout_with_substs(ty, substs).size(&self.tcx.data_layout).bytes() as usize + fn type_size_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> Option { + let layout = self.type_layout_with_substs(ty, substs); + if layout.is_unsized() { + None + } else { + Some(layout.size(&self.tcx.data_layout).bytes() as usize) + } } fn type_align_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> usize { @@ -480,7 +485,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Array { .. } => { let elem_size = match dest_ty.sty { - ty::TyArray(elem_ty, _) => self.type_size(elem_ty) as u64, + ty::TyArray(elem_ty, _) => self.type_size(elem_ty).expect("array elements are sized") as u64, _ => bug!("tried to assign {:?} to non-array type {:?}", kind, dest_ty), }; let offsets = (0..).map(|i| i * elem_size); @@ -534,7 +539,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } else { for operand in operands { let operand_ty = self.operand_ty(operand); - assert_eq!(self.type_size(operand_ty), 0); + assert_eq!(self.type_size(operand_ty), Some(0)); } let offset = self.nonnull_offset(dest_ty, nndiscr, discrfield)?; @@ -576,7 +581,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ty::TyArray(elem_ty, n) => (elem_ty, n), _ => bug!("tried to assign array-repeat to non-array type {:?}", dest_ty), }; - let elem_size = self.type_size(elem_ty); + let elem_size = self.type_size(elem_ty).expect("repeat element type must be sized"); let value = self.eval_operand(operand)?; // FIXME(solson) @@ -991,7 +996,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let (base_ptr, _) = base.to_ptr_and_extra(); let (elem_ty, len) = base.elem_ty_and_len(base_ty); - let elem_size = self.type_size(elem_ty); + let elem_size = self.type_size(elem_ty).expect("slice element must be sized"); let n_ptr = self.eval_operand(operand)?; let usize = self.tcx.types.usize; let n = self.value_to_primval(n_ptr, usize)? @@ -1007,7 +1012,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let (base_ptr, _) = base.to_ptr_and_extra(); let (elem_ty, n) = base.elem_ty_and_len(base_ty); - let elem_size = self.type_size(elem_ty); + let elem_size = self.type_size(elem_ty).expect("sequence element must be sized"); assert!(n >= min_length as u64); let index = if from_end { @@ -1026,7 +1031,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let (base_ptr, _) = base.to_ptr_and_extra(); let (elem_ty, n) = base.elem_ty_and_len(base_ty); - let elem_size = self.type_size(elem_ty); + let elem_size = self.type_size(elem_ty).expect("slice element must be sized"); assert!((from as u64) <= n - (to as u64)); let ptr = base_ptr.offset(from as isize * elem_size as isize); let extra = LvalueExtra::Length(n - to as u64 - from as u64); @@ -1046,7 +1051,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } fn copy(&mut self, src: Pointer, dest: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, ()> { - let size = self.type_size(ty); + let size = self.type_size(ty).expect("cannot copy from an unsized type"); let align = self.type_align(ty); self.memory.copy(src, dest, size, align)?; Ok(()) @@ -1512,7 +1517,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { for (i, (src_f, dst_f)) in iter { let src_fty = monomorphize_field_ty(self.tcx, src_f, substs_a); let dst_fty = monomorphize_field_ty(self.tcx, dst_f, substs_b); - if self.type_size(dst_fty) == 0 { + if self.type_size(dst_fty) == Some(0) { continue; } let src_field_offset = self.get_field_offset(src_ty, i)?.bytes() as isize; diff --git a/src/interpreter/terminator/intrinsics.rs b/src/interpreter/terminator/intrinsics.rs index 9161f6e35b..280cabc078 100644 --- a/src/interpreter/terminator/intrinsics.rs +++ b/src/interpreter/terminator/intrinsics.rs @@ -96,7 +96,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "copy_nonoverlapping" => { // FIXME: check whether overlapping occurs let elem_ty = substs.type_at(0); - let elem_size = self.type_size(elem_ty); + let elem_size = self.type_size(elem_ty).expect("cannot copy unsized value"); let elem_align = self.type_align(elem_ty); let src = arg_vals[0].read_ptr(&self.memory)?; let dest = arg_vals[1].read_ptr(&self.memory)?; @@ -230,7 +230,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "offset" => { let pointee_ty = substs.type_at(0); - let pointee_size = self.type_size(pointee_ty) as isize; + let pointee_size = self.type_size(pointee_ty).expect("cannot offset a pointer to an unsized type") as isize; let offset = self.value_to_primval(arg_vals[1], isize)? .expect_int("offset second arg not isize"); @@ -281,7 +281,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "size_of" => { let ty = substs.type_at(0); - let size = self.type_size(ty) as u64; + // FIXME: change the `box_free` lang item to take `T: ?Sized` and have it use the + // `size_of_val` intrinsic, then change this back to + // .expect("size_of intrinsic called on unsized value") + // see https://github.com/rust-lang/rust/pull/37708 + let size = self.type_size(ty).unwrap_or(!0) as u64; let size_val = self.usize_primval(size); self.write_primval(dest, size_val)?; } @@ -360,8 +364,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { value: Value, ) -> EvalResult<'tcx, (u64, u64)> { let pointer_size = self.memory.pointer_size(); - if self.type_is_sized(ty) { - Ok((self.type_size(ty) as u64, self.type_align(ty) as 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) => { @@ -435,7 +439,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ty::TySlice(_) | ty::TyStr => { let elem_ty = ty.sequence_element_type(self.tcx); - let elem_size = self.type_size(elem_ty) as u64; + let elem_size = self.type_size(elem_ty).expect("slice element must be sized") as u64; let len = value.expect_slice_len(&self.memory)?; let align = self.type_align(elem_ty); Ok((len * elem_size, align as u64)) diff --git a/src/interpreter/terminator/mod.rs b/src/interpreter/terminator/mod.rs index 1ddcee3472..0097e4d2c2 100644 --- a/src/interpreter/terminator/mod.rs +++ b/src/interpreter/terminator/mod.rs @@ -193,7 +193,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Abi::C => { let ty = fn_ty.sig.0.output; - let size = self.type_size(ty); + let size = self.type_size(ty).expect("function return type cannot be unsized"); let (ret, target) = destination.unwrap(); self.call_c_abi(def_id, arg_operands, ret, size)?; self.goto_block(target); @@ -655,7 +655,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Lvalue::Ptr { ptr, extra: LvalueExtra::Length(len) } => (ptr, len as isize), _ => bug!("expected an lvalue with a length"), }; - let size = self.type_size(elem_ty) as isize; + let size = self.type_size(elem_ty).expect("slice element must be sized") as isize; // FIXME: this creates a lot of stack frames if the element type has // a drop impl for i in 0..len { @@ -668,7 +668,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Lvalue::Ptr { ptr, extra } => (ptr, extra), _ => bug!("expected an lvalue with optional extra data"), }; - let size = self.type_size(elem_ty) as isize; + let size = self.type_size(elem_ty).expect("array element cannot be unsized") as isize; // FIXME: this creates a lot of stack frames if the element type has // a drop impl for i in 0..len { diff --git a/src/interpreter/vtable.rs b/src/interpreter/vtable.rs index 17f2c6b702..7320872724 100644 --- a/src/interpreter/vtable.rs +++ b/src/interpreter/vtable.rs @@ -78,7 +78,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } }).collect(); - let size = self.type_size(trait_ref.self_ty()); + let size = self.type_size(trait_ref.self_ty()).expect("can't create a vtable for an unsized type"); let align = self.type_align(trait_ref.self_ty()); let ptr_size = self.memory.pointer_size();