about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2014-09-20 09:19:45 -0400
committerNiko Matsakis <niko@alum.mit.edu>2014-09-25 07:06:28 -0400
commit7119974f82cb239307ed9ea2e885eb66c0edba95 (patch)
tree99e64cda462319d774008198af11bd34e4fde020
parentc31623b0e42e73ef2c9411445d3172e2e9c9e467 (diff)
downloadrust-7119974f82cb239307ed9ea2e885eb66c0edba95.tar.gz
rust-7119974f82cb239307ed9ea2e885eb66c0edba95.zip
Move unsafe destructor check from kind.rs into wf.rs
-rw-r--r--src/librustc/diagnostics.rs1
-rw-r--r--src/librustc/middle/kind.rs81
-rw-r--r--src/librustc/middle/traits/mod.rs3
-rw-r--r--src/librustc/middle/typeck/check/vtable2.rs8
-rw-r--r--src/librustc/middle/typeck/check/wf.rs46
-rw-r--r--src/test/compile-fail/kindck-destructor-owned.rs22
6 files changed, 78 insertions, 83 deletions
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 20842beae16..a3ca3802e47 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -130,7 +130,6 @@ register_diagnostics!(
     E0121,
     E0122,
     E0124,
-    E0125,
     E0126,
     E0127,
     E0128,
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index f5d4ece3bcc..b065e09692c 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -9,15 +9,11 @@
 // except according to those terms.
 
 use middle::mem_categorization::Typer;
-use middle::subst;
 use middle::ty;
-use middle::ty_fold::TypeFoldable;
-use middle::ty_fold;
 use util::ppaux::{ty_to_string};
 use util::ppaux::UserString;
 
 use syntax::ast::*;
-use syntax::attr;
 use syntax::codemap::Span;
 use syntax::print::pprust::{expr_to_string, ident_to_string};
 use syntax::visit::Visitor;
@@ -48,10 +44,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
         check_ty(self, t);
     }
 
-    fn visit_item(&mut self, i: &Item) {
-        check_item(self, i);
-    }
-
     fn visit_pat(&mut self, p: &Pat) {
         check_pat(self, p);
     }
@@ -65,79 +57,6 @@ pub fn check_crate(tcx: &ty::ctxt) {
     tcx.sess.abort_if_errors();
 }
 
-struct EmptySubstsFolder<'a, 'tcx: 'a> {
-    tcx: &'a ty::ctxt<'tcx>
-}
-impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for EmptySubstsFolder<'a, 'tcx> {
-    fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
-        self.tcx
-    }
-    fn fold_substs(&mut self, _: &subst::Substs) -> subst::Substs {
-        subst::Substs::empty()
-    }
-}
-
-fn check_struct_safe_for_destructor(cx: &mut Context,
-                                    span: Span,
-                                    struct_did: DefId) {
-    let struct_tpt = ty::lookup_item_type(cx.tcx, struct_did);
-    if !struct_tpt.generics.has_type_params(subst::TypeSpace)
-      && !struct_tpt.generics.has_region_params(subst::TypeSpace) {
-        let mut folder = EmptySubstsFolder { tcx: cx.tcx };
-        if !ty::type_is_sendable(cx.tcx, struct_tpt.ty.fold_with(&mut folder)) {
-            span_err!(cx.tcx.sess, span, E0125,
-                      "cannot implement a destructor on a \
-                       structure or enumeration that does not satisfy Send");
-            span_note!(cx.tcx.sess, span,
-                       "use \"#[unsafe_destructor]\" on the implementation \
-                        to force the compiler to allow this");
-        }
-    } else {
-        span_err!(cx.tcx.sess, span, E0141,
-                  "cannot implement a destructor on a structure \
-                   with type parameters");
-        span_note!(cx.tcx.sess, span,
-                   "use \"#[unsafe_destructor]\" on the implementation \
-                    to force the compiler to allow this");
-    }
-}
-
-fn check_impl_of_trait(cx: &mut Context, it: &Item, trait_ref: &TraitRef, self_type: &Ty) {
-    let ast_trait_def = *cx.tcx.def_map.borrow()
-                              .find(&trait_ref.ref_id)
-                              .expect("trait ref not in def map!");
-    let trait_def_id = ast_trait_def.def_id();
-
-    // If this is a destructor, check kinds.
-    if cx.tcx.lang_items.drop_trait() == Some(trait_def_id) &&
-        !attr::contains_name(it.attrs.as_slice(), "unsafe_destructor")
-    {
-        match self_type.node {
-            TyPath(_, ref bounds, path_node_id) => {
-                assert!(bounds.is_none());
-                let struct_def = cx.tcx.def_map.borrow().get_copy(&path_node_id);
-                let struct_did = struct_def.def_id();
-                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");
-            }
-        }
-    }
-}
-
-fn check_item(cx: &mut Context, item: &Item) {
-    match item.node {
-        ItemImpl(_, Some(ref trait_ref), ref self_type, _) => {
-            check_impl_of_trait(cx, item, trait_ref, &**self_type);
-        }
-        _ => {}
-    }
-
-    visit::walk_item(cx, item)
-}
-
 // Yields the appropriate function to check the kind of closed over
 // variables. `id` is the NodeId for some expression that creates the
 // closure.
diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs
index ad3e1ae0242..4ce32383525 100644
--- a/src/librustc/middle/traits/mod.rs
+++ b/src/librustc/middle/traits/mod.rs
@@ -69,6 +69,9 @@ pub enum ObligationCauseCode {
     /// Obligation incurred due to an object cast.
     ObjectCastObligation(/* Object type */ ty::t),
 
+    /// To implement drop, type must be sendable.
+    DropTrait,
+
     /// Various cases where expressions must be sized/copy/etc:
     AssignmentLhsSized,        // L = X implies that L is Sized
     StructInitializerSized,    // S { ... } must be Sized
diff --git a/src/librustc/middle/typeck/check/vtable2.rs b/src/librustc/middle/typeck/check/vtable2.rs
index 63a17cec575..e0bf04a1cc3 100644
--- a/src/librustc/middle/typeck/check/vtable2.rs
+++ b/src/librustc/middle/typeck/check/vtable2.rs
@@ -390,5 +390,13 @@ fn note_obligation_cause(fcx: &FnCtxt,
                 obligation.cause.span,
                 "structs must have a statically known size to be initialized");
         }
+        traits::DropTrait => {
+            span_note!(tcx.sess, obligation.cause.span,
+                      "cannot implement a destructor on a \
+                      structure or enumeration that does not satisfy Send");
+            span_note!(tcx.sess, obligation.cause.span,
+                       "use \"#[unsafe_destructor]\" on the implementation \
+                       to force the compiler to allow this");
+        }
     }
 }
diff --git a/src/librustc/middle/typeck/check/wf.rs b/src/librustc/middle/typeck/check/wf.rs
index 6a63464c4b6..8a7de70ea2b 100644
--- a/src/librustc/middle/typeck/check/wf.rs
+++ b/src/librustc/middle/typeck/check/wf.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use middle::subst;
 use middle::subst::{Subst};
 use middle::traits;
 use middle::ty;
@@ -21,6 +22,7 @@ use util::ppaux::Repr;
 use std::collections::HashSet;
 use syntax::ast;
 use syntax::ast_util::{local_def};
+use syntax::attr;
 use syntax::codemap::Span;
 use syntax::visit;
 use syntax::visit::Visitor;
@@ -165,6 +167,22 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             };
             let trait_ref = (*trait_ref).subst(fcx.tcx(), &fcx.inh.param_env.free_substs);
 
+            // There are special rules that apply to drop.
+            if
+                fcx.tcx().lang_items.drop_trait() == Some(trait_ref.def_id) &&
+                !attr::contains_name(item.attrs.as_slice(), "unsafe_destructor")
+            {
+                match ty::get(self_ty).sty {
+                    ty::ty_struct(def_id, _) |
+                    ty::ty_enum(def_id, _) => {
+                        check_struct_safe_for_destructor(fcx, item.span, self_ty, def_id);
+                    }
+                    _ => {
+                        // Coherence already reports an error in this case.
+                    }
+                }
+            }
+
             // We are stricter on the trait-ref in an impl than the
             // self-type.  In particular, we enforce region
             // relationships. The reason for this is that (at least
@@ -362,3 +380,31 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
         t // we're not folding to produce a new type, so just return `t` here
     }
 }
+
+///////////////////////////////////////////////////////////////////////////
+// Special drop trait checking
+
+fn check_struct_safe_for_destructor(fcx: &FnCtxt,
+                                    span: Span,
+                                    self_ty: ty::t,
+                                    struct_did: ast::DefId) {
+    let struct_tpt = ty::lookup_item_type(fcx.tcx(), struct_did);
+    if !struct_tpt.generics.has_type_params(subst::TypeSpace)
+        && !struct_tpt.generics.has_region_params(subst::TypeSpace)
+    {
+        let cause = traits::ObligationCause::new(span, traits::DropTrait);
+        fcx.register_obligation(
+            traits::obligation_for_builtin_bound(
+                fcx.tcx(),
+                cause,
+                self_ty,
+                ty::BoundSend));
+    } else {
+        span_err!(fcx.tcx().sess, span, E0141,
+                  "cannot implement a destructor on a structure \
+                       with type parameters");
+            span_note!(fcx.tcx().sess, span,
+                       "use \"#[unsafe_destructor]\" on the implementation \
+                        to force the compiler to allow this");
+    }
+}
diff --git a/src/test/compile-fail/kindck-destructor-owned.rs b/src/test/compile-fail/kindck-destructor-owned.rs
index 4197464c600..e50bb8fbede 100644
--- a/src/test/compile-fail/kindck-destructor-owned.rs
+++ b/src/test/compile-fail/kindck-destructor-owned.rs
@@ -16,7 +16,27 @@ struct Foo {
 }
 
 impl Drop for Foo {
-//~^ ERROR cannot implement a destructor on a structure or enumeration that does not satisfy Send
+//~^ ERROR the trait `core::kinds::Send` is not implemented for the type `Foo`
+//~^^ NOTE cannot implement a destructor on a structure or enumeration that does not satisfy Send
+    fn drop(&mut self) {
+    }
+}
+
+struct Bar<'a> {
+    f: &'a int,
+}
+
+impl<'a> Drop for Bar<'a> {
+//~^ ERROR E0141
+    fn drop(&mut self) {
+    }
+}
+
+struct Baz {
+    f: &'static int,
+}
+
+impl Drop for Baz {
     fn drop(&mut self) {
     }
 }