1
Fork 0

type_size now returns None for unsized types

This commit is contained in:
Oliver 'ker' Schneider 2016-11-11 13:07:41 +01:00
parent 921f5af1fe
commit b2d476eb38
4 changed files with 31 additions and 22 deletions

View file

@ -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<usize> {
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<usize> {
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;

View file

@ -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))

View file

@ -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 {

View file

@ -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();