}
}
- Drop { target, .. } => {
- // TODO: Handle destructors and dynamic drop.
+ Drop { ref value, target, .. } => {
+ let ptr = try!(self.eval_lvalue(value)).to_ptr();
+ let ty = self.lvalue_ty(value);
+ try!(self.drop(ptr, ty));
TerminatorTarget::Block(target)
}
Ok(target)
}
+ fn drop(&mut self, ptr: Pointer, ty: ty::Ty<'tcx>) -> EvalResult<()> {
+ if !self.type_needs_drop(ty) {
+ self.log(1, || print!("no need to drop {:?}", ty));
+ return Ok(());
+ }
+ self.log(1, || print!("need to drop {:?}", ty));
+
+ match ty.sty {
+ ty::TyBox(contents_ty) => {
+ let contents_ptr = try!(self.memory.read_ptr(ptr));
+ try!(self.drop(contents_ptr, contents_ty));
+ self.log(1, || print!("deallocating box"));
+ try!(self.memory.deallocate(contents_ptr));
+ }
+
+ // TODO(tsion): Implement drop for other relevant types (e.g. aggregates).
+ _ => {}
+ }
+
+ Ok(())
+ }
+
fn call_intrinsic(
&mut self,
name: &str,
infer::normalize_associated_type(self.tcx, &substituted)
}
+ fn type_needs_drop(&self, ty: ty::Ty<'tcx>) -> bool {
+ self.tcx.type_needs_drop_given_env(ty, &self.tcx.empty_parameter_environment())
+ }
+
fn type_is_sized(&self, ty: ty::Ty<'tcx>) -> bool {
ty.is_sized(&self.tcx.empty_parameter_environment(), DUMMY_SP)
}
Ok(())
}
+ // TODO(tsion): See comment on `reallocate`.
+ pub fn deallocate(&mut self, ptr: Pointer) -> EvalResult<()> {
+ if ptr.offset != 0 {
+ // TODO(tsion): Report error about non-__rust_allocate'd pointer.
+ panic!()
+ }
+
+ if self.alloc_map.remove(&ptr.alloc_id.0).is_none() {
+ // TODO(tsion): Report error about erroneous free. This is blocked on properly tracking
+ // already-dropped state since this if-statement is entered even in safe code without
+ // it.
+ }
+
+ Ok(())
+ }
+
////////////////////////////////////////////////////////////////////////////////
// Allocation accessors
////////////////////////////////////////////////////////////////////////////////
}
#[miri_run]
-fn invalid_bools_are_rejected() -> u8 {
+fn invalid_bool() -> u8 {
let b = unsafe { std::mem::transmute::<u8, bool>(2) };
if b { 1 } else { 2 }
}
#[miri_run]
-fn undefined_byte_reads_are_rejected() -> u8 {
+fn undefined_byte_read() -> u8 {
let v: Vec<u8> = Vec::with_capacity(10);
let undef = unsafe { *v.get_unchecked(5) };
undef + 1
}
#[miri_run]
-fn out_of_bounds_reads_are_rejected() -> u8 {
+fn out_of_bounds_read() -> u8 {
let v: Vec<u8> = vec![1, 2];
unsafe { *v.get_unchecked(5) }
}
+
+#[miri_run]
+fn dangling_pointer_deref() -> i32 {
+ let p = {
+ let b = Box::new(42);
+ &*b as *const i32
+ };
+ unsafe { *p }
+}