Skip to content

Commit

Permalink
type_size now returns None for unsized types
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Nov 11, 2016
1 parent 921f5af commit b2d476e
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 22 deletions.
29 changes: 17 additions & 12 deletions src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -290,16 +290,21 @@ 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())
}

fn type_align(&self, ty: Ty<'tcx>) -> usize {
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 {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)?;

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)?
Expand All @@ -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 {
Expand All @@ -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);
Expand All @@ -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(())
Expand Down Expand Up @@ -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;
Expand Down
16 changes: 10 additions & 6 deletions src/interpreter/terminator/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand Down Expand Up @@ -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");

Expand Down Expand Up @@ -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;

This comment has been minimized.

Copy link
@solson

solson Nov 11, 2016

Member

Why !0?

This comment has been minimized.

Copy link
@oli-obk

oli-obk Nov 11, 2016

Author Contributor

Because it's definitely gonna crash any code trying to allocate that. 42 would be fine, too ^^

let size_val = self.usize_primval(size);
self.write_primval(dest, size_val)?;
}
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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))
Expand Down
6 changes: 3 additions & 3 deletions src/interpreter/terminator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/interpreter/vtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit b2d476e

Please sign in to comment.