]> git.lizzy.rs Git - rust.git/commitdiff
Implement drop/deallocation for Box.
authorScott Olson <scott@solson.me>
Thu, 7 Apr 2016 09:02:02 +0000 (03:02 -0600)
committerScott Olson <scott@solson.me>
Thu, 7 Apr 2016 09:02:02 +0000 (03:02 -0600)
src/interpreter.rs
src/memory.rs
test/errors.rs

index 5ea2a117b8c58374a8debc36fa2d7b4975c4a4ba..324a2008e38108049c271e4b1691185e258fdb69 100644 (file)
@@ -360,8 +360,10 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>)
                 }
             }
 
-            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)
             }
 
@@ -371,6 +373,28 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>)
         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,
@@ -847,6 +871,10 @@ fn monomorphize(&self, ty: ty::Ty<'tcx>) -> ty::Ty<'tcx> {
         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)
     }
index b41cd7760b0c133dbc7cff73036bcb719ff3e61b..661f45672648b5554aa01736af72fe0f23b08377 100644 (file)
@@ -140,6 +140,22 @@ pub fn reallocate(&mut self, ptr: Pointer, new_size: usize) -> EvalResult<()> {
         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
     ////////////////////////////////////////////////////////////////////////////////
index f6f5eae9d0fe6d0a328d07a27bf33df18b9a1960..a488d7acb433fe2efc5b57dbe73eaa3bb40ef3b8 100644 (file)
@@ -19,20 +19,29 @@ fn pointers_to_different_allocations_are_unorderable() -> bool {
 }
 
 #[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 }
+}