about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_typeck/coherence/impls.rs51
-rw-r--r--src/librustc_typeck/coherence/mod.rs2
-rw-r--r--src/test/compile-fail/coherence-impls-builtin.rs37
3 files changed, 90 insertions, 0 deletions
diff --git a/src/librustc_typeck/coherence/impls.rs b/src/librustc_typeck/coherence/impls.rs
new file mode 100644
index 00000000000..9b53cbe84e7
--- /dev/null
+++ b/src/librustc_typeck/coherence/impls.rs
@@ -0,0 +1,51 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Implementations checker: builtin traits and default impls are allowed just
+//! for structs and enums.
+
+use middle::def;
+use middle::ty;
+use syntax::ast::{Item, ItemImpl};
+use syntax::ast;
+use syntax::ast_util;
+use syntax::visit;
+use util::ppaux::UserString;
+
+pub fn check(tcx: &ty::ctxt) {
+    let mut impls = ImplsChecker { tcx: tcx };
+    visit::walk_crate(&mut impls, tcx.map.krate());
+}
+
+struct ImplsChecker<'cx, 'tcx:'cx> {
+    tcx: &'cx ty::ctxt<'tcx>
+}
+
+impl<'cx, 'tcx,'v> visit::Visitor<'v> for ImplsChecker<'cx, 'tcx> {
+    fn visit_item(&mut self, item: &'v ast::Item) {
+        match item.node {
+            ast::ItemImpl(_, _, _, Some(ref opt_trait), _, _) => {
+                let trait_ref = ty::node_id_to_trait_ref(self.tcx, opt_trait.ref_id);
+                if let Some(_) = self.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
+                    match trait_ref.self_ty().sty {
+                        ty::ty_struct(..) | ty::ty_enum(..) => {}
+                        _ => {
+                            self.tcx.sess.span_err(
+                                item.span,
+                                &format!("builtin traits can only be \
+                                          implemented on structs or enums")[]);
+                        }
+                    }
+                }
+            }
+            _ => {}
+        }
+    }
+}
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 9d4aa23960d..a7ef4c1e9f2 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -49,6 +49,7 @@ use syntax::visit;
 use util::nodemap::{DefIdMap, FnvHashMap};
 use util::ppaux::Repr;
 
+mod impls;
 mod orphan;
 mod overlap;
 mod unsafety;
@@ -596,6 +597,7 @@ pub fn check_coherence(crate_context: &CrateCtxt) {
         inference_context: new_infer_ctxt(crate_context.tcx),
         inherent_impls: RefCell::new(FnvHashMap::new()),
     }.check(crate_context.tcx.map.krate());
+    impls::check(crate_context.tcx);
     unsafety::check(crate_context.tcx);
     orphan::check(crate_context.tcx);
     overlap::check(crate_context.tcx);
diff --git a/src/test/compile-fail/coherence-impls-builtin.rs b/src/test/compile-fail/coherence-impls-builtin.rs
new file mode 100644
index 00000000000..2ca288b60a3
--- /dev/null
+++ b/src/test/compile-fail/coherence-impls-builtin.rs
@@ -0,0 +1,37 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::marker::Send;
+
+enum TestE {
+  A
+}
+
+struct MyType;
+
+unsafe impl Send for TestE {}
+unsafe impl Send for MyType {}
+unsafe impl Send for (MyType, MyType) {}
+//~^ ERROR builtin traits can only be implemented on structs or enums
+
+unsafe impl Send for &'static MyType {}
+//~^ ERROR builtin traits can only be implemented on structs or enums
+
+unsafe impl Send for [MyType] {}
+//~^ ERROR builtin traits can only be implemented on structs or enums
+
+unsafe impl Send for &'static [MyType] {}
+//~^ ERROR builtin traits can only be implemented on structs or enums
+
+fn is_send<T: Send>() {}
+
+fn main() {
+    is_send::<(MyType, TestE)>();
+}