layout computation can fail, make it fail with a miri error
This commit is contained in:
parent
26ccc1e4bc
commit
986b3a07c2
@ -1,13 +1,13 @@
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use rustc::mir;
|
||||
use rustc::ty::{BareFnTy, Ty, FnSig};
|
||||
use rustc::ty::{BareFnTy, Ty, FnSig, layout};
|
||||
use syntax::abi::Abi;
|
||||
use memory::Pointer;
|
||||
use rustc_const_math::ConstMathErr;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum EvalError<'tcx> {
|
||||
FunctionPointerTyMismatch(Abi, &'tcx FnSig<'tcx>, &'tcx BareFnTy<'tcx>),
|
||||
NoMirFor(String),
|
||||
@ -50,6 +50,7 @@ pub enum EvalError<'tcx> {
|
||||
TypeNotPrimitive(Ty<'tcx>),
|
||||
ReallocatedFrozenMemory,
|
||||
DeallocatedFrozenMemory,
|
||||
Layout(layout::LayoutError<'tcx>),
|
||||
}
|
||||
|
||||
pub type EvalResult<'tcx, T> = Result<T, EvalError<'tcx>>;
|
||||
@ -116,6 +117,8 @@ impl<'tcx> Error for EvalError<'tcx> {
|
||||
"tried to reallocate frozen memory",
|
||||
EvalError::DeallocatedFrozenMemory =>
|
||||
"tried to deallocate frozen memory",
|
||||
EvalError::Layout(_) =>
|
||||
"rustc layout computation failed",
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,6 +149,8 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
|
||||
has, required),
|
||||
EvalError::TypeNotPrimitive(ref ty) =>
|
||||
write!(f, "expected primitive type, got {}", ty),
|
||||
EvalError::Layout(ref err) =>
|
||||
write!(f, "rustc layout computation failed: {:?}", err),
|
||||
_ => write!(f, "{}", self.description()),
|
||||
}
|
||||
}
|
||||
|
@ -188,8 +188,8 @@ 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).expect("cannot alloc memory for unsized type");
|
||||
let align = self.type_align_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)
|
||||
}
|
||||
|
||||
@ -292,38 +292,38 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
self.tcx.normalize_associated_type(&substituted)
|
||||
}
|
||||
|
||||
fn type_size(&self, ty: Ty<'tcx>) -> Option<usize> {
|
||||
fn type_size(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<usize>> {
|
||||
self.type_size_with_substs(ty, self.substs())
|
||||
}
|
||||
|
||||
fn type_align(&self, ty: Ty<'tcx>) -> usize {
|
||||
fn type_align(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, usize> {
|
||||
self.type_align_with_substs(ty, self.substs())
|
||||
}
|
||||
|
||||
fn type_size_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> Option<usize> {
|
||||
let layout = self.type_layout_with_substs(ty, substs);
|
||||
fn type_size_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> EvalResult<'tcx, Option<usize>> {
|
||||
let layout = self.type_layout_with_substs(ty, substs)?;
|
||||
if layout.is_unsized() {
|
||||
None
|
||||
Ok(None)
|
||||
} else {
|
||||
Some(layout.size(&self.tcx.data_layout).bytes() as usize)
|
||||
Ok(Some(layout.size(&self.tcx.data_layout).bytes() as usize))
|
||||
}
|
||||
}
|
||||
|
||||
fn type_align_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> usize {
|
||||
self.type_layout_with_substs(ty, substs).align(&self.tcx.data_layout).abi() as usize
|
||||
fn type_align_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> EvalResult<'tcx, usize> {
|
||||
self.type_layout_with_substs(ty, substs).map(|layout| layout.align(&self.tcx.data_layout).abi() as usize)
|
||||
}
|
||||
|
||||
fn type_layout(&self, ty: Ty<'tcx>) -> &'tcx Layout {
|
||||
fn type_layout(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, &'tcx Layout> {
|
||||
self.type_layout_with_substs(ty, self.substs())
|
||||
}
|
||||
|
||||
fn type_layout_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> &'tcx Layout {
|
||||
fn type_layout_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> EvalResult<'tcx, &'tcx Layout> {
|
||||
// TODO(solson): Is this inefficient? Needs investigation.
|
||||
let ty = self.monomorphize(ty, substs);
|
||||
|
||||
self.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
|
||||
// TODO(solson): Report this error properly.
|
||||
ty.layout(&infcx).unwrap()
|
||||
ty.layout(&infcx).map_err(EvalError::Layout)
|
||||
})
|
||||
}
|
||||
|
||||
@ -482,7 +482,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
) -> EvalResult<'tcx, ()> {
|
||||
let dest = self.eval_lvalue(lvalue)?;
|
||||
let dest_ty = self.lvalue_ty(lvalue);
|
||||
let dest_layout = self.type_layout(dest_ty);
|
||||
let dest_layout = self.type_layout(dest_ty)?;
|
||||
|
||||
use rustc::mir::Rvalue::*;
|
||||
match *rvalue {
|
||||
@ -516,7 +516,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
|
||||
Array { .. } => {
|
||||
let elem_size = match dest_ty.sty {
|
||||
ty::TyArray(elem_ty, _) => self.type_size(elem_ty).expect("array elements are sized") 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);
|
||||
@ -556,9 +556,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
if let Some(operand) = operands.get(0) {
|
||||
assert_eq!(operands.len(), 1);
|
||||
let operand_ty = self.operand_ty(operand);
|
||||
assert_eq!(self.type_size(operand_ty), Some(0));
|
||||
assert_eq!(self.type_size(operand_ty)?, Some(0));
|
||||
}
|
||||
let value_size = self.type_size(dest_ty).expect("pointer types are sized");
|
||||
let value_size = self.type_size(dest_ty)?.expect("pointer types are sized");
|
||||
let zero = PrimVal::from_int_with_size(0, value_size);
|
||||
self.write_primval(dest, zero)?;
|
||||
}
|
||||
@ -575,7 +575,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), Some(0));
|
||||
assert_eq!(self.type_size(operand_ty)?, Some(0));
|
||||
}
|
||||
let (offset, ty) = self.nonnull_offset_and_ty(dest_ty, nndiscr, discrfield)?;
|
||||
|
||||
@ -583,7 +583,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let dest = self.force_allocation(dest)?.to_ptr();
|
||||
|
||||
let dest = dest.offset(offset.bytes() as isize);
|
||||
let dest_size = self.type_size(ty).expect("bad StructWrappedNullablePointer discrfield");
|
||||
let dest_size = self.type_size(ty)?.expect("bad StructWrappedNullablePointer discrfield");
|
||||
try!(self.memory.write_int(dest, 0, dest_size));
|
||||
}
|
||||
} else {
|
||||
@ -625,8 +625,8 @@ 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).expect("repeat element type must be sized");
|
||||
self.inc_step_counter_and_check_limit(length as u64)?;
|
||||
let elem_size = self.type_size(elem_ty)?.expect("repeat element type must be sized");
|
||||
let value = self.eval_operand(operand)?;
|
||||
|
||||
// FIXME(solson)
|
||||
@ -797,7 +797,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn get_field_offset(&self, ty: Ty<'tcx>, field_index: usize) -> EvalResult<'tcx, Size> {
|
||||
let layout = self.type_layout(ty);
|
||||
let layout = self.type_layout(ty)?;
|
||||
|
||||
use rustc::ty::layout::Layout::*;
|
||||
match *layout {
|
||||
@ -816,7 +816,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn get_field_count(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, usize> {
|
||||
let layout = self.type_layout(ty);
|
||||
let layout = self.type_layout(ty)?;
|
||||
|
||||
use rustc::ty::layout::Layout::*;
|
||||
match *layout {
|
||||
@ -944,7 +944,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
) -> EvalResult<'tcx, Lvalue<'tcx>> {
|
||||
let base = self.eval_lvalue(&proj.base)?;
|
||||
let base_ty = self.lvalue_ty(&proj.base);
|
||||
let base_layout = self.type_layout(base_ty);
|
||||
let base_layout = self.type_layout(base_ty)?;
|
||||
|
||||
use rustc::mir::ProjectionElem::*;
|
||||
let (ptr, extra) = match proj.elem {
|
||||
@ -1043,7 +1043,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).expect("slice element must be sized");
|
||||
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)?
|
||||
@ -1059,7 +1059,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).expect("sequence element must be sized");
|
||||
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 {
|
||||
@ -1078,7 +1078,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).expect("slice element must be sized");
|
||||
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);
|
||||
@ -1098,8 +1098,8 @@ 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).expect("cannot copy from an unsized type");
|
||||
let align = self.type_align(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(())
|
||||
}
|
||||
@ -1368,7 +1368,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
|
||||
ty::TyAdt(..) => {
|
||||
use rustc::ty::layout::Layout::*;
|
||||
if let CEnum { discr, signed, .. } = *self.type_layout(ty) {
|
||||
if let CEnum { discr, signed, .. } = *self.type_layout(ty)? {
|
||||
let size = discr.size().bytes() as usize;
|
||||
if signed {
|
||||
PrimValKind::from_int_size(size)
|
||||
@ -1464,7 +1464,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
|
||||
ty::TyAdt(..) => {
|
||||
use rustc::ty::layout::Layout::*;
|
||||
if let CEnum { discr, signed, .. } = *self.type_layout(ty) {
|
||||
if let CEnum { discr, signed, .. } = *self.type_layout(ty)? {
|
||||
let size = discr.size().bytes() as usize;
|
||||
if signed {
|
||||
let n = self.memory.read_int(ptr, size)?;
|
||||
@ -1564,7 +1564,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) == Some(0) {
|
||||
if self.type_size(dst_fty)? == Some(0) {
|
||||
continue;
|
||||
}
|
||||
let src_field_offset = self.get_field_offset(src_ty, i)?.bytes() as isize;
|
||||
|
@ -144,8 +144,8 @@ 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).expect("cannot copy unsized value");
|
||||
let elem_align = self.type_align(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)?;
|
||||
let count = self.value_to_primval(arg_vals[2], usize)?
|
||||
@ -252,14 +252,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
|
||||
"min_align_of" => {
|
||||
let elem_ty = substs.type_at(0);
|
||||
let elem_align = self.type_align(elem_ty);
|
||||
let elem_align = self.type_align(elem_ty)?;
|
||||
let align_val = self.usize_primval(elem_align as u64);
|
||||
self.write_primval(dest, align_val)?;
|
||||
}
|
||||
|
||||
"pref_align_of" => {
|
||||
let ty = substs.type_at(0);
|
||||
let layout = self.type_layout(ty);
|
||||
let layout = self.type_layout(ty)?;
|
||||
let align = layout.align(&self.tcx.data_layout).pref();
|
||||
let align_val = self.usize_primval(align);
|
||||
self.write_primval(dest, align_val)?;
|
||||
@ -280,7 +280,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
|
||||
"offset" => {
|
||||
let pointee_ty = substs.type_at(0);
|
||||
let pointee_size = self.type_size(pointee_ty).expect("cannot offset a pointer to an unsized type") 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");
|
||||
|
||||
@ -335,7 +335,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
// `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 = self.type_size(ty)?.unwrap_or(!0) as u64;
|
||||
let size_val = self.usize_primval(size);
|
||||
self.write_primval(dest, size_val)?;
|
||||
}
|
||||
@ -414,8 +414,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
value: Value,
|
||||
) -> EvalResult<'tcx, (u64, u64)> {
|
||||
let pointer_size = self.memory.pointer_size();
|
||||
if let Some(size) = self.type_size(ty) {
|
||||
Ok((size 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) => {
|
||||
@ -424,7 +424,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
// and it also rounds up to alignment, which we want to avoid,
|
||||
// as the unsized field's alignment could be smaller.
|
||||
assert!(!ty.is_simd());
|
||||
let layout = self.type_layout(ty);
|
||||
let layout = self.type_layout(ty)?;
|
||||
debug!("DST {} layout: {:?}", ty, layout);
|
||||
|
||||
let (sized_size, sized_align) = match *layout {
|
||||
@ -489,9 +489,9 @@ 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).expect("slice element must be sized") as u64;
|
||||
let elem_size = self.type_size(elem_ty)?.expect("slice element must be sized") as u64;
|
||||
let (_, len) = value.expect_slice(&self.memory)?;
|
||||
let align = self.type_align(elem_ty);
|
||||
let align = self.type_align(elem_ty)?;
|
||||
Ok((len * elem_size, align as u64))
|
||||
}
|
||||
|
||||
|
@ -183,7 +183,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
match fn_ty.abi {
|
||||
Abi::RustIntrinsic => {
|
||||
let ty = fn_ty.sig.0.output;
|
||||
let layout = self.type_layout(ty);
|
||||
let layout = self.type_layout(ty)?;
|
||||
let (ret, target) = destination.unwrap();
|
||||
self.call_intrinsic(def_id, substs, arg_operands, ret, ty, layout, target)?;
|
||||
Ok(())
|
||||
@ -191,7 +191,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
|
||||
Abi::C => {
|
||||
let ty = fn_ty.sig.0.output;
|
||||
let size = self.type_size(ty).expect("function return type cannot be unsized");
|
||||
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);
|
||||
@ -248,7 +248,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
|
||||
fn read_discriminant_value(&self, adt_ptr: Pointer, adt_ty: Ty<'tcx>) -> EvalResult<'tcx, u64> {
|
||||
use rustc::ty::layout::Layout::*;
|
||||
let adt_layout = self.type_layout(adt_ty);
|
||||
let adt_layout = self.type_layout(adt_ty)?;
|
||||
trace!("read_discriminant_value {:?}", adt_layout);
|
||||
|
||||
let discr_val = match *adt_layout {
|
||||
@ -273,7 +273,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let nonnull = adt_ptr.offset(offset.bytes() as isize);
|
||||
trace!("struct wrapped nullable pointer type: {}", ty);
|
||||
// only the pointer part of a fat pointer is used for this space optimization
|
||||
let discr_size = self.type_size(ty).expect("bad StructWrappedNullablePointer discrfield");
|
||||
let discr_size = self.type_size(ty)?.expect("bad StructWrappedNullablePointer discrfield");
|
||||
self.read_nonnull_discriminant_value(nonnull, nndiscr, discr_size)?
|
||||
}
|
||||
|
||||
@ -402,9 +402,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
fn unpack_fn_args(&self, args: &mut Vec<(Value, Ty<'tcx>)>) {
|
||||
fn unpack_fn_args(&self, args: &mut Vec<(Value, Ty<'tcx>)>) -> EvalResult<'tcx, ()> {
|
||||
if let Some((last, last_ty)) = args.pop() {
|
||||
let last_layout = self.type_layout(last_ty);
|
||||
let last_layout = self.type_layout(last_ty)?;
|
||||
match (&last_ty.sty, last_layout) {
|
||||
(&ty::TyTuple(fields),
|
||||
&Layout::Univariant { ref variant, .. }) => {
|
||||
@ -421,6 +421,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
ty => bug!("expected tuple as last argument in function with 'rust-call' ABI, got {:?}", ty),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Trait method, which has to be resolved to an impl method.
|
||||
@ -452,7 +453,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
.expect("The substitutions should have no type parameters remaining after passing through fulfill_obligation");
|
||||
let closure_kind = self.tcx.closure_kind(vtable_closure.closure_def_id);
|
||||
trace!("closures {:?}, {:?}", closure_kind, trait_closure_kind);
|
||||
self.unpack_fn_args(args);
|
||||
self.unpack_fn_args(args)?;
|
||||
match (closure_kind, trait_closure_kind) {
|
||||
(ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
|
||||
(ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
|
||||
@ -487,7 +488,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
traits::VtableFnPointer(vtable_fn_ptr) => {
|
||||
if let ty::TyFnDef(did, ref substs, _) = vtable_fn_ptr.fn_ty.sty {
|
||||
args.remove(0);
|
||||
self.unpack_fn_args(args);
|
||||
self.unpack_fn_args(args)?;
|
||||
Ok((did, substs))
|
||||
} else {
|
||||
bug!("VtableFnPointer did not contain a concrete function: {:?}", vtable_fn_ptr)
|
||||
@ -583,7 +584,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
if let Some(drop_def_id) = adt_def.destructor() {
|
||||
drop.push((drop_def_id, Value::ByVal(PrimVal::from_ptr(adt_ptr)), substs));
|
||||
}
|
||||
let layout = self.type_layout(ty);
|
||||
let layout = self.type_layout(ty)?;
|
||||
let fields = match *layout {
|
||||
Layout::Univariant { ref variant, .. } => {
|
||||
adt_def.struct_variant().fields.iter().zip(&variant.offsets)
|
||||
@ -630,7 +631,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
)?;
|
||||
},
|
||||
ty::TyTuple(fields) => {
|
||||
let offsets = match *self.type_layout(ty) {
|
||||
let offsets = match *self.type_layout(ty)? {
|
||||
Layout::Univariant { ref variant, .. } => &variant.offsets,
|
||||
_ => bug!("tuples must be univariant"),
|
||||
};
|
||||
@ -658,7 +659,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).expect("slice element must be sized") 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 {
|
||||
@ -671,7 +672,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).expect("array element cannot be unsized") 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 {
|
||||
|
@ -80,8 +80,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
}
|
||||
}).collect();
|
||||
|
||||
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 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();
|
||||
let vtable = self.memory.allocate(ptr_size * (3 + methods.len()), ptr_size)?;
|
||||
|
@ -212,7 +212,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
if ptr.points_to_zst() {
|
||||
return self.allocate(new_size, align);
|
||||
}
|
||||
if self.get(ptr.alloc_id).map(|alloc| alloc.immutable) == Ok(true) {
|
||||
if self.get(ptr.alloc_id).map(|alloc| alloc.immutable).ok() == Some(true) {
|
||||
return Err(EvalError::ReallocatedFrozenMemory);
|
||||
}
|
||||
|
||||
@ -245,7 +245,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
// TODO(solson): Report error about non-__rust_allocate'd pointer.
|
||||
return Err(EvalError::Unimplemented(format!("bad pointer offset: {}", ptr.offset)));
|
||||
}
|
||||
if self.get(ptr.alloc_id).map(|alloc| alloc.immutable) == Ok(true) {
|
||||
if self.get(ptr.alloc_id).map(|alloc| alloc.immutable).ok() == Some(true) {
|
||||
return Err(EvalError::DeallocatedFrozenMemory);
|
||||
}
|
||||
|
||||
|
5
tests/compile-fail/repeat.rs
Normal file
5
tests/compile-fail/repeat.rs
Normal file
@ -0,0 +1,5 @@
|
||||
fn main() {
|
||||
let data: [u8; std::isize::MAX as usize] = [42; std::isize::MAX as usize];
|
||||
//~^ ERROR: rustc layout computation failed: SizeOverflow([u8;
|
||||
assert_eq!(data.len(), 1024);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user