// Copyright 2014 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 super::{
    FulfillmentError,
    FulfillmentErrorCode,
    MismatchedProjectionTypes,
    Obligation,
    ObligationCause,
    ObligationCauseCode,
    OutputTypeParameterMismatch,
    TraitNotObjectSafe,
    PredicateObligation,
    SelectionContext,
    SelectionError,
    ObjectSafetyViolation,
    MethodViolationCode,
};

use fmt_macros::{Parser, Piece, Position};
use hir::def_id::DefId;
use infer::{self, InferCtxt, TypeOrigin};
use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
use ty::error::ExpectedFound;
use ty::fast_reject;
use ty::fold::TypeFolder;
use ty::subst::{self, Subst, TypeSpace};
use util::nodemap::{FnvHashMap, FnvHashSet};

use std::cmp;
use std::fmt;
use syntax::ast;
use syntax::attr::{AttributeMethods, AttrMetaMethods};
use syntax_pos::Span;
use errors::DiagnosticBuilder;

#[derive(Debug, PartialEq, Eq, Hash)]
pub struct TraitErrorKey<'tcx> {
    span: Span,
    warning_node_id: Option<ast::NodeId>,
    predicate: ty::Predicate<'tcx>
}

impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
    fn from_error(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                  e: &FulfillmentError<'tcx>,
                  warning_node_id: Option<ast::NodeId>) -> Self {
        let predicate =
            infcx.resolve_type_vars_if_possible(&e.obligation.predicate);
        TraitErrorKey {
            span: e.obligation.cause.span,
            predicate: infcx.tcx.erase_regions(&predicate),
            warning_node_id: warning_node_id
        }
    }
}

impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
    pub fn report_fulfillment_errors(&self, errors: &Vec<FulfillmentError<'tcx>>) {
        for error in errors {
            self.report_fulfillment_error(error, None);
        }
    }

    pub fn report_fulfillment_errors_as_warnings(&self,
                                                 errors: &Vec<FulfillmentError<'tcx>>,
                                                 node_id: ast::NodeId) {
        for error in errors {
            self.report_fulfillment_error(error, Some(node_id));
        }
    }

    fn report_fulfillment_error(&self,
                                error: &FulfillmentError<'tcx>,
                                warning_node_id: Option<ast::NodeId>) {
        let error_key = TraitErrorKey::from_error(self, error, warning_node_id);
        debug!("report_fulfillment_errors({:?}) - key={:?}",
               error, error_key);
        if !self.reported_trait_errors.borrow_mut().insert(error_key) {
            debug!("report_fulfillment_errors: skipping duplicate");
            return;
        }
        match error.code {
            FulfillmentErrorCode::CodeSelectionError(ref e) => {
                self.report_selection_error(&error.obligation, e, warning_node_id);
            }
            FulfillmentErrorCode::CodeProjectionError(ref e) => {
                self.report_projection_error(&error.obligation, e, warning_node_id);
            }
            FulfillmentErrorCode::CodeAmbiguity => {
                self.maybe_report_ambiguity(&error.obligation);
            }
        }
    }

    fn report_projection_error(&self,
                               obligation: &PredicateObligation<'tcx>,
                               error: &MismatchedProjectionTypes<'tcx>,
                               warning_node_id: Option<ast::NodeId>)
    {
        let predicate =
            self.resolve_type_vars_if_possible(&obligation.predicate);

        if predicate.references_error() {
            return
        }
        if let Some(warning_node_id) = warning_node_id {
            self.tcx.sess.add_lint(
                ::lint::builtin::UNSIZED_IN_TUPLE,
                warning_node_id,
                obligation.cause.span,
                format!("type mismatch resolving `{}`: {}",
                        predicate,
                        error.err));
            return
        }
        self.probe(|_| {
            let origin = TypeOrigin::Misc(obligation.cause.span);
            let err_buf;
            let mut err = &error.err;
            let mut values = None;

            // try to find the mismatched types to report the error with.
            //
            // this can fail if the problem was higher-ranked, in which
            // cause I have no idea for a good error message.
            if let ty::Predicate::Projection(ref data) = predicate {
                let mut selcx = SelectionContext::new(self);
                let (data, _) = self.replace_late_bound_regions_with_fresh_var(
                    obligation.cause.span,
                    infer::LateBoundRegionConversionTime::HigherRankedType,
                    data);
                let normalized = super::normalize_projection_type(
                    &mut selcx,
                    data.projection_ty,
                    obligation.cause.clone(),
                    0
                );
                let origin = TypeOrigin::Misc(obligation.cause.span);
                if let Err(error) = self.eq_types(
                    false, origin,
                    data.ty, normalized.value
                ) {
                    values = Some(infer::ValuePairs::Types(ExpectedFound {
                        expected: normalized.value,
                        found: data.ty,
                    }));
                    err_buf = error;
                    err = &err_buf;
                }
            }

            let mut diag = struct_span_err!(
                self.tcx.sess, origin.span(), E0271,
                "type mismatch resolving `{}`", predicate
            );
            self.note_type_err(&mut diag, origin, values, err);
            self.note_obligation_cause(&mut diag, obligation);
            diag.emit();
        });
    }

    fn impl_substs(&self,
                   did: DefId,
                   obligation: PredicateObligation<'tcx>)
                   -> subst::Substs<'tcx> {
        let tcx = self.tcx;

        let ity = tcx.lookup_item_type(did);
        let (tps, rps, _) =
            (ity.generics.types.get_slice(TypeSpace),
             ity.generics.regions.get_slice(TypeSpace),
             ity.ty);

        let rps = self.region_vars_for_defs(obligation.cause.span, rps);
        let mut substs = subst::Substs::new(
            subst::VecPerParamSpace::empty(),
            subst::VecPerParamSpace::new(rps, Vec::new(), Vec::new()));
        self.type_vars_for_defs(obligation.cause.span,
                                TypeSpace,
                                &mut substs,
                                tps);
        substs
    }

    fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
        /// returns the fuzzy category of a given type, or None
        /// if the type can be equated to any type.
        fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> {
            match t.sty {
                ty::TyBool => Some(0),
                ty::TyChar => Some(1),
                ty::TyStr => Some(2),
                ty::TyInt(..) | ty::TyUint(..) |
                ty::TyInfer(ty::IntVar(..)) => Some(3),
                ty::TyFloat(..) | ty::TyInfer(ty::FloatVar(..)) => Some(4),
                ty::TyEnum(..) => Some(5),
                ty::TyStruct(..) => Some(6),
                ty::TyBox(..) | ty::TyRef(..) | ty::TyRawPtr(..) => Some(7),
                ty::TyArray(..) | ty::TySlice(..) => Some(8),
                ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(9),
                ty::TyTrait(..) => Some(10),
                ty::TyClosure(..) => Some(11),
                ty::TyTuple(..) => Some(12),
                ty::TyProjection(..) => Some(13),
                ty::TyParam(..) => Some(14),
                ty::TyInfer(..) | ty::TyError => None
            }
        }

        match (type_category(a), type_category(b)) {
            (Some(cat_a), Some(cat_b)) => match (&a.sty, &b.sty) {
                (&ty::TyStruct(def_a, _), &ty::TyStruct(def_b, _)) |
                (&ty::TyEnum(def_a, _), &ty::TyEnum(def_b, _)) =>
                    def_a == def_b,
                _ => cat_a == cat_b
            },
            // infer and error can be equated to all types
            _ => true
        }
    }

    fn impl_similar_to(&self,
                       trait_ref: ty::PolyTraitRef<'tcx>,
                       obligation: &PredicateObligation<'tcx>)
                       -> Option<DefId>
    {
        let tcx = self.tcx;

        let trait_ref = tcx.erase_late_bound_regions(&trait_ref);
        let trait_self_ty = trait_ref.self_ty();

        let mut self_match_impls = vec![];
        let mut fuzzy_match_impls = vec![];

        self.tcx.lookup_trait_def(trait_ref.def_id)
            .for_each_relevant_impl(self.tcx, trait_self_ty, |def_id| {
                let impl_trait_ref = tcx
                    .impl_trait_ref(def_id)
                    .unwrap()
                    .subst(tcx, &self.impl_substs(def_id, obligation.clone()));

                let impl_self_ty = impl_trait_ref.self_ty();

                if let Ok(..) = self.can_equate(&trait_self_ty, &impl_self_ty) {
                    self_match_impls.push(def_id);

                    if trait_ref.substs.types.get_slice(TypeSpace).iter()
                        .zip(impl_trait_ref.substs.types.get_slice(TypeSpace))
                        .all(|(u,v)| self.fuzzy_match_tys(u, v))
                    {
                        fuzzy_match_impls.push(def_id);
                    }
                }
            });

        let impl_def_id = if self_match_impls.len() == 1 {
            self_match_impls[0]
        } else if fuzzy_match_impls.len() == 1 {
            fuzzy_match_impls[0]
        } else {
            return None
        };

        if tcx.has_attr(impl_def_id, "rustc_on_unimplemented") {
            Some(impl_def_id)
        } else {
            None
        }
    }

    fn on_unimplemented_note(&self,
                             trait_ref: ty::PolyTraitRef<'tcx>,
                             obligation: &PredicateObligation<'tcx>) -> Option<String> {
        let def_id = self.impl_similar_to(trait_ref, obligation)
            .unwrap_or(trait_ref.def_id());
        let trait_ref = trait_ref.skip_binder();

        let span = obligation.cause.span;
        let mut report = None;
        for item in self.tcx.get_attrs(def_id).iter() {
            if item.check_name("rustc_on_unimplemented") {
                let err_sp = item.meta().span.substitute_dummy(span);
                let def = self.tcx.lookup_trait_def(trait_ref.def_id);
                let trait_str = def.trait_ref.to_string();
                if let Some(ref istring) = item.value_str() {
                    let mut generic_map = def.generics.types.iter_enumerated()
                                             .map(|(param, i, gen)| {
                                                   (gen.name.as_str().to_string(),
                                                    trait_ref.substs.types.get(param, i)
                                                             .to_string())
                                                  }).collect::<FnvHashMap<String, String>>();
                    generic_map.insert("Self".to_string(),
                                       trait_ref.self_ty().to_string());
                    let parser = Parser::new(&istring);
                    let mut errored = false;
                    let err: String = parser.filter_map(|p| {
                        match p {
                            Piece::String(s) => Some(s),
                            Piece::NextArgument(a) => match a.position {
                                Position::ArgumentNamed(s) => match generic_map.get(s) {
                                    Some(val) => Some(val),
                                    None => {
                                        span_err!(self.tcx.sess, err_sp, E0272,
                                                       "the #[rustc_on_unimplemented] \
                                                                attribute on \
                                                                trait definition for {} refers to \
                                                                non-existent type parameter {}",
                                                               trait_str, s);
                                        errored = true;
                                        None
                                    }
                                },
                                _ => {
                                    span_err!(self.tcx.sess, err_sp, E0273,
                                              "the #[rustc_on_unimplemented] attribute \
                                               on trait definition for {} must have \
                                               named format arguments, eg \
                                               `#[rustc_on_unimplemented = \
                                                \"foo {{T}}\"]`", trait_str);
                                    errored = true;
                                    None
                                }
                            }
                        }
                    }).collect();
                    // Report only if the format string checks out
                    if !errored {
                        report = Some(err);
                    }
                } else {
                    span_err!(self.tcx.sess, err_sp, E0274,
                                            "the #[rustc_on_unimplemented] attribute on \
                                                     trait definition for {} must have a value, \
                                                     eg `#[rustc_on_unimplemented = \"foo\"]`",
                                                     trait_str);
                }
                break;
            }
        }
        report
    }

    fn find_similar_impl_candidates(&self,
                                    trait_ref: ty::PolyTraitRef<'tcx>)
                                    -> Vec<ty::TraitRef<'tcx>>
    {
        let simp = fast_reject::simplify_type(self.tcx,
                                              trait_ref.skip_binder().self_ty(),
                                              true);
        let mut impl_candidates = Vec::new();
        let trait_def = self.tcx.lookup_trait_def(trait_ref.def_id());

        match simp {
            Some(simp) => trait_def.for_each_impl(self.tcx, |def_id| {
                let imp = self.tcx.impl_trait_ref(def_id).unwrap();
                let imp_simp = fast_reject::simplify_type(self.tcx,
                                                          imp.self_ty(),
                                                          true);
                if let Some(imp_simp) = imp_simp {
                    if simp != imp_simp {
                        return;
                    }
                }
                impl_candidates.push(imp);
            }),
            None => trait_def.for_each_impl(self.tcx, |def_id| {
                impl_candidates.push(
                    self.tcx.impl_trait_ref(def_id).unwrap());
            })
        };
        impl_candidates
    }

    fn report_similar_impl_candidates(&self,
                                      trait_ref: ty::PolyTraitRef<'tcx>,
                                      err: &mut DiagnosticBuilder)
    {
        let simp = fast_reject::simplify_type(self.tcx,
                                              trait_ref.skip_binder().self_ty(),
                                              true);
        let mut impl_candidates = Vec::new();
        let trait_def = self.tcx.lookup_trait_def(trait_ref.def_id());

        match simp {
            Some(simp) => trait_def.for_each_impl(self.tcx, |def_id| {
                let imp = self.tcx.impl_trait_ref(def_id).unwrap();
                let imp_simp = fast_reject::simplify_type(self.tcx,
                                                          imp.self_ty(),
                                                          true);
                if let Some(imp_simp) = imp_simp {
                    if simp != imp_simp {
                        return;
                    }
                }
                impl_candidates.push(imp);
            }),
            None => trait_def.for_each_impl(self.tcx, |def_id| {
                impl_candidates.push(
                    self.tcx.impl_trait_ref(def_id).unwrap());
            })
        };

        if impl_candidates.is_empty() {
            return;
        }

        err.help(&format!("the following implementations were found:"));

        let end = cmp::min(4, impl_candidates.len());
        for candidate in &impl_candidates[0..end] {
            err.help(&format!("  {:?}", candidate));
        }
        if impl_candidates.len() > 4 {
            err.help(&format!("and {} others", impl_candidates.len()-4));
        }
    }

    /// Reports that an overflow has occurred and halts compilation. We
    /// halt compilation unconditionally because it is important that
    /// overflows never be masked -- they basically represent computations
    /// whose result could not be truly determined and thus we can't say
    /// if the program type checks or not -- and they are unusual
    /// occurrences in any case.
    pub fn report_overflow_error<T>(&self,
                                    obligation: &Obligation<'tcx, T>,
                                    suggest_increasing_limit: bool) -> !
        where T: fmt::Display + TypeFoldable<'tcx>
    {
        let predicate =
            self.resolve_type_vars_if_possible(&obligation.predicate);
        let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0275,
                                       "overflow evaluating the requirement `{}`",
                                       predicate);

        if suggest_increasing_limit {
            self.suggest_new_overflow_limit(&mut err);
        }

        self.note_obligation_cause(&mut err, obligation);

        err.emit();
        self.tcx.sess.abort_if_errors();
        bug!();
    }

    /// Reports that a cycle was detected which led to overflow and halts
    /// compilation. This is equivalent to `report_overflow_error` except
    /// that we can give a more helpful error message (and, in particular,
    /// we do not suggest increasing the overflow limit, which is not
    /// going to help).
    pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
        let cycle = self.resolve_type_vars_if_possible(&cycle.to_owned());
        assert!(cycle.len() > 0);

        debug!("report_overflow_error_cycle: cycle={:?}", cycle);

        self.report_overflow_error(&cycle[0], false);
    }

    pub fn report_selection_error(&self,
                                  obligation: &PredicateObligation<'tcx>,
                                  error: &SelectionError<'tcx>,
                                  warning_node_id: Option<ast::NodeId>)
    {
        let span = obligation.cause.span;
        let mut err = match *error {
            SelectionError::Unimplemented => {
                if let ObligationCauseCode::CompareImplMethodObligation = obligation.cause.code {
                    span_err!(
                        self.tcx.sess, span, E0276,
                        "the requirement `{}` appears on the impl \
                         method but not on the corresponding trait method",
                        obligation.predicate);
                    return;
                } else {
                    match obligation.predicate {
                        ty::Predicate::Trait(ref trait_predicate) => {
                            let trait_predicate =
                                self.resolve_type_vars_if_possible(trait_predicate);

                            if self.tcx.sess.has_errors() && trait_predicate.references_error() {
                                return;
                            } else {
                                let trait_ref = trait_predicate.to_poly_trait_ref();

                                if let Some(warning_node_id) = warning_node_id {
                                    self.tcx.sess.add_lint(
                                        ::lint::builtin::UNSIZED_IN_TUPLE,
                                        warning_node_id,
                                        obligation.cause.span,
                                        format!("the trait bound `{}` is not satisfied",
                                                trait_ref.to_predicate()));
                                    return;
                                }

                                let mut err = struct_span_err!(
                                    self.tcx.sess, span, E0277,
                                    "the trait bound `{}` is not satisfied",
                                    trait_ref.to_predicate());

                                // Try to report a help message

                                if !trait_ref.has_infer_types() &&
                                    self.predicate_can_apply(trait_ref) {
                                    // If a where-clause may be useful, remind the
                                    // user that they can add it.
                                    //
                                    // don't display an on-unimplemented note, as
                                    // these notes will often be of the form
                                    //     "the type `T` can't be frobnicated"
                                    // which is somewhat confusing.
                                    err.help(&format!("consider adding a `where {}` bound",
                                                      trait_ref.to_predicate()));
                                } else if let Some(s) = self.on_unimplemented_note(trait_ref,
                                                                                   obligation) {
                                    // If it has a custom "#[rustc_on_unimplemented]"
                                    // error message, let's display it!
                                    err.note(&s);
                                } else {
                                    // If we can't show anything useful, try to find
                                    // similar impls.
                                    let impl_candidates =
                                        self.find_similar_impl_candidates(trait_ref);
                                    if impl_candidates.len() > 0 {
                                        self.report_similar_impl_candidates(trait_ref, &mut err);
                                    }
                                }
                                err
                            }
                        }

                        ty::Predicate::Equate(ref predicate) => {
                            let predicate = self.resolve_type_vars_if_possible(predicate);
                            let err = self.equality_predicate(span,
                                                              &predicate).err().unwrap();
                            struct_span_err!(self.tcx.sess, span, E0278,
                                "the requirement `{}` is not satisfied (`{}`)",
                                predicate, err)
                        }

                        ty::Predicate::RegionOutlives(ref predicate) => {
                            let predicate = self.resolve_type_vars_if_possible(predicate);
                            let err = self.region_outlives_predicate(span,
                                                                     &predicate).err().unwrap();
                            struct_span_err!(self.tcx.sess, span, E0279,
                                "the requirement `{}` is not satisfied (`{}`)",
                                predicate, err)
                        }

                        ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
                            let predicate =
                                self.resolve_type_vars_if_possible(&obligation.predicate);
                            struct_span_err!(self.tcx.sess, span, E0280,
                                "the requirement `{}` is not satisfied",
                                predicate)
                        }

                        ty::Predicate::ObjectSafe(trait_def_id) => {
                            let violations = self.tcx.object_safety_violations(trait_def_id);
                            let err = self.tcx.report_object_safety_error(span,
                                                                          trait_def_id,
                                                                          warning_node_id,
                                                                          violations);
                            if let Some(err) = err {
                                err
                            } else {
                                return;
                            }
                        }

                        ty::Predicate::ClosureKind(closure_def_id, kind) => {
                            let found_kind = self.closure_kind(closure_def_id).unwrap();
                            let closure_span = self.tcx.map.span_if_local(closure_def_id).unwrap();
                            let mut err = struct_span_err!(
                                self.tcx.sess, closure_span, E0525,
                                "expected a closure that implements the `{}` trait, \
                                 but this closure only implements `{}`",
                                kind,
                                found_kind);
                            err.span_note(
                                obligation.cause.span,
                                &format!("the requirement to implement \
                                          `{}` derives from here", kind));
                            err.emit();
                            return;
                        }

                        ty::Predicate::WellFormed(ty) => {
                            // WF predicates cannot themselves make
                            // errors. They can only block due to
                            // ambiguity; otherwise, they always
                            // degenerate into other obligations
                            // (which may fail).
                            span_bug!(span, "WF predicate not satisfied for {:?}", ty);
                        }

                        ty::Predicate::Rfc1592(ref data) => {
                            span_bug!(
                                obligation.cause.span,
                                "RFC1592 predicate not satisfied for {:?}",
                                data);
                        }
                    }
                }
            }

            OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
                let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref);
                let actual_trait_ref = self.resolve_type_vars_if_possible(&*actual_trait_ref);
                if actual_trait_ref.self_ty().references_error() {
                    return;
                }
                struct_span_err!(self.tcx.sess, span, E0281,
                    "type mismatch: the type `{}` implements the trait `{}`, \
                     but the trait `{}` is required ({})",
                    expected_trait_ref.self_ty(),
                    expected_trait_ref,
                    actual_trait_ref,
                    e)
            }

            TraitNotObjectSafe(did) => {
                let violations = self.tcx.object_safety_violations(did);
                let err = self.tcx.report_object_safety_error(span, did,
                                                              warning_node_id,
                                                              violations);
                if let Some(err) = err {
                    err
                } else {
                    return;
                }
            }
        };
        self.note_obligation_cause(&mut err, obligation);
        err.emit();
    }
}

impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
    pub fn recursive_type_with_infinite_size_error(self,
                                                   type_def_id: DefId)
                                                   -> DiagnosticBuilder<'tcx>
    {
        assert!(type_def_id.is_local());
        let span = self.map.span_if_local(type_def_id).unwrap();
        let mut err = struct_span_err!(self.sess, span, E0072,
                                       "recursive type `{}` has infinite size",
                                       self.item_path_str(type_def_id));
        err.help(&format!("insert indirection (e.g., a `Box`, `Rc`, or `&`) \
                           at some point to make `{}` representable",
                          self.item_path_str(type_def_id)));
        err
    }

    pub fn report_object_safety_error(self,
                                      span: Span,
                                      trait_def_id: DefId,
                                      warning_node_id: Option<ast::NodeId>,
                                      violations: Vec<ObjectSafetyViolation>)
                                      -> Option<DiagnosticBuilder<'tcx>>
    {
        let mut err = match warning_node_id {
            Some(_) => None,
            None => {
                Some(struct_span_err!(
                    self.sess, span, E0038,
                    "the trait `{}` cannot be made into an object",
                    self.item_path_str(trait_def_id)))
            }
        };

        let mut reported_violations = FnvHashSet();
        for violation in violations {
            if !reported_violations.insert(violation.clone()) {
                continue;
            }
            let buf;
            let note = match violation {
                ObjectSafetyViolation::SizedSelf => {
                    "the trait cannot require that `Self : Sized`"
                }

                ObjectSafetyViolation::SupertraitSelf => {
                    "the trait cannot use `Self` as a type parameter \
                         in the supertrait listing"
                }

                ObjectSafetyViolation::Method(method,
                                              MethodViolationCode::StaticMethod) => {
                    buf = format!("method `{}` has no receiver",
                                  method.name);
                    &buf
                }

                ObjectSafetyViolation::Method(method,
                                              MethodViolationCode::ReferencesSelf) => {
                    buf = format!("method `{}` references the `Self` type \
                                       in its arguments or return type",
                                  method.name);
                    &buf
                }

                ObjectSafetyViolation::Method(method,
                                              MethodViolationCode::Generic) => {
                    buf = format!("method `{}` has generic type parameters",
                                  method.name);
                    &buf
                }
            };
            match (warning_node_id, &mut err) {
                (Some(node_id), &mut None) => {
                    self.sess.add_lint(
                        ::lint::builtin::OBJECT_UNSAFE_FRAGMENT,
                        node_id,
                        span,
                        note.to_string());
                }
                (None, &mut Some(ref mut err)) => {
                    err.note(note);
                }
                _ => unreachable!()
            }
        }
        err
    }
}

impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
    fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
        // Unable to successfully determine, probably means
        // insufficient type information, but could mean
        // ambiguous impls. The latter *ought* to be a
        // coherence violation, so we don't report it here.

        let predicate = self.resolve_type_vars_if_possible(&obligation.predicate);

        debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
               predicate,
               obligation);

        // Ambiguity errors are often caused as fallout from earlier
        // errors. So just ignore them if this infcx is tainted.
        if self.is_tainted_by_errors() {
            return;
        }

        match predicate {
            ty::Predicate::Trait(ref data) => {
                let trait_ref = data.to_poly_trait_ref();
                let self_ty = trait_ref.self_ty();
                let all_types = &trait_ref.substs().types;
                if all_types.references_error() {
                } else {
                    // Typically, this ambiguity should only happen if
                    // there are unresolved type inference variables
                    // (otherwise it would suggest a coherence
                    // failure). But given #21974 that is not necessarily
                    // the case -- we can have multiple where clauses that
                    // are only distinguished by a region, which results
                    // in an ambiguity even when all types are fully
                    // known, since we don't dispatch based on region
                    // relationships.

                    // This is kind of a hack: it frequently happens that some earlier
                    // error prevents types from being fully inferred, and then we get
                    // a bunch of uninteresting errors saying something like "<generic
                    // #0> doesn't implement Sized".  It may even be true that we
                    // could just skip over all checks where the self-ty is an
                    // inference variable, but I was afraid that there might be an
                    // inference variable created, registered as an obligation, and
                    // then never forced by writeback, and hence by skipping here we'd
                    // be ignoring the fact that we don't KNOW the type works
                    // out. Though even that would probably be harmless, given that
                    // we're only talking about builtin traits, which are known to be
                    // inhabited. But in any case I just threw in this check for
                    // has_errors() to be sure that compilation isn't happening
                    // anyway. In that case, why inundate the user.
                    if !self.tcx.sess.has_errors() {
                        if
                            self.tcx.lang_items.sized_trait()
                            .map_or(false, |sized_id| sized_id == trait_ref.def_id())
                        {
                            self.need_type_info(obligation.cause.span, self_ty);
                        } else {
                            let mut err = struct_span_err!(self.tcx.sess,
                                                           obligation.cause.span, E0283,
                                                           "type annotations required: \
                                                            cannot resolve `{}`",
                                                           predicate);
                            self.note_obligation_cause(&mut err, obligation);
                            err.emit();
                        }
                    }
                }
            }

            ty::Predicate::WellFormed(ty) => {
                // Same hacky approach as above to avoid deluging user
                // with error messages.
                if !ty.references_error() && !self.tcx.sess.has_errors() {
                    self.need_type_info(obligation.cause.span, ty);
                }
            }

            _ => {
                if !self.tcx.sess.has_errors() {
                    let mut err = struct_span_err!(self.tcx.sess,
                                                   obligation.cause.span, E0284,
                                                   "type annotations required: \
                                                    cannot resolve `{}`",
                                                   predicate);
                    self.note_obligation_cause(&mut err, obligation);
                    err.emit();
                }
            }
        }
    }

    /// Returns whether the trait predicate may apply for *some* assignment
    /// to the type parameters.
    fn predicate_can_apply(&self, pred: ty::PolyTraitRef<'tcx>) -> bool {
        struct ParamToVarFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
            infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
            var_map: FnvHashMap<Ty<'tcx>, Ty<'tcx>>
        }

        impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ParamToVarFolder<'a, 'gcx, 'tcx> {
            fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx }

            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                if let ty::TyParam(..) = ty.sty {
                    let infcx = self.infcx;
                    self.var_map.entry(ty).or_insert_with(|| infcx.next_ty_var())
                } else {
                    ty.super_fold_with(self)
                }
            }
        }

        self.probe(|_| {
            let mut selcx = SelectionContext::new(self);

            let cleaned_pred = pred.fold_with(&mut ParamToVarFolder {
                infcx: self,
                var_map: FnvHashMap()
            });

            let cleaned_pred = super::project::normalize(
                &mut selcx,
                ObligationCause::dummy(),
                &cleaned_pred
            ).value;

            let obligation = Obligation::new(
                ObligationCause::dummy(),
                cleaned_pred.to_predicate()
            );

            selcx.evaluate_obligation(&obligation)
        })
    }


    fn need_type_info(&self, span: Span, ty: Ty<'tcx>) {
        span_err!(self.tcx.sess, span, E0282,
                  "unable to infer enough type information about `{}`; \
                   type annotations or generic parameter binding required",
                  ty);
    }

    fn note_obligation_cause<T>(&self,
                                err: &mut DiagnosticBuilder,
                                obligation: &Obligation<'tcx, T>)
        where T: fmt::Display
    {
        self.note_obligation_cause_code(err,
                                        &obligation.predicate,
                                        &obligation.cause.code);
    }

    fn note_obligation_cause_code<T>(&self,
                                     err: &mut DiagnosticBuilder,
                                     predicate: &T,
                                     cause_code: &ObligationCauseCode<'tcx>)
        where T: fmt::Display
    {
        let tcx = self.tcx;
        match *cause_code {
            ObligationCauseCode::MiscObligation => { }
            ObligationCauseCode::SliceOrArrayElem => {
                err.note("slice and array elements must have `Sized` type");
            }
            ObligationCauseCode::TupleElem => {
                err.note("tuple elements must have `Sized` type");
            }
            ObligationCauseCode::ProjectionWf(data) => {
                err.note(&format!("required so that the projection `{}` is well-formed",
                                  data));
            }
            ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
                err.note(&format!("required so that reference `{}` does not outlive its referent",
                                  ref_ty));
            }
            ObligationCauseCode::ItemObligation(item_def_id) => {
                let item_name = tcx.item_path_str(item_def_id);
                err.note(&format!("required by `{}`", item_name));
            }
            ObligationCauseCode::ObjectCastObligation(object_ty) => {
                err.note(&format!("required for the cast to the object type `{}`",
                                  self.ty_to_string(object_ty)));
            }
            ObligationCauseCode::RepeatVec => {
                err.note("the `Copy` trait is required because the \
                          repeated element will be copied");
            }
            ObligationCauseCode::VariableType(_) => {
                err.note("all local variables must have a statically known size");
            }
            ObligationCauseCode::ReturnType => {
                err.note("the return type of a function must have a \
                          statically known size");
            }
            ObligationCauseCode::AssignmentLhsSized => {
                err.note("the left-hand-side of an assignment must have a statically known size");
            }
            ObligationCauseCode::StructInitializerSized => {
                err.note("structs must have a statically known size to be initialized");
            }
            ObligationCauseCode::ClosureCapture(var_id, _, builtin_bound) => {
                let def_id = tcx.lang_items.from_builtin_kind(builtin_bound).unwrap();
                let trait_name = tcx.item_path_str(def_id);
                let name = tcx.local_var_name_str(var_id);
                err.note(
                    &format!("the closure that captures `{}` requires that all captured variables \
                              implement the trait `{}`",
                             name,
                             trait_name));
            }
            ObligationCauseCode::FieldSized => {
                err.note("only the last field of a struct or enum variant \
                          may have a dynamically sized type");
            }
            ObligationCauseCode::ConstSized => {
                err.note("constant expressions must have a statically known size");
            }
            ObligationCauseCode::SharedStatic => {
                err.note("shared static variables must have a type that implements `Sync`");
            }
            ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
                let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref);
                err.note(&format!("required because it appears within the type `{}`",
                                  parent_trait_ref.0.self_ty()));
                let parent_predicate = parent_trait_ref.to_predicate();
                self.note_obligation_cause_code(err,
                                                &parent_predicate,
                                                &data.parent_code);
            }
            ObligationCauseCode::ImplDerivedObligation(ref data) => {
                let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref);
                err.note(
                    &format!("required because of the requirements on the impl of `{}` for `{}`",
                             parent_trait_ref,
                             parent_trait_ref.0.self_ty()));
                let parent_predicate = parent_trait_ref.to_predicate();
                self.note_obligation_cause_code(err,
                                                &parent_predicate,
                                                &data.parent_code);
            }
            ObligationCauseCode::CompareImplMethodObligation => {
                err.note(
                    &format!("the requirement `{}` appears on the impl method \
                              but not on the corresponding trait method",
                             predicate));
            }
        }
    }

    fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder) {
        let current_limit = self.tcx.sess.recursion_limit.get();
        let suggested_limit = current_limit * 2;
        err.note(&format!(
                          "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
                          suggested_limit));
    }
}
