about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-02-05 14:49:27 -0500
committerDavid Wood <david@davidtw.co>2018-02-14 18:17:54 +0000
commit552024a52eb17b2542e87f9fc97b7b643707d759 (patch)
tree4b5932b3eb0947c61bad5e9958640d49c2f1f165
parent5fd64dde2198971df0869cbf4944d3996395b826 (diff)
downloadrust-552024a52eb17b2542e87f9fc97b7b643707d759.tar.gz
rust-552024a52eb17b2542e87f9fc97b7b643707d759.zip
check that types "need drop" before we access them
Also, add some comments and remove extra deref.
-rw-r--r--src/librustc_mir/borrow_check/mod.rs40
1 files changed, 28 insertions, 12 deletions
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 46f94f2388f..3cdfe640006 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -711,6 +711,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
              self.tcx.sess.opts.debugging_opts.two_phase_beyond_autoref)
     }
 
+    /// Invokes `access_place` as appropriate for dropping the value
+    /// at `drop_place`. Note that the *actual* `Drop` in the MIR is
+    /// always for a variable (e.g., `Drop(x)`) -- but we recursively
+    /// break this variable down into subpaths (e.g., `Drop(x.foo)`)
+    /// to indicate more precisely which fields might actually be
+    /// accessed by a destructor.
     fn visit_terminator_drop(
         &mut self,
         loc: Location,
@@ -721,15 +727,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     ) {
         let ty = drop_place.ty(self.mir, self.tcx).to_ty(self.tcx);
         match ty.sty {
-            // When a struct is being dropped, we need to check whether it has a
-            // destructor, if it does, then we can call it, if it does not then we
-            // need to check the individual fields instead.
-            // See #47703.
+            // When a struct is being dropped, we need to check
+            // whether it has a destructor, if it does, then we can
+            // call it, if it does not then we need to check the
+            // individual fields instead. This way if `foo` has a
+            // destructor but `bar` does not, we will only check for
+            // borrows of `x.foo` and not `x.bar`. See #47703.
             ty::TyAdt(def, substs) if def.is_struct() && !def.has_dtor(self.tcx) => {
                 for (index, field) in def.all_fields().enumerate() {
                     let place = drop_place.clone();
                     let place = place.field(Field::new(index), field.ty(self.tcx, substs));
-                    let place = place.deref();
 
                     self.visit_terminator_drop(
                         loc,
@@ -741,13 +748,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 }
             },
             _ => {
-                self.access_place(
-                    ContextKind::Drop.new(loc),
-                    (drop_place, span),
-                    (Deep, Write(WriteKind::StorageDeadOrDrop)),
-                    LocalMutationIsAllowed::Yes,
-                    flow_state,
-                );
+                // We have now refined the type of the value being
+                // dropped (potentially) to just the type of a
+                // subfield; so check whether that field's type still
+                // "needs drop". If so, we assume that the destructor
+                // may access any data it likes (i.e., a Deep Write).
+                let gcx = self.tcx.global_tcx();
+                let erased_ty = gcx.lift(&self.tcx.erase_regions(&ty)).unwrap();
+                if erased_ty.needs_drop(gcx, self.param_env) {
+                    self.access_place(
+                        ContextKind::Drop.new(loc),
+                        (drop_place, span),
+                        (Deep, Write(WriteKind::StorageDeadOrDrop)),
+                        LocalMutationIsAllowed::Yes,
+                        flow_state,
+                    );
+                }
             },
         }
     }