type_size
now returns None
for unsized types
This commit is contained in:
parent
921f5af1fe
commit
b2d476eb38
4 changed files with 31 additions and 22 deletions
|
@ -182,7 +182,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
substs: &'tcx Substs<'tcx>
|
substs: &'tcx Substs<'tcx>
|
||||||
) -> EvalResult<'tcx, Pointer> {
|
) -> 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);
|
let align = self.type_align_with_substs(ty, substs);
|
||||||
self.memory.allocate(size, align)
|
self.memory.allocate(size, align)
|
||||||
}
|
}
|
||||||
|
@ -290,7 +290,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
self.tcx.normalize_associated_type(&substituted)
|
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())
|
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())
|
self.type_align_with_substs(ty, self.substs())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_size_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> usize {
|
fn type_size_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> Option<usize> {
|
||||||
self.type_layout_with_substs(ty, substs).size(&self.tcx.data_layout).bytes() as 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 {
|
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 { .. } => {
|
Array { .. } => {
|
||||||
let elem_size = match dest_ty.sty {
|
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),
|
_ => bug!("tried to assign {:?} to non-array type {:?}", kind, dest_ty),
|
||||||
};
|
};
|
||||||
let offsets = (0..).map(|i| i * elem_size);
|
let offsets = (0..).map(|i| i * elem_size);
|
||||||
|
@ -534,7 +539,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
for operand in operands {
|
for operand in operands {
|
||||||
let operand_ty = self.operand_ty(operand);
|
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)?;
|
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),
|
ty::TyArray(elem_ty, n) => (elem_ty, n),
|
||||||
_ => bug!("tried to assign array-repeat to non-array type {:?}", dest_ty),
|
_ => 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)?;
|
let value = self.eval_operand(operand)?;
|
||||||
|
|
||||||
// FIXME(solson)
|
// FIXME(solson)
|
||||||
|
@ -991,7 +996,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
let (base_ptr, _) = base.to_ptr_and_extra();
|
let (base_ptr, _) = base.to_ptr_and_extra();
|
||||||
|
|
||||||
let (elem_ty, len) = base.elem_ty_and_len(base_ty);
|
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 n_ptr = self.eval_operand(operand)?;
|
||||||
let usize = self.tcx.types.usize;
|
let usize = self.tcx.types.usize;
|
||||||
let n = self.value_to_primval(n_ptr, 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 (base_ptr, _) = base.to_ptr_and_extra();
|
||||||
|
|
||||||
let (elem_ty, n) = base.elem_ty_and_len(base_ty);
|
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);
|
assert!(n >= min_length as u64);
|
||||||
|
|
||||||
let index = if from_end {
|
let index = if from_end {
|
||||||
|
@ -1026,7 +1031,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
let (base_ptr, _) = base.to_ptr_and_extra();
|
let (base_ptr, _) = base.to_ptr_and_extra();
|
||||||
|
|
||||||
let (elem_ty, n) = base.elem_ty_and_len(base_ty);
|
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));
|
assert!((from as u64) <= n - (to as u64));
|
||||||
let ptr = base_ptr.offset(from as isize * elem_size as isize);
|
let ptr = base_ptr.offset(from as isize * elem_size as isize);
|
||||||
let extra = LvalueExtra::Length(n - to as u64 - from as u64);
|
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, ()> {
|
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);
|
let align = self.type_align(ty);
|
||||||
self.memory.copy(src, dest, size, align)?;
|
self.memory.copy(src, dest, size, align)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1512,7 +1517,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
for (i, (src_f, dst_f)) in iter {
|
for (i, (src_f, dst_f)) in iter {
|
||||||
let src_fty = monomorphize_field_ty(self.tcx, src_f, substs_a);
|
let src_fty = monomorphize_field_ty(self.tcx, src_f, substs_a);
|
||||||
let dst_fty = monomorphize_field_ty(self.tcx, dst_f, substs_b);
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
let src_field_offset = self.get_field_offset(src_ty, i)?.bytes() as isize;
|
let src_field_offset = self.get_field_offset(src_ty, i)?.bytes() as isize;
|
||||||
|
|
|
@ -96,7 +96,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
"copy_nonoverlapping" => {
|
"copy_nonoverlapping" => {
|
||||||
// FIXME: check whether overlapping occurs
|
// FIXME: check whether overlapping occurs
|
||||||
let elem_ty = substs.type_at(0);
|
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 elem_align = self.type_align(elem_ty);
|
||||||
let src = arg_vals[0].read_ptr(&self.memory)?;
|
let src = arg_vals[0].read_ptr(&self.memory)?;
|
||||||
let dest = arg_vals[1].read_ptr(&self.memory)?;
|
let dest = arg_vals[1].read_ptr(&self.memory)?;
|
||||||
|
@ -230,7 +230,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
|
|
||||||
"offset" => {
|
"offset" => {
|
||||||
let pointee_ty = substs.type_at(0);
|
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)?
|
let offset = self.value_to_primval(arg_vals[1], isize)?
|
||||||
.expect_int("offset second arg not isize");
|
.expect_int("offset second arg not isize");
|
||||||
|
|
||||||
|
@ -281,7 +281,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
|
|
||||||
"size_of" => {
|
"size_of" => {
|
||||||
let ty = substs.type_at(0);
|
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);
|
let size_val = self.usize_primval(size);
|
||||||
self.write_primval(dest, size_val)?;
|
self.write_primval(dest, size_val)?;
|
||||||
}
|
}
|
||||||
|
@ -360,8 +364,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
value: Value,
|
value: Value,
|
||||||
) -> EvalResult<'tcx, (u64, u64)> {
|
) -> EvalResult<'tcx, (u64, u64)> {
|
||||||
let pointer_size = self.memory.pointer_size();
|
let pointer_size = self.memory.pointer_size();
|
||||||
if self.type_is_sized(ty) {
|
if let Some(size) = self.type_size(ty) {
|
||||||
Ok((self.type_size(ty) as u64, self.type_align(ty) as u64))
|
Ok((size as u64, self.type_align(ty) as u64))
|
||||||
} else {
|
} else {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyAdt(def, substs) => {
|
ty::TyAdt(def, substs) => {
|
||||||
|
@ -435,7 +439,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
|
|
||||||
ty::TySlice(_) | ty::TyStr => {
|
ty::TySlice(_) | ty::TyStr => {
|
||||||
let elem_ty = ty.sequence_element_type(self.tcx);
|
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 len = value.expect_slice_len(&self.memory)?;
|
||||||
let align = self.type_align(elem_ty);
|
let align = self.type_align(elem_ty);
|
||||||
Ok((len * elem_size, align as u64))
|
Ok((len * elem_size, align as u64))
|
||||||
|
|
|
@ -193,7 +193,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
|
|
||||||
Abi::C => {
|
Abi::C => {
|
||||||
let ty = fn_ty.sig.0.output;
|
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();
|
let (ret, target) = destination.unwrap();
|
||||||
self.call_c_abi(def_id, arg_operands, ret, size)?;
|
self.call_c_abi(def_id, arg_operands, ret, size)?;
|
||||||
self.goto_block(target);
|
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),
|
Lvalue::Ptr { ptr, extra: LvalueExtra::Length(len) } => (ptr, len as isize),
|
||||||
_ => bug!("expected an lvalue with a length"),
|
_ => 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
|
// FIXME: this creates a lot of stack frames if the element type has
|
||||||
// a drop impl
|
// a drop impl
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
|
@ -668,7 +668,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
Lvalue::Ptr { ptr, extra } => (ptr, extra),
|
Lvalue::Ptr { ptr, extra } => (ptr, extra),
|
||||||
_ => bug!("expected an lvalue with optional extra data"),
|
_ => 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
|
// FIXME: this creates a lot of stack frames if the element type has
|
||||||
// a drop impl
|
// a drop impl
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
|
|
|
@ -78,7 +78,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}).collect();
|
}).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 align = self.type_align(trait_ref.self_ty());
|
||||||
|
|
||||||
let ptr_size = self.memory.pointer_size();
|
let ptr_size = self.memory.pointer_size();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue