]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc_typeck/coherence/orphan.rs
New upstream version 1.31.0~beta.4+dfsg1
[rustc.git] / src / librustc_typeck / coherence / orphan.rs
index f9b89488232d26e5b098b7efffa7bdd1a4faa041..b155587dddc419f284fcda6978e89a0201c98f98 100644 (file)
@@ -33,131 +33,126 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
     /// reports.
     fn visit_item(&mut self, item: &hir::Item) {
         let def_id = self.tcx.hir.local_def_id(item.id);
-        match item.node {
-            hir::ItemKind::Impl(.., Some(_), _, _) => {
-                // "Trait" impl
-                debug!("coherence2::orphan check: trait impl {}",
-                       self.tcx.hir.node_to_string(item.id));
-                let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
-                let trait_def_id = trait_ref.def_id;
-                let cm = self.tcx.sess.source_map();
-                let sp = cm.def_span(item.span);
-                match traits::orphan_check(self.tcx, def_id) {
-                    Ok(()) => {}
-                    Err(traits::OrphanCheckErr::NoLocalInputType) => {
-                        struct_span_err!(self.tcx.sess,
-                                         sp,
-                                         E0117,
-                                         "only traits defined in the current crate can be \
-                                          implemented for arbitrary types")
-                            .span_label(sp, "impl doesn't use types inside crate")
-                            .note("the impl does not reference any types defined in this crate")
-                            .note("define and implement a trait or new type instead")
-                            .emit();
-                        return;
-                    }
-                    Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
-                        struct_span_err!(self.tcx.sess,
-                                         sp,
-                                         E0210,
-                                         "type parameter `{}` must be used as the type parameter \
-                                          for some local type (e.g. `MyStruct<{}>`)",
-                                         param_ty,
-                                         param_ty)
-                            .span_label(sp,
-                                        format!("type parameter `{}` must be used as the type \
-                                                 parameter for some local type", param_ty))
-                            .note("only traits defined in the current crate can be implemented \
-                                   for a type parameter")
-                            .emit();
-                        return;
-                    }
+        // "Trait" impl
+        if let hir::ItemKind::Impl(.., Some(_), _, _) = item.node {
+            debug!("coherence2::orphan check: trait impl {}",
+                   self.tcx.hir.node_to_string(item.id));
+            let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
+            let trait_def_id = trait_ref.def_id;
+            let cm = self.tcx.sess.source_map();
+            let sp = cm.def_span(item.span);
+            match traits::orphan_check(self.tcx, def_id) {
+                Ok(()) => {}
+                Err(traits::OrphanCheckErr::NoLocalInputType) => {
+                    struct_span_err!(self.tcx.sess,
+                                     sp,
+                                     E0117,
+                                     "only traits defined in the current crate can be \
+                                      implemented for arbitrary types")
+                        .span_label(sp, "impl doesn't use types inside crate")
+                        .note("the impl does not reference any types defined in this crate")
+                        .note("define and implement a trait or new type instead")
+                        .emit();
+                    return;
+                }
+                Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
+                    struct_span_err!(self.tcx.sess,
+                                     sp,
+                                     E0210,
+                                     "type parameter `{}` must be used as the type parameter \
+                                      for some local type (e.g. `MyStruct<{}>`)",
+                                     param_ty,
+                                     param_ty)
+                        .span_label(sp,
+                                    format!("type parameter `{}` must be used as the type \
+                                             parameter for some local type", param_ty))
+                        .note("only traits defined in the current crate can be implemented \
+                               for a type parameter")
+                        .emit();
+                    return;
                 }
+            }
 
-                // In addition to the above rules, we restrict impls of auto traits
-                // so that they can only be implemented on nominal types, such as structs,
-                // enums or foreign types. To see why this restriction exists, consider the
-                // following example (#22978). Imagine that crate A defines an auto trait
-                // `Foo` and a fn that operates on pairs of types:
-                //
-                // ```
-                // // Crate A
-                // auto trait Foo { }
-                // fn two_foos<A:Foo,B:Foo>(..) {
-                //     one_foo::<(A,B)>(..)
-                // }
-                // fn one_foo<T:Foo>(..) { .. }
-                // ```
-                //
-                // This type-checks fine; in particular the fn
-                // `two_foos` is able to conclude that `(A,B):Foo`
-                // because `A:Foo` and `B:Foo`.
-                //
-                // Now imagine that crate B comes along and does the following:
-                //
-                // ```
-                // struct A { }
-                // struct B { }
-                // impl Foo for A { }
-                // impl Foo for B { }
-                // impl !Send for (A, B) { }
-                // ```
-                //
-                // This final impl is legal according to the orpan
-                // rules, but it invalidates the reasoning from
-                // `two_foos` above.
-                debug!("trait_ref={:?} trait_def_id={:?} trait_is_auto={}",
-                       trait_ref,
-                       trait_def_id,
-                       self.tcx.trait_is_auto(trait_def_id));
-                if self.tcx.trait_is_auto(trait_def_id) &&
-                   !trait_def_id.is_local() {
-                    let self_ty = trait_ref.self_ty();
-                    let opt_self_def_id = match self_ty.sty {
-                        ty::Adt(self_def, _) => Some(self_def.did),
-                        ty::Foreign(did) => Some(did),
-                        _ => None,
-                    };
+            // In addition to the above rules, we restrict impls of auto traits
+            // so that they can only be implemented on nominal types, such as structs,
+            // enums or foreign types. To see why this restriction exists, consider the
+            // following example (#22978). Imagine that crate A defines an auto trait
+            // `Foo` and a fn that operates on pairs of types:
+            //
+            // ```
+            // // Crate A
+            // auto trait Foo { }
+            // fn two_foos<A:Foo,B:Foo>(..) {
+            //     one_foo::<(A,B)>(..)
+            // }
+            // fn one_foo<T:Foo>(..) { .. }
+            // ```
+            //
+            // This type-checks fine; in particular the fn
+            // `two_foos` is able to conclude that `(A,B):Foo`
+            // because `A:Foo` and `B:Foo`.
+            //
+            // Now imagine that crate B comes along and does the following:
+            //
+            // ```
+            // struct A { }
+            // struct B { }
+            // impl Foo for A { }
+            // impl Foo for B { }
+            // impl !Send for (A, B) { }
+            // ```
+            //
+            // This final impl is legal according to the orpan
+            // rules, but it invalidates the reasoning from
+            // `two_foos` above.
+            debug!("trait_ref={:?} trait_def_id={:?} trait_is_auto={}",
+                   trait_ref,
+                   trait_def_id,
+                   self.tcx.trait_is_auto(trait_def_id));
+            if self.tcx.trait_is_auto(trait_def_id) &&
+               !trait_def_id.is_local() {
+                let self_ty = trait_ref.self_ty();
+                let opt_self_def_id = match self_ty.sty {
+                    ty::Adt(self_def, _) => Some(self_def.did),
+                    ty::Foreign(did) => Some(did),
+                    _ => None,
+                };
 
-                    let msg = match opt_self_def_id {
-                        // We only want to permit nominal types, but not *all* nominal types.
-                        // They must be local to the current crate, so that people
-                        // can't do `unsafe impl Send for Rc<SomethingLocal>` or
-                        // `impl !Send for Box<SomethingLocalAndSend>`.
-                        Some(self_def_id) => {
-                            if self_def_id.is_local() {
-                                None
-                            } else {
-                                Some((
-                                    format!("cross-crate traits with a default impl, like `{}`, \
-                                             can only be implemented for a struct/enum type \
-                                             defined in the current crate",
-                                            self.tcx.item_path_str(trait_def_id)),
-                                    "can't implement cross-crate trait for type in another crate"
-                                ))
-                            }
-                        }
-                        _ => {
-                            Some((format!("cross-crate traits with a default impl, like `{}`, can \
-                                           only be implemented for a struct/enum type, not `{}`",
-                                          self.tcx.item_path_str(trait_def_id),
-                                          self_ty),
-                                  "can't implement cross-crate trait with a default impl for \
-                                   non-struct/enum type"))
+                let msg = match opt_self_def_id {
+                    // We only want to permit nominal types, but not *all* nominal types.
+                    // They must be local to the current crate, so that people
+                    // can't do `unsafe impl Send for Rc<SomethingLocal>` or
+                    // `impl !Send for Box<SomethingLocalAndSend>`.
+                    Some(self_def_id) => {
+                        if self_def_id.is_local() {
+                            None
+                        } else {
+                            Some((
+                                format!("cross-crate traits with a default impl, like `{}`, \
+                                         can only be implemented for a struct/enum type \
+                                         defined in the current crate",
+                                        self.tcx.item_path_str(trait_def_id)),
+                                "can't implement cross-crate trait for type in another crate"
+                            ))
                         }
-                    };
-
-                    if let Some((msg, label)) = msg {
-                        struct_span_err!(self.tcx.sess, sp, E0321, "{}", msg)
-                            .span_label(sp, label)
-                            .emit();
-                        return;
                     }
+                    _ => {
+                        Some((format!("cross-crate traits with a default impl, like `{}`, can \
+                                       only be implemented for a struct/enum type, not `{}`",
+                                      self.tcx.item_path_str(trait_def_id),
+                                      self_ty),
+                              "can't implement cross-crate trait with a default impl for \
+                               non-struct/enum type"))
+                    }
+                };
+
+                if let Some((msg, label)) = msg {
+                    struct_span_err!(self.tcx.sess, sp, E0321, "{}", msg)
+                        .span_label(sp, label)
+                        .emit();
+                    return;
                 }
             }
-            _ => {
-                // Not an impl
-            }
         }
     }