about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2013-03-20 18:18:57 -0700
committerPatrick Walton <pcwalton@mimiga.net>2013-03-21 17:31:34 -0700
commitd4fee24c7c4c8ddb1c2c681a01f666a59881acbb (patch)
tree8e708c38984e6d54dfe823377113d6047d9f3551
parent5726fd45268d1ef3574c9321c7ce6efb7e676eac (diff)
downloadrust-d4fee24c7c4c8ddb1c2c681a01f666a59881acbb.tar.gz
rust-d4fee24c7c4c8ddb1c2c681a01f666a59881acbb.zip
librustc: Forbid destructors from being attached to any structs that might contain non-Owned fields. r=nmatsakis
-rw-r--r--src/libcore/condition.rs1
-rw-r--r--src/libcore/io.rs14
-rw-r--r--src/libcore/option.rs1
-rw-r--r--src/libcore/pipes.rs16
-rw-r--r--src/libcore/unstable.rs1
-rw-r--r--src/libcore/unstable/finally.rs1
-rw-r--r--src/librustc/middle/kind.rs99
-rw-r--r--src/librustc/middle/trans/base.rs9
-rw-r--r--src/libstd/arena.rs1
-rw-r--r--src/libstd/c_vec.rs9
-rw-r--r--src/libstd/future.rs1
-rw-r--r--src/libstd/net_tcp.rs1
-rw-r--r--src/libstd/sort.rs1
-rw-r--r--src/libstd/sync.rs12
-rw-r--r--src/libstd/task_pool.rs1
-rw-r--r--src/libsyntax/parse/parser.rs1
-rw-r--r--src/test/auxiliary/issue-2526.rs1
-rw-r--r--src/test/bench/task-perf-alloc-unwind.rs1
-rw-r--r--src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs5
-rw-r--r--src/test/compile-fail/issue-2548.rs7
-rw-r--r--src/test/compile-fail/kindck-destructor-owned.rs12
-rw-r--r--src/test/compile-fail/no-send-res-ports.rs1
-rw-r--r--src/test/compile-fail/pinned-deep-copy.rs5
-rw-r--r--src/test/compile-fail/unique-vec-res.rs5
-rw-r--r--src/test/run-fail/unwind-resource-fail3.rs1
-rw-r--r--src/test/run-pass/drop-trait-generic.rs1
-rw-r--r--src/test/run-pass/init-res-into-things.rs5
-rw-r--r--src/test/run-pass/issue-2718.rs2
-rw-r--r--src/test/run-pass/issue-2735-2.rs5
-rw-r--r--src/test/run-pass/issue-2735-3.rs5
-rw-r--r--src/test/run-pass/issue-979.rs5
-rw-r--r--src/test/run-pass/option-unwrap.rs5
-rw-r--r--src/test/run-pass/resource-assign-is-not-copy.rs5
-rw-r--r--src/test/run-pass/resource-destruct.rs5
-rw-r--r--src/test/run-pass/resource-generic.rs5
-rw-r--r--src/test/run-pass/resource-in-struct.rs5
-rw-r--r--src/test/run-pass/task-killjoin-rsrc.rs17
-rw-r--r--src/test/run-pass/unique-pinned-nocopy-2.rs5
-rw-r--r--src/test/run-pass/unwind-resource2.rs1
-rw-r--r--src/test/run-pass/vec-slice-drop.rs5
40 files changed, 236 insertions, 47 deletions
diff --git a/src/libcore/condition.rs b/src/libcore/condition.rs
index 56b690ca8af..66e9b970fa7 100644
--- a/src/libcore/condition.rs
+++ b/src/libcore/condition.rs
@@ -84,6 +84,7 @@ struct Guard<T, U> {
     cond: &'self Condition/&self<T, U>
 }
 
