//! Orphan checker: every impl either implements a trait defined in this
//! crate or pertains to a type defined in this crate.

use rustc::traits;
use rustc::ty::{self, TyCtxt};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir;

pub fn check(tcx: TyCtxt<'_>) {
    let mut orphan = OrphanChecker { tcx };
    tcx.hir().krate().visit_all_item_likes(&mut orphan);
}

struct OrphanChecker<'tcx> {
    tcx: TyCtxt<'tcx>,
}

impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
    /// Checks exactly one impl for orphan rules and other such
    /// restrictions. In this fn, it can happen that multiple errors
    /// apply to a specific impl, so just return after reporting one
    /// to prevent inundating the user with a bunch of similar error
    /// reports.
    fn visit_item(&mut self, item: &hir::Item) {
        let def_id = self.tcx.hir().local_def_id(item.hir_id);
        // "Trait" impl
        if let hir::ItemKind::Impl(.., Some(_), _, _) = item.node {
            debug!("coherence2::orphan check: trait impl {}",
                   self.tcx.hir().node_to_string(item.hir_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 only 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,
                };

                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.def_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.def_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;
                }
            }
        }
    }

    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
    }

    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
    }
}
