//! Check properties that are required by built-in traits and set
//! up data structures required by type-checking/codegen.

use rustc::infer::SuppressRegionErrors;
use rustc::infer::outlives::env::OutlivesEnvironment;
use rustc::middle::region;
use rustc::middle::lang_items::UnsizeTraitLangItem;

use rustc::traits::{self, TraitEngine, ObligationCause};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::TypeFoldable;
use rustc::ty::adjustment::CoerceUnsizedInfo;
use rustc::ty::util::CopyImplementationError;
use rustc::infer;

use rustc::hir::def_id::DefId;
use hir::Node;
use rustc::hir::{self, ItemKind};

use rustc_error_codes::*;

pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
    Checker { tcx, trait_def_id }
        .check(tcx.lang_items().drop_trait(), visit_implementation_of_drop)
        .check(tcx.lang_items().copy_trait(), visit_implementation_of_copy)
        .check(tcx.lang_items().coerce_unsized_trait(), visit_implementation_of_coerce_unsized)
        .check(tcx.lang_items().dispatch_from_dyn_trait(),
            visit_implementation_of_dispatch_from_dyn);
}

struct Checker<'tcx> {
    tcx: TyCtxt<'tcx>,
    trait_def_id: DefId,
}

impl<'tcx> Checker<'tcx> {
    fn check<F>(&self, trait_def_id: Option<DefId>, mut f: F) -> &Self
    where
        F: FnMut(TyCtxt<'tcx>, DefId),
    {
        if Some(self.trait_def_id) == trait_def_id {
            for &impl_id in self.tcx.hir().trait_impls(self.trait_def_id) {
                let impl_def_id = self.tcx.hir().local_def_id(impl_id);
                f(self.tcx, impl_def_id);
            }
        }
        self
    }
}

fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: DefId) {
    if let ty::Adt(..) = tcx.type_of(impl_did).kind {
        /* do nothing */
    } else {
        // Destructors only work on nominal types.
        if let Some(impl_hir_id) = tcx.hir().as_local_hir_id(impl_did) {
            if let Some(Node::Item(item)) = tcx.hir().find(impl_hir_id) {
                let span = match item.kind {
                    ItemKind::Impl(.., ref ty, _) => ty.span,
                    _ => item.span,
                };
                struct_span_err!(tcx.sess,
                                 span,
                                 E0120,
                                 "the Drop trait may only be implemented on \
                                  structures")
                    .span_label(span, "implementing Drop requires a struct")
                    .emit();
            } else {
                bug!("didn't find impl in ast map");
            }
        } else {
            bug!("found external impl of Drop trait on \
                  something other than a struct");
        }
    }
}

fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: DefId) {
    debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);

    let impl_hir_id = if let Some(n) = tcx.hir().as_local_hir_id(impl_did) {
        n
    } else {
        debug!("visit_implementation_of_copy(): impl not in this crate");
        return;
    };

    let self_type = tcx.type_of(impl_did);
    debug!("visit_implementation_of_copy: self_type={:?} (bound)",
           self_type);

    let span = tcx.hir().span(impl_hir_id);
    let param_env = tcx.param_env(impl_did);
    assert!(!self_type.has_escaping_bound_vars());

    debug!("visit_implementation_of_copy: self_type={:?} (free)",
           self_type);

    match param_env.can_type_implement_copy(tcx, self_type) {
        Ok(()) => {}
        Err(CopyImplementationError::InfrigingFields(fields)) => {
            let item = tcx.hir().expect_item(impl_hir_id);
            let span = if let ItemKind::Impl(.., Some(ref tr), _, _) = item.kind {
                tr.path.span
            } else {
                span
            };

            let mut err = struct_span_err!(tcx.sess,
                                           span,
                                           E0204,
                                           "the trait `Copy` may not be implemented for this type");
            for span in fields.iter().map(|f| tcx.def_span(f.did)) {
                err.span_label(span, "this field does not implement `Copy`");
            }
            err.emit()
        }
        Err(CopyImplementationError::NotAnAdt) => {
            let item = tcx.hir().expect_item(impl_hir_id);
            let span = if let ItemKind::Impl(.., ref ty, _) = item.kind {
                ty.span
            } else {
                span
            };

            struct_span_err!(tcx.sess,
                             span,
                             E0206,
                             "the trait `Copy` may not be implemented for this type")
                .span_label(span, "type is not a structure or enumeration")
                .emit();
        }
        Err(CopyImplementationError::HasDestructor) => {
            struct_span_err!(tcx.sess,
                             span,
                             E0184,
                             "the trait `Copy` may not be implemented for this type; the \
                              type has a destructor")
                .span_label(span, "Copy not allowed on types with destructors")
                .emit();
        }
    }
}

fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'tcx>, impl_did: DefId) {
    debug!("visit_implementation_of_coerce_unsized: impl_did={:?}",
           impl_did);

    // Just compute this for the side-effects, in particular reporting
    // errors; other parts of the code may demand it for the info of
    // course.
    if impl_did.is_local() {
        let span = tcx.def_span(impl_did);
        tcx.at(span).coerce_unsized_info(impl_did);
    }
}

fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) {
    debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}",
           impl_did);
    if impl_did.is_local() {
        let dispatch_from_dyn_trait = tcx.lang_items().dispatch_from_dyn_trait().unwrap();

        let impl_hir_id = tcx.hir().as_local_hir_id(impl_did).unwrap();
        let span = tcx.hir().span(impl_hir_id);

        let source = tcx.type_of(impl_did);
        assert!(!source.has_escaping_bound_vars());
        let target = {
            let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
            assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);

            trait_ref.substs.type_at(1)
        };

        debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}",
            source,
            target);

        let param_env = tcx.param_env(impl_did);

        let create_err = |msg: &str| {
            struct_span_err!(tcx.sess, span, E0378, "{}", msg)
        };

        tcx.infer_ctxt().enter(|infcx| {
            let cause = ObligationCause::misc(span, impl_hir_id);

            use ty::TyKind::*;
            match (&source.kind, &target.kind) {
                (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b))
                    if infcx.at(&cause, param_env).eq(r_a, r_b).is_ok()
                    && mutbl_a == *mutbl_b => (),
                (&RawPtr(tm_a), &RawPtr(tm_b))
                    if tm_a.mutbl == tm_b.mutbl => (),
                (&Adt(def_a, substs_a), &Adt(def_b, substs_b))
                    if def_a.is_struct() && def_b.is_struct() =>
                {
                    if def_a != def_b {
                        let source_path = tcx.def_path_str(def_a.did);
                        let target_path = tcx.def_path_str(def_b.did);

                        create_err(
                            &format!(
                                "the trait `DispatchFromDyn` may only be implemented \
                                for a coercion between structures with the same \
                                definition; expected `{}`, found `{}`",
                                source_path, target_path,
                            )
                        ).emit();

                        return
                    }

                    if def_a.repr.c() || def_a.repr.packed() {
                        create_err(
                            "structs implementing `DispatchFromDyn` may not have \
                             `#[repr(packed)]` or `#[repr(C)]`"
                        ).emit();
                    }

                    let fields = &def_a.non_enum_variant().fields;

                    let coerced_fields = fields.iter().filter_map(|field| {
                        let ty_a = field.ty(tcx, substs_a);
                        let ty_b = field.ty(tcx, substs_b);

                        if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) {
                            if layout.is_zst() && layout.details.align.abi.bytes() == 1 {
                                // ignore ZST fields with alignment of 1 byte
                                return None;
                            }
                        }

                        if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) {
                            if ok.obligations.is_empty() {
                                create_err(
                                    "the trait `DispatchFromDyn` may only be implemented \
                                     for structs containing the field being coerced, \
                                     ZST fields with 1 byte alignment, and nothing else"
                                ).note(
                                    &format!(
                                        "extra field `{}` of type `{}` is not allowed",
                                        field.ident, ty_a,
                                    )
                                ).emit();

                                return None;
                            }
                        }

                        Some(field)
                    }).collect::<Vec<_>>();

                    if coerced_fields.is_empty() {
                        create_err(
                            "the trait `DispatchFromDyn` may only be implemented \
                            for a coercion between structures with a single field \
                            being coerced, none found"
                        ).emit();
                    } else if coerced_fields.len() > 1 {
                        create_err(
                            "implementing the `DispatchFromDyn` trait requires multiple coercions",
                        ).note(
                            "the trait `DispatchFromDyn` may only be implemented \
                                for a coercion between structures with a single field \
                                being coerced"
                        ).note(
                            &format!(
                                "currently, {} fields need coercions: {}",
                                coerced_fields.len(),
                                coerced_fields.iter().map(|field| {
                                    format!("`{}` (`{}` to `{}`)",
                                        field.ident,
                                        field.ty(tcx, substs_a),
                                        field.ty(tcx, substs_b),
                                    )
                                }).collect::<Vec<_>>()
                                .join(", ")
                            )
                        ).emit();
                    } else {
                        let mut fulfill_cx = TraitEngine::new(infcx.tcx);

                        for field in coerced_fields {

                            let predicate = tcx.predicate_for_trait_def(
                                param_env,
                                cause.clone(),
                                dispatch_from_dyn_trait,
                                0,
                                field.ty(tcx, substs_a),
                                &[field.ty(tcx, substs_b).into()]
                            );

                            fulfill_cx.register_predicate_obligation(&infcx, predicate);
                        }

                        // Check that all transitive obligations are satisfied.
                        if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
                            infcx.report_fulfillment_errors(&errors, None, false);
                        }

                        // Finally, resolve all regions.
                        let region_scope_tree = region::ScopeTree::default();
                        let outlives_env = OutlivesEnvironment::new(param_env);
                        infcx.resolve_regions_and_report_errors(
                            impl_did,
                            &region_scope_tree,
                            &outlives_env,
                            SuppressRegionErrors::default(),
                        );
                    }
                }
                _ => {
                    create_err(
                        "the trait `DispatchFromDyn` may only be implemented \
                        for a coercion between structures"
                    ).emit();
                }
            }
        })
    }
}

pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo {
    debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
    let coerce_unsized_trait = tcx.lang_items().coerce_unsized_trait().unwrap();

    let unsize_trait = tcx.lang_items().require(UnsizeTraitLangItem).unwrap_or_else(|err| {
        tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err));
    });

    // this provider should only get invoked for local def-ids
    let impl_hir_id = tcx.hir().as_local_hir_id(impl_did).unwrap_or_else(|| {
        bug!("coerce_unsized_info: invoked for non-local def-id {:?}", impl_did)
    });

    let source = tcx.type_of(impl_did);
    let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
    assert_eq!(trait_ref.def_id, coerce_unsized_trait);
    let target = trait_ref.substs.type_at(1);
    debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)",
           source,
           target);

    let span = tcx.hir().span(impl_hir_id);
    let param_env = tcx.param_env(impl_did);
    assert!(!source.has_escaping_bound_vars());

    let err_info = CoerceUnsizedInfo { custom_kind: None };

    debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)",
           source,
           target);

    tcx.infer_ctxt().enter(|infcx| {
        let cause = ObligationCause::misc(span, impl_hir_id);
        let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
                           mt_b: ty::TypeAndMut<'tcx>,
                           mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
            if (mt_a.mutbl, mt_b.mutbl) == (hir::Mutability::Immutable, hir::Mutability::Mutable) {
                infcx.report_mismatched_types(&cause,
                                              mk_ptr(mt_b.ty),
                                              target,
                                              ty::error::TypeError::Mutability)
                    .emit();
            }
            (mt_a.ty, mt_b.ty, unsize_trait, None)
        };
        let (source, target, trait_def_id, kind) = match (&source.kind, &target.kind) {
            (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => {
                infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a);
                let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
                let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
                check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ref(r_b, ty))
            }

            (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(mt_b)) => {
                let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
                check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty))
            }

            (&ty::RawPtr(mt_a), &ty::RawPtr(mt_b)) => {
                check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty))
            }

            (&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b)) if def_a.is_struct() &&
                                                                      def_b.is_struct() => {
                if def_a != def_b {
                    let source_path = tcx.def_path_str(def_a.did);
                    let target_path = tcx.def_path_str(def_b.did);
                    span_err!(tcx.sess,
                              span,
                              E0377,
                              "the trait `CoerceUnsized` may only be implemented \
                               for a coercion between structures with the same \
                               definition; expected `{}`, found `{}`",
                              source_path,
                              target_path);
                    return err_info;
                }

                // Here we are considering a case of converting
                // `S<P0...Pn>` to S<Q0...Qn>`. As an example, let's imagine a struct `Foo<T, U>`,
                // which acts like a pointer to `U`, but carries along some extra data of type `T`:
                //
                //     struct Foo<T, U> {
                //         extra: T,
                //         ptr: *mut U,
                //     }
                //
                // We might have an impl that allows (e.g.) `Foo<T, [i32; 3]>` to be unsized
                // to `Foo<T, [i32]>`. That impl would look like:
                //
                //   impl<T, U: Unsize<V>, V> CoerceUnsized<Foo<T, V>> for Foo<T, U> {}
                //
                // Here `U = [i32; 3]` and `V = [i32]`. At runtime,
                // when this coercion occurs, we would be changing the
                // field `ptr` from a thin pointer of type `*mut [i32;
                // 3]` to a fat pointer of type `*mut [i32]` (with
                // extra data `3`).  **The purpose of this check is to
                // make sure that we know how to do this conversion.**
                //
                // To check if this impl is legal, we would walk down
                // the fields of `Foo` and consider their types with
                // both substitutes. We are looking to find that
                // exactly one (non-phantom) field has changed its
                // type, which we will expect to be the pointer that
                // is becoming fat (we could probably generalize this
                // to multiple thin pointers of the same type becoming
                // fat, but we don't). In this case:
                //
                // - `extra` has type `T` before and type `T` after
                // - `ptr` has type `*mut U` before and type `*mut V` after
                //
                // Since just one field changed, we would then check
                // that `*mut U: CoerceUnsized<*mut V>` is implemented
                // (in other words, that we know how to do this
                // conversion). This will work out because `U:
                // Unsize<V>`, and we have a builtin rule that `*mut
                // U` can be coerced to `*mut V` if `U: Unsize<V>`.
                let fields = &def_a.non_enum_variant().fields;
                let diff_fields = fields.iter()
                    .enumerate()
                    .filter_map(|(i, f)| {
                        let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b));

                        if tcx.type_of(f.did).is_phantom_data() {
                            // Ignore PhantomData fields
                            return None;
                        }

                        // Ignore fields that aren't changed; it may
                        // be that we could get away with subtyping or
                        // something more accepting, but we use
                        // equality because we want to be able to
                        // perform this check without computing
                        // variance where possible. (This is because
                        // we may have to evaluate constraint
                        // expressions in the course of execution.)
                        // See e.g., #41936.
                        if let Ok(ok) = infcx.at(&cause, param_env).eq(a, b) {
                            if ok.obligations.is_empty() {
                                return None;
                            }
                        }

                        // Collect up all fields that were significantly changed
                        // i.e., those that contain T in coerce_unsized T -> U
                        Some((i, a, b))
                    })
                    .collect::<Vec<_>>();

                if diff_fields.is_empty() {
                    span_err!(tcx.sess,
                              span,
                              E0374,
                              "the trait `CoerceUnsized` may only be implemented \
                               for a coercion between structures with one field \
                               being coerced, none found");
                    return err_info;
                } else if diff_fields.len() > 1 {
                    let item = tcx.hir().expect_item(impl_hir_id);
                    let span = if let ItemKind::Impl(.., Some(ref t), _, _) = item.kind {
                        t.path.span
                    } else {
                        tcx.hir().span(impl_hir_id)
                    };

                    let mut err = struct_span_err!(tcx.sess,
                                                   span,
                                                   E0375,
                                                   "implementing the trait \
                                                    `CoerceUnsized` requires multiple \
                                                    coercions");
                    err.note("`CoerceUnsized` may only be implemented for \
                              a coercion between structures with one field being coerced");
                    err.note(&format!("currently, {} fields need coercions: {}",
                                      diff_fields.len(),
                                      diff_fields.iter()
                                          .map(|&(i, a, b)| {
                                              format!("`{}` (`{}` to `{}`)", fields[i].ident, a, b)
                                          })
                                          .collect::<Vec<_>>()
                                          .join(", ")));
                    err.span_label(span, "requires multiple coercions");
                    err.emit();
                    return err_info;
                }

                let (i, a, b) = diff_fields[0];
                let kind = ty::adjustment::CustomCoerceUnsized::Struct(i);
                (a, b, coerce_unsized_trait, Some(kind))
            }

            _ => {
                span_err!(tcx.sess,
                          span,
                          E0376,
                          "the trait `CoerceUnsized` may only be implemented \
                           for a coercion between structures");
                return err_info;
            }
        };

        let mut fulfill_cx = TraitEngine::new(infcx.tcx);

        // Register an obligation for `A: Trait<B>`.
        let cause = traits::ObligationCause::misc(span, impl_hir_id);
        let predicate = tcx.predicate_for_trait_def(param_env,
                                                    cause,
                                                    trait_def_id,
                                                    0,
                                                    source,
                                                    &[target.into()]);
        fulfill_cx.register_predicate_obligation(&infcx, predicate);

        // Check that all transitive obligations are satisfied.
        if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
            infcx.report_fulfillment_errors(&errors, None, false);
        }

        // Finally, resolve all regions.
        let region_scope_tree = region::ScopeTree::default();
        let outlives_env = OutlivesEnvironment::new(param_env);
        infcx.resolve_regions_and_report_errors(
            impl_did,
            &region_scope_tree,
            &outlives_env,
            SuppressRegionErrors::default(),
        );

        CoerceUnsizedInfo {
            custom_kind: kind
        }
    })
}