+#[unsafe_destructor]
 impl<T, U> Drop for Guard/&self<T, U> {
     fn finalize(&self) {
         unsafe {
diff --git a/src/libcore/io.rs b/src/libcore/io.rs
index 7fd61c48207..e77dc0bbc78 100644
--- a/src/libcore/io.rs
+++ b/src/libcore/io.rs
@@ -1230,15 +1230,17 @@ pub mod fsync {
         arg: Arg<t>,
     }
 
+    #[unsafe_destructor]
     impl<T:Copy> Drop for Res<T> {
         fn finalize(&self) {
-          match self.arg.opt_level {
-            None => (),
-            Some(level) => {
-              // fail hard if not succesful
-              fail_unless!(((self.arg.fsync_fn)(self.arg.val, level) != -1));
+            match self.arg.opt_level {
+                None => (),
+                Some(level) => {
+                  // fail hard if not succesful
+                  fail_unless!(((self.arg.fsync_fn)(self.arg.val, level)
+                    != -1));
+                }
             }
-          }
         }
     }
 
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 5e5396ea121..8103166909c 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -514,6 +514,7 @@ fn test_unwrap_resource() {
        i: @mut int,
     }
 
+    #[unsafe_destructor]
     impl ::ops::Drop for R {
        fn finalize(&self) { *(self.i) += 1; }
     }
diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs
index eb385d90354..a5d1cfa2793 100644
--- a/src/libcore/pipes.rs
+++ b/src/libcore/pipes.rs
@@ -350,6 +350,7 @@ struct BufferResource<T> {
 
 }
 
+#[unsafe_destructor]
 impl<T> ::ops::Drop for BufferResource<T> {
     fn finalize(&self) {
         unsafe {
@@ -445,16 +446,17 @@ pub fn try_recv<T:Owned,Tbuffer:Owned>(p: RecvPacketBuffered<T, Tbuffer>)
     let p_ = p.unwrap();
     let p = unsafe { &*p_ };
 
+    #[unsafe_destructor]
     struct DropState {
         p: &'self PacketHeader,
 
         drop {
-            if task::failing() {
-                self.p.state = Terminated;
-                let old_task = swap_task(&mut self.p.blocked_task,
-                                         ptr::null());
-                if !old_task.is_null() {
-                    unsafe {
+            unsafe {
+                if task::failing() {
+                    self.p.state = Terminated;
+                    let old_task = swap_task(&mut self.p.blocked_task,
+                                             ptr::null());
+                    if !old_task.is_null() {
                         rustrt::rust_task_deref(old_task);
                     }
                 }
@@ -773,6 +775,7 @@ pub struct SendPacketBuffered<T, Tbuffer> {
     mut buffer: Option<BufferResource<Tbuffer>>,
 }
 
+#[unsafe_destructor]
 impl<T:Owned,Tbuffer:Owned> ::ops::Drop for SendPacketBuffered<T,Tbuffer> {
     fn finalize(&self) {
         //if self.p != none {
@@ -842,6 +845,7 @@ pub struct RecvPacketBuffered<T, Tbuffer> {
     mut buffer: Option<BufferResource<Tbuffer>>,
 }
 
+#[unsafe_destructor]
 impl<T:Owned,Tbuffer:Owned> ::ops::Drop for RecvPacketBuffered<T,Tbuffer> {
     fn finalize(&self) {
         //if self.p != none {
diff --git a/src/libcore/unstable.rs b/src/libcore/unstable.rs
index 899d01cd996..0ef736d5198 100644
--- a/src/libcore/unstable.rs
+++ b/src/libcore/unstable.rs
@@ -118,6 +118,7 @@ struct ArcDestruct<T> {
     mut data: *libc::c_void,
 }
 
+#[unsafe_destructor]
 impl<T> Drop for ArcDestruct<T>{
     fn finalize(&self) {
         unsafe {
diff --git a/src/libcore/unstable/finally.rs b/src/libcore/unstable/finally.rs
index e8c27ff7d92..c96889cebc8 100644
--- a/src/libcore/unstable/finally.rs
+++ b/src/libcore/unstable/finally.rs
@@ -45,6 +45,7 @@ struct Finallyalizer {
     dtor: &'self fn()
 }
 
+#[unsafe_destructor]
 impl Drop for Finallyalizer/&self {
     fn finalize(&self) {
         (self.dtor)();
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index 4b1b0d0200f..0564e244437 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -22,6 +22,7 @@ use core::str;
 use core::vec;
 use std::oldmap::HashMap;
 use syntax::ast::*;
+use syntax::attr::attrs_contains_name;
 use syntax::codemap::{span, spanned};
 use syntax::print::pprust::expr_to_str;
 use syntax::{visit, ast_util};
@@ -55,6 +56,8 @@ use syntax::{visit, ast_util};
 // primitives in the stdlib are explicitly annotated to only take sendable
 // types.
 
+use core::hashmap::linear::LinearSet;
+
 pub const try_adding: &'static str = "Try adding a move";
 
 pub type rval_map = HashMap<node_id, ()>;
@@ -63,7 +66,7 @@ pub struct Context {
     tcx: ty::ctxt,
     method_map: typeck::method_map,
     last_use_map: liveness::last_use_map,
-    current_item: node_id
+    current_item: node_id,
 }
 
 pub fn check_crate(tcx: ty::ctxt,
@@ -74,16 +77,15 @@ pub fn check_crate(tcx: ty::ctxt,
         tcx: tcx,
         method_map: method_map,
         last_use_map: last_use_map,
-        current_item: -1
+        current_item: -1,
     };
     let visit = visit::mk_vt(@visit::Visitor {
         visit_arm: check_arm,
         visit_expr: check_expr,
         visit_fn: check_fn,
         visit_ty: check_ty,
-        visit_item: |i, cx, v| {
-            visit::visit_item(i, Context { current_item: i.id,.. cx }, v);
-        },
+        visit_item: check_item,
+        visit_block: check_block,
         .. *visit::default_visitor()
     });
     visit::visit_crate(*crate, ctx, visit);
@@ -92,6 +94,93 @@ pub fn check_crate(tcx: ty::ctxt,
 
 type check_fn = @fn(Context, @freevar_entry);
 
+fn check_struct_safe_for_destructor(cx: Context,
+                                    span: span,
+                                    struct_did: def_id) {
+    let struct_tpt = ty::lookup_item_type(cx.tcx, struct_did);
+    if struct_tpt.bounds.len() == 0 {
+        let struct_ty = ty::mk_struct(cx.tcx, struct_did, ty::substs {
+            self_r: None,
+            self_ty: None,
+            tps: ~[]
+        });
+        if !ty::type_is_owned(cx.tcx, struct_ty) {
+            cx.tcx.sess.span_err(span,
+                                 ~"cannot implement a destructor on a struct \
+                                   that is not Owned");
+            cx.tcx.sess.span_note(span,
+                                  ~"use \"#[unsafe_destructor]\" on the \
+                                    implementation to force the compiler to \
+                                    allow this");
+        }
+    } else {
+        cx.tcx.sess.span_err(span,
+                             ~"cannot implement a destructor on a struct \
+                               with type parameters");
+        cx.tcx.sess.span_note(span,
+                              ~"use \"#[unsafe_destructor]\" on the \
+                                implementation to force the compiler to \
+                                allow this");
+    }
+}
+
+fn check_block(block: &blk, cx: Context, visitor: visit::vt<Context>) {
+    visit::visit_block(block, cx, visitor);
+}
+
+fn check_item(item: @item, cx: Context, visitor: visit::vt<Context>) {
+    // If this is a destructor, check kinds.
+    if !attrs_contains_name(item.attrs, "unsafe_destructor") {
+        match item.node {
+            item_impl(_, Some(trait_ref), self_type, _) => {
+                match cx.tcx.def_map.find(&trait_ref.ref_id) {
+                    None => cx.tcx.sess.bug(~"trait ref not in def map!"),
+                    Some(trait_def) => {
+                        let trait_def_id = ast_util::def_id_of_def(trait_def);
+                        if cx.tcx.lang_items.drop_trait() == trait_def_id {
+                            // Yes, it's a destructor.
+                            match self_type.node {
+                                ty_path(_, path_node_id) => {
+                                    let struct_def = cx.tcx.def_map.get(
+                                        &path_node_id);
+                                    let struct_did =
+                                        ast_util::def_id_of_def(struct_def);
+                                    check_struct_safe_for_destructor(
+                                        cx,
+                                        self_type.span,
+                                        struct_did);
+                                }
+                                _ => {
+                                    cx.tcx.sess.span_bug(self_type.span,
+                                                         ~"the self type for \
+                                                           the Drop trait \
+                                                           impl is not a \
+                                                           path");
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            item_struct(struct_def, _) => {
+                match struct_def.dtor {
+                    None => {}
+                    Some(ref dtor) => {
+                        let struct_did = def_id { crate: 0, node: item.id };
+                        check_struct_safe_for_destructor(cx,
+                                                         dtor.span,
+                                                         struct_did);
+                    }
+                }
+            }
+            _ => {}
+        }
+    }
+
+    let cx = Context { current_item: item.id, ..cx };
+    visit::visit_item(item, cx, visitor);
+}
+
 // Yields the appropriate function to check the kind of closed over
 // variables. `id` is the node_id for some expression that creates the
 // closure.
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 9346872f949..62fff583766 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -88,11 +88,14 @@ pub struct icx_popper {
     ccx: @CrateContext,
 }
 
+#[unsafe_destructor]
 impl Drop for icx_popper {
     fn finalize(&self) {
-      if self.ccx.sess.count_llvm_insns() {
-          self.ccx.stats.llvm_insn_ctxt.pop();
-      }
+        unsafe {
+            if self.ccx.sess.count_llvm_insns() {
+                self.ccx.stats.llvm_insn_ctxt.pop();
+            }
+        }
     }
 }
 
diff --git a/src/libstd/arena.rs b/src/libstd/arena.rs
index 68132a1c08d..911abf95ff8 100644
--- a/src/libstd/arena.rs
+++ b/src/libstd/arena.rs
@@ -88,6 +88,7 @@ pub struct Arena {
     priv mut chunks: @List<Chunk>,
 }
 
+#[unsafe_destructor]
 impl Drop for Arena {
     fn finalize(&self) {
         unsafe {
diff --git a/src/libstd/c_vec.rs b/src/libstd/c_vec.rs
index 8e75f694fa3..d9595656f05 100644
--- a/src/libstd/c_vec.rs
+++ b/src/libstd/c_vec.rs
@@ -54,11 +54,14 @@ struct DtorRes {
   dtor: Option<@fn()>,
 }
 
+#[unsafe_destructor]
 impl Drop for DtorRes {
     fn finalize(&self) {
-        match self.dtor {
-          option::None => (),
-          option::Some(f) => f()
+        unsafe {
+            match self.dtor {
+                option::None => (),
+                option::Some(f) => f()
+            }
         }
     }
 }
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
index 4867204ea39..fc60932b67a 100644
--- a/src/libstd/future.rs
+++ b/src/libstd/future.rs
@@ -35,6 +35,7 @@ pub struct Future<A> {
 
 // FIXME(#2829) -- futures should not be copyable, because they close
 // over ~fn's that have pipes and so forth within!
+#[unsafe_destructor]
 impl<A> Drop for Future<A> {
     fn finalize(&self) {}
 }
diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs
index a93e94e0d04..c49f65d0f99 100644
--- a/src/libstd/net_tcp.rs
+++ b/src/libstd/net_tcp.rs
@@ -55,6 +55,7 @@ pub struct TcpSocket {
   socket_data: @TcpSocketData,
 }
 
+#[unsafe_destructor]
 impl Drop for TcpSocket {
     fn finalize(&self) {
         unsafe {
diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs
index 40be303a147..db8311ca035 100644
--- a/src/libstd/sort.rs
+++ b/src/libstd/sort.rs
@@ -1190,6 +1190,7 @@ mod big_tests {
         key: &'self fn(@uint),
     }
 
+    #[unsafe_destructor]
     impl Drop for LVal/&self {
         fn finalize(&self) {
             let x = unsafe { task::local_data::local_data_get(self.key) };
diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs
index d47232cc535..00de601da6f 100644
--- a/src/libstd/sync.rs
+++ b/src/libstd/sync.rs
@@ -167,9 +167,12 @@ type SemRelease = SemReleaseGeneric<'self, ()>;
 type SemAndSignalRelease = SemReleaseGeneric<'self, ~[Waitqueue]>;
 struct SemReleaseGeneric<Q> { sem: &'self Sem<Q> }
 
+#[unsafe_destructor]
 impl<Q:Owned> Drop for SemReleaseGeneric/&self<Q> {
     fn finalize(&self) {
-        self.sem.release();
+        unsafe {
+            self.sem.release();
+        }
     }
 }
 
@@ -189,6 +192,7 @@ fn SemAndSignalRelease(sem: &'r Sem<~[Waitqueue]>)
 /// A mechanism for atomic-unlock-and-deschedule blocking and signalling.
 pub struct Condvar { priv sem: &'self Sem<~[Waitqueue]> }
 
+#[unsafe_destructor]
 impl Drop for Condvar/&self { fn finalize(&self) {} }
 
 pub impl Condvar/&self {
@@ -261,6 +265,7 @@ pub impl Condvar/&self {
             sem: &'self Sem<~[Waitqueue]>,
         }
 
+        #[unsafe_destructor]
         impl Drop for SemAndSignalReacquire/&self {
             fn finalize(&self) {
                 unsafe {
@@ -613,6 +618,7 @@ struct RWlockReleaseRead {
     lock: &'self RWlock,
 }
 
+#[unsafe_destructor]
 impl Drop for RWlockReleaseRead/&self {
     fn finalize(&self) {
         unsafe {
@@ -643,10 +649,12 @@ fn RWlockReleaseRead(lock: &'r RWlock) -> RWlockReleaseRead/&r {
 
 // FIXME(#3588) should go inside of downgrade()
 #[doc(hidden)]
+#[unsafe_destructor]
 struct RWlockReleaseDowngrade {
     lock: &'self RWlock,
 }
 
+#[unsafe_destructor]
 impl Drop for RWlockReleaseDowngrade/&self {
     fn finalize(&self) {
         unsafe {
@@ -685,10 +693,12 @@ fn RWlockReleaseDowngrade(lock: &'r RWlock) -> RWlockReleaseDowngrade/&r {
 
 /// The "write permission" token used for rwlock.write_downgrade().
 pub struct RWlockWriteMode { priv lock: &'self RWlock }
+#[unsafe_destructor]
 impl Drop for RWlockWriteMode/&self { fn finalize(&self) {} }
 
 /// The "read permission" token used for rwlock.write_downgrade().
 pub struct RWlockReadMode  { priv lock: &'self RWlock }
+#[unsafe_destructor]
 impl Drop for RWlockReadMode/&self { fn finalize(&self) {} }
 
 pub impl RWlockWriteMode/&self {
diff --git a/src/libstd/task_pool.rs b/src/libstd/task_pool.rs
index 09cab72ab21..d8ca5559f42 100644
--- a/src/libstd/task_pool.rs
+++ b/src/libstd/task_pool.rs
@@ -28,6 +28,7 @@ pub struct TaskPool<T> {
 
 }
 
+#[unsafe_destructor]
 impl<T> Drop for TaskPool<T> {
     fn finalize(&self) {
         for self.channels.each |channel| {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index de861075a5b..421c1805f6a 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -268,6 +268,7 @@ pub struct Parser {
 
 }
 
+#[unsafe_destructor]
 impl Drop for Parser {
     /* do not copy the parser; its state is tied to outside state */
     fn finalize(&self) {}
diff --git a/src/test/auxiliary/issue-2526.rs b/src/test/auxiliary/issue-2526.rs
index c09e64eac8c..775955ff38c 100644
--- a/src/test/auxiliary/issue-2526.rs
+++ b/src/test/auxiliary/issue-2526.rs
@@ -19,6 +19,7 @@ struct arc_destruct<T> {
   _data: int,
 }
 
+#[unsafe_destructor]
 impl<T:Const> Drop for arc_destruct<T> {
     fn finalize(&self) {}
 }
diff --git a/src/test/bench/task-perf-alloc-unwind.rs b/src/test/bench/task-perf-alloc-unwind.rs
index 4a372d016f9..c29ab9a769e 100644
--- a/src/test/bench/task-perf-alloc-unwind.rs
+++ b/src/test/bench/task-perf-alloc-unwind.rs
@@ -56,6 +56,7 @@ struct r {
   _l: @nillist,
 }
 
+#[unsafe_destructor]
 impl Drop for r {
     fn finalize(&self) {}
 }
diff --git a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs
index fd8190358c9..fe7b29cf9a8 100644
--- a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs
+++ b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs
@@ -12,9 +12,12 @@ struct defer {
     x: &'self [&'self str],
 }
 
+#[unsafe_destructor]
 impl Drop for defer<'self> {
     fn finalize(&self) {
-        error!("%?", self.x);
+        unsafe {
+            error!("%?", self.x);
+        }
     }
 }
 
diff --git a/src/test/compile-fail/issue-2548.rs b/src/test/compile-fail/issue-2548.rs
index 83fdb86628b..f8f973dbc6b 100644
--- a/src/test/compile-fail/issue-2548.rs
+++ b/src/test/compile-fail/issue-2548.rs
@@ -16,10 +16,13 @@ struct foo {
 
 }
 
+#[unsafe_destructor]
 impl Drop for foo {
     fn finalize(&self) {
-        io::println("Goodbye, World!");
-        *self.x += 1;
+        unsafe {
+            io::println("Goodbye, World!");
+            *self.x += 1;
+        }
     }
 }
 
diff --git a/src/test/compile-fail/kindck-destructor-owned.rs b/src/test/compile-fail/kindck-destructor-owned.rs
new file mode 100644
index 00000000000..e956f95b422
--- /dev/null
+++ b/src/test/compile-fail/kindck-destructor-owned.rs
@@ -0,0 +1,12 @@
+struct Foo {
+    f: @mut int,
+}
+
+impl Drop for Foo { //~ ERROR cannot implement a destructor on a struct that is not Owned
+    fn finalize(&self) {
+        *self.f = 10;
+    }
+}
+
+fn main() { }
+
diff --git a/src/test/compile-fail/no-send-res-ports.rs b/src/test/compile-fail/no-send-res-ports.rs
index 192cde21bf1..c1071e5a8c4 100644
--- a/src/test/compile-fail/no-send-res-ports.rs
+++ b/src/test/compile-fail/no-send-res-ports.rs
@@ -17,6 +17,7 @@ fn main() {
       _x: Port<()>,
     }
 
+    #[unsafe_destructor]
     impl Drop for foo {
         fn finalize(&self) {}
     }
diff --git a/src/test/compile-fail/pinned-deep-copy.rs b/src/test/compile-fail/pinned-deep-copy.rs
index 5df65832099..17e23360a5b 100644
--- a/src/test/compile-fail/pinned-deep-copy.rs
+++ b/src/test/compile-fail/pinned-deep-copy.rs
@@ -12,9 +12,12 @@ struct r {
   i: @mut int,
 }
 
+#[unsafe_destructor]
 impl Drop for r {
     fn finalize(&self) {
-        *(self.i) = *(self.i) + 1;
+        unsafe {
+            *(self.i) = *(self.i) + 1;
+        }
     }
 }
 
diff --git a/src/test/compile-fail/unique-vec-res.rs b/src/test/compile-fail/unique-vec-res.rs
index 3f4636328b6..a3c51e2b7b1 100644
--- a/src/test/compile-fail/unique-vec-res.rs
+++ b/src/test/compile-fail/unique-vec-res.rs
@@ -12,9 +12,12 @@ struct r {
   i: @mut int,
 }
 
+#[unsafe_destructor]
 impl Drop for r {
     fn finalize(&self) {
-        *(self.i) = *(self.i) + 1;
+        unsafe {
+            *(self.i) = *(self.i) + 1;
+        }
     }
 }
 
diff --git a/src/test/run-fail/unwind-resource-fail3.rs b/src/test/run-fail/unwind-resource-fail3.rs
index 27e0ebe7761..d3ba5737b71 100644
--- a/src/test/run-fail/unwind-resource-fail3.rs
+++ b/src/test/run-fail/unwind-resource-fail3.rs
@@ -17,6 +17,7 @@ struct faily_box {
  
 fn faily_box(i: @int) -> faily_box { faily_box { i: i } }
 
+#[unsafe_destructor]
 impl Drop for faily_box {
     fn finalize(&self) {
         fail!(~"quux");
diff --git a/src/test/run-pass/drop-trait-generic.rs b/src/test/run-pass/drop-trait-generic.rs
index 270137c2fd2..21b85084117 100644
--- a/src/test/run-pass/drop-trait-generic.rs
+++ b/src/test/run-pass/drop-trait-generic.rs
@@ -12,6 +12,7 @@ struct S<T> {
     x: T
 }
 
+#[unsafe_destructor]
 impl<T> ::core::ops::Drop for S<T> {
     fn finalize(&self) {
         io::println("bye");
diff --git a/src/test/run-pass/init-res-into-things.rs b/src/test/run-pass/init-res-into-things.rs
index 50b31361cee..5db8e34c7b5 100644
--- a/src/test/run-pass/init-res-into-things.rs
+++ b/src/test/run-pass/init-res-into-things.rs
@@ -17,9 +17,12 @@ struct r {
 
 struct Box { x: r }
 
+#[unsafe_destructor]
 impl Drop for r {
     fn finalize(&self) {
-        *(self.i) = *(self.i) + 1;
+        unsafe {
+            *(self.i) = *(self.i) + 1;
+        }
     }
 }
 
diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs
index ae927ff7918..c8c2d381a7e 100644
--- a/src/test/run-pass/issue-2718.rs
+++ b/src/test/run-pass/issue-2718.rs
@@ -155,6 +155,7 @@ pub mod pipes {
         p: Option<*packet<T>>,
     }
 
+    #[unsafe_destructor]
     impl<T:Owned> Drop for send_packet<T> {
         fn finalize(&self) {
             unsafe {
@@ -187,6 +188,7 @@ pub mod pipes {
         p: Option<*packet<T>>,
     }
 
+    #[unsafe_destructor]
     impl<T:Owned> Drop for recv_packet<T> {
         fn finalize(&self) {
             unsafe {
diff --git a/src/test/run-pass/issue-2735-2.rs b/src/test/run-pass/issue-2735-2.rs
index 4c8559f0552..52a5f193447 100644
--- a/src/test/run-pass/issue-2735-2.rs
+++ b/src/test/run-pass/issue-2735-2.rs
@@ -13,9 +13,12 @@ struct defer {
     b: &'self mut bool,
 }
 
+#[unsafe_destructor]
 impl Drop for defer/&self {
     fn finalize(&self) {
-        *(self.b) = true;
+        unsafe {
+            *(self.b) = true;
+        }
     }
 }
 
diff --git a/src/test/run-pass/issue-2735-3.rs b/src/test/run-pass/issue-2735-3.rs
index 9fa1d56406a..02e9f6f8b67 100644
--- a/src/test/run-pass/issue-2735-3.rs
+++ b/src/test/run-pass/issue-2735-3.rs
@@ -13,9 +13,12 @@ struct defer {
     b: &'self mut bool,
 }
 
+#[unsafe_destructor]
 impl Drop for defer/&self {
     fn finalize(&self) {
-        *(self.b) = true;
+        unsafe {
+            *(self.b) = true;
+        }
     }
 }
 
diff --git a/src/test/run-pass/issue-979.rs b/src/test/run-pass/issue-979.rs
index d46f62c6ae0..d5184efa4c3 100644
--- a/src/test/run-pass/issue-979.rs
+++ b/src/test/run-pass/issue-979.rs
@@ -12,9 +12,12 @@ struct r {
   b: @mut int,
 }
 
+#[unsafe_destructor]
 impl Drop for r {
     fn finalize(&self) {
-        *(self.b) += 1;
+        unsafe {
+            *(self.b) += 1;
+        }
     }
 }
 
diff --git a/src/test/run-pass/option-unwrap.rs b/src/test/run-pass/option-unwrap.rs
index d2e5911111d..207428c2cec 100644
--- a/src/test/run-pass/option-unwrap.rs
+++ b/src/test/run-pass/option-unwrap.rs
@@ -13,10 +13,13 @@ struct dtor {
 
 }
 
+#[unsafe_destructor]
 impl Drop for dtor {
     fn finalize(&self) {
         // abuse access to shared mutable state to write this code
-        *self.x -= 1;
+        unsafe {
+            *self.x -= 1;
+        }
     }
 }
 
diff --git a/src/test/run-pass/resource-assign-is-not-copy.rs b/src/test/run-pass/resource-assign-is-not-copy.rs
index df084c13427..7d9c01cd2e3 100644
--- a/src/test/run-pass/resource-assign-is-not-copy.rs
+++ b/src/test/run-pass/resource-assign-is-not-copy.rs
@@ -12,9 +12,12 @@ struct r {
   i: @mut int,
 }
 
+#[unsafe_destructor]
 impl Drop for r {
     fn finalize(&self) {
-        *(self.i) += 1;
+        unsafe {
+            *(self.i) += 1;
+        }
     }
 }
 
diff --git a/src/test/run-pass/resource-destruct.rs b/src/test/run-pass/resource-destruct.rs
index db444f08fab..cc9a27fd9e4 100644
--- a/src/test/run-pass/resource-destruct.rs
+++ b/src/test/run-pass/resource-destruct.rs
@@ -12,9 +12,12 @@ struct shrinky_pointer {
   i: @@mut int,
 }
 
+#[unsafe_destructor]
 impl Drop for shrinky_pointer {
     fn finalize(&self) {
-        error!(~"Hello!"); **(self.i) -= 1;
+        unsafe {
+            error!(~"Hello!"); **(self.i) -= 1;
+        }
     }
 }
 
diff --git a/src/test/run-pass/resource-generic.rs b/src/test/run-pass/resource-generic.rs
index e43b90c30b0..4ce6a37956c 100644
--- a/src/test/run-pass/resource-generic.rs
+++ b/src/test/run-pass/resource-generic.rs
@@ -16,9 +16,12 @@ struct finish<T> {
   arg: Arg<T>
 }
 
+#[unsafe_destructor]
 impl<T:Copy> Drop for finish<T> {
     fn finalize(&self) {
-        (self.arg.fin)(self.arg.val);
+        unsafe {
+            (self.arg.fin)(self.arg.val);
+        }
     }
 }
 
diff --git a/src/test/run-pass/resource-in-struct.rs b/src/test/run-pass/resource-in-struct.rs
index 53c76680bde..9eb680ed7cc 100644
--- a/src/test/run-pass/resource-in-struct.rs
+++ b/src/test/run-pass/resource-in-struct.rs
@@ -18,9 +18,12 @@ struct close_res {
 
 }
 
+#[unsafe_destructor]
 impl Drop for close_res {
     fn finalize(&self) {
-        *(self.i) = false;
+        unsafe {
+            *(self.i) = false;
+        }
     }
 }
 
diff --git a/src/test/run-pass/task-killjoin-rsrc.rs b/src/test/run-pass/task-killjoin-rsrc.rs
index 39651f86e22..042ae1785d1 100644
--- a/src/test/run-pass/task-killjoin-rsrc.rs
+++ b/src/test/run-pass/task-killjoin-rsrc.rs
@@ -20,15 +20,18 @@ struct notify {
     ch: Chan<bool>, v: @mut bool,
 }
 
+#[unsafe_destructor]
 impl Drop for notify {
     fn finalize(&self) {
-        error!("notify: task=%? v=%x unwinding=%b b=%b",
-               task::get_task(),
-               ptr::addr_of(&(*(self.v))) as uint,
-               task::failing(),
-               *(self.v));
-        let b = *(self.v);
-        self.ch.send(b);
+        unsafe {
+            error!("notify: task=%? v=%x unwinding=%b b=%b",
+                   task::get_task(),
+                   ptr::addr_of(&(*(self.v))) as uint,
+                   task::failing(),
+                   *(self.v));
+            let b = *(self.v);
+            self.ch.send(b);
+        }
     }
 }
 
diff --git a/src/test/run-pass/unique-pinned-nocopy-2.rs b/src/test/run-pass/unique-pinned-nocopy-2.rs
index 3fc22c9a5a5..ff22c18b02c 100644
--- a/src/test/run-pass/unique-pinned-nocopy-2.rs
+++ b/src/test/run-pass/unique-pinned-nocopy-2.rs
@@ -12,9 +12,12 @@ struct r {
   i: @mut int,
 }
 
+#[unsafe_destructor]
 impl Drop for r {
     fn finalize(&self) {
-        *(self.i) = *(self.i) + 1;
+        unsafe {
+            *(self.i) = *(self.i) + 1;
+        }
     }
 }
 
diff --git a/src/test/run-pass/unwind-resource2.rs b/src/test/run-pass/unwind-resource2.rs
index 75ce797cfc8..993acc2264f 100644
--- a/src/test/run-pass/unwind-resource2.rs
+++ b/src/test/run-pass/unwind-resource2.rs
@@ -15,6 +15,7 @@ struct complainer {
   c: @int,
 }
 
+#[unsafe_destructor]
 impl Drop for complainer {
     fn finalize(&self) {}
 }
diff --git a/src/test/run-pass/vec-slice-drop.rs b/src/test/run-pass/vec-slice-drop.rs
index 71963e073db..2a7c9610ad4 100644
--- a/src/test/run-pass/vec-slice-drop.rs
+++ b/src/test/run-pass/vec-slice-drop.rs
@@ -13,9 +13,12 @@ struct foo {
     x: @mut int,
 }
 
+#[unsafe_destructor]
 impl Drop for foo {
     fn finalize(&self) {
-        *self.x += 1;
+        unsafe {
+            *self.x += 1;
+        }
     }
 }