]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_typeck/coherence/orphan.rs
rollup merge of #20594: nikomatsakis/orphan-ordered
[rust.git] / src / librustc_typeck / coherence / orphan.rs
index bb8efd29910702a2f4b0b3f23246b10b8670bf8e..77d71e740d681f8c626bc173e1139b8e87cca468 100644 (file)
@@ -18,7 +18,7 @@
 use syntax::ast_util;
 use syntax::codemap::Span;
 use syntax::visit;
-use util::ppaux::Repr;
+use util::ppaux::{Repr, UserString};
 
 pub fn check(tcx: &ty::ctxt) {
     let mut orphan = OrphanChecker { tcx: tcx };
@@ -44,7 +44,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
     fn visit_item(&mut self, item: &'v ast::Item) {
         let def_id = ast_util::local_def(item.id);
         match item.node {
-            ast::ItemImpl(_, _, None, _, _) => {
+            ast::ItemImpl(_, _, _, None, _, _) => {
                 // For inherent impls, self type must be a nominal type
                 // defined in this crate.
                 debug!("coherence2::orphan check: inherent impl {}", item.repr(self.tcx));
@@ -54,8 +54,13 @@ fn visit_item(&mut self, item: &'v ast::Item) {
                     ty::ty_struct(def_id, _) => {
                         self.check_def_id(item.span, def_id);
                     }
-                    ty::ty_trait(box ty::TyTrait{ ref principal, ..}) => {
-                        self.check_def_id(item.span, principal.def_id());
+                    ty::ty_trait(ref data) => {
+                        self.check_def_id(item.span, data.principal_def_id());
+                    }
+                    ty::ty_uniq(..) => {
+                        self.check_def_id(item.span,
+                                          self.tcx.lang_items.owned_box()
+                                              .unwrap());
                     }
                     _ => {
                         span_err!(self.tcx.sess, item.span, E0118,
@@ -64,13 +69,40 @@ fn visit_item(&mut self, item: &'v ast::Item) {
                     }
                 }
             }
-            ast::ItemImpl(_, _, Some(_), _, _) => {
+            ast::ItemImpl(_, _, _, Some(_), _, _) => {
                 // "Trait" impl
                 debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx));
-                if traits::is_orphan_impl(self.tcx, def_id) {
-                    span_err!(self.tcx.sess, item.span, E0117,
-                              "cannot provide an extension implementation \
-                               where both trait and type are not defined in this crate");
+                let trait_def_id = ty::impl_trait_ref(self.tcx, def_id).unwrap().def_id;
+                match traits::orphan_check(self.tcx, def_id) {
+                    Ok(()) => { }
+                    Err(traits::OrphanCheckErr::NoLocalInputType) => {
+                        if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") {
+                            let self_ty = ty::lookup_item_type(self.tcx, def_id).ty;
+                            span_err!(
+                                self.tcx.sess, item.span, E0117,
+                                "the type `{}` does not reference any \
+                                 types defined in this crate; \
+                                 only traits defined in the current crate can be \
+                                 implemented for arbitrary types",
+                                self_ty.user_string(self.tcx));
+                        }
+                    }
+                    Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
+                        if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") {
+                            self.tcx.sess.span_err(
+                                item.span,
+                                format!(
+                                    "type parameter `{}` is not constrained by any local type; \
+                                     only traits defined in the current crate can be implemented \
+                                     for a type parameter",
+                                    param_ty.user_string(self.tcx)).as_slice());
+                            self.tcx.sess.span_note(
+                                item.span,
+                                format!("for a limited time, you can add \
+                                         `#![feature(old_orphan_check)]` to your crate \
+                                         to disable this rule").as_slice());
+                        }
+                    }
                 }
             }
             _ => {