// Copyright 2012-2015 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.

/*

# check.rs

Within the check phase of type check, we check each item one at a time
(bodies of function expressions are checked as part of the containing
function).  Inference is used to supply types wherever they are
unknown.

By far the most complex case is checking the body of a function. This
can be broken down into several distinct phases:

- gather: creates type variables to represent the type of each local
  variable and pattern binding.

- main: the main pass does the lion's share of the work: it
  determines the types of all expressions, resolves
  methods, checks for most invalid conditions, and so forth.  In
  some cases, where a type is unknown, it may create a type or region
  variable and use that as the type of an expression.

  In the process of checking, various constraints will be placed on
  these type variables through the subtyping relationships requested
  through the `demand` module.  The `infer` module is in charge
  of resolving those constraints.

- regionck: after main is complete, the regionck pass goes over all
  types looking for regions and making sure that they did not escape
  into places they are not in scope.  This may also influence the
  final assignments of the various region variables if there is some
  flexibility.

- vtable: find and records the impls to use for each trait bound that
  appears on a type parameter.

- writeback: writes the final types within a function body, replacing
  type variables with their final inferred types.  These final types
  are written into the `tcx.node_types` table, which should *never* contain
  any reference to a type variable.

## Intermediate types

While type checking a function, the intermediate types for the
expressions, blocks, and so forth contained within the function are
stored in `fcx.node_types` and `fcx.item_substs`.  These types
may contain unresolved type variables.  After type checking is
complete, the functions in the writeback module are used to take the
types from this table, resolve them, and then write them into their
permanent home in the type context `ccx.tcx`.

This means that during inferencing you should use `fcx.write_ty()`
and `fcx.expr_ty()` / `fcx.node_ty()` to write/obtain the types of
nodes within the function.

The types of top-level items, which never contain unbound type
variables, are stored directly into the `tcx` tables.

n.b.: A type variable is not the same thing as a type parameter.  A
type variable is rather an "instance" of a type parameter: that is,
given a generic function `fn foo<T>(t: T)`: while checking the
function `foo`, the type `ty_param(0)` refers to the type `T`, which
is treated in abstract.  When `foo()` is called, however, `T` will be
substituted for a fresh type variable `N`.  This variable will
eventually be resolved to some concrete type (which might itself be
type parameter).

*/

pub use self::Expectation::*;
pub use self::compare_method::{compare_impl_method, compare_const_impl};
use self::TupleArgumentsFlag::*;

use astconv::{AstConv, ast_region_to_region, PathParamMode};
use dep_graph::DepNode;
use fmt_macros::{Parser, Piece, Position};
use middle::cstore::LOCAL_CRATE;
use hir::def::{Def, PathResolution};
use hir::def_id::DefId;
use hir::pat_util;
use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable};
use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace};
use rustc::traits::{self, ProjectionMode};
use rustc::ty::{GenericPredicates, TypeScheme};
use rustc::ty::{ParamTy, ParameterEnvironment};
use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, Visibility};
use rustc::ty::{MethodCall, MethodCallee};
use rustc::ty::adjustment;
use rustc::ty::fold::TypeFoldable;
use rustc::ty::util::{Representability, IntTypeExt};
use require_c_abi_if_variadic;
use rscope::{ElisionFailureInfo, RegionScope};
use session::{Session, CompileResult};
use CrateCtxt;
use TypeAndSubsts;
use lint;
use util::common::{block_query, ErrorReported, indenter, loop_query};
use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};

use std::cell::{Cell, Ref, RefCell};
use std::collections::{HashSet};
use std::mem::replace;
use std::ops::Deref;
use syntax::abi::Abi;
use syntax::ast;
use syntax::attr;
use syntax::attr::AttrMetaMethods;
use syntax::codemap::{self, Spanned};
use syntax::parse::token::{self, InternedString, keywords};
use syntax::ptr::P;
use syntax::util::lev_distance::find_best_match_for_name;
use syntax_pos::{self, Span};
use errors::DiagnosticBuilder;

use rustc::hir::intravisit::{self, Visitor};
use rustc::hir::{self, PatKind};
use rustc::hir::print as pprust;
use rustc_back::slice;
use rustc_const_eval::eval_length;

mod assoc;
mod autoderef;
pub mod dropck;
pub mod _match;
pub mod writeback;
pub mod regionck;
pub mod coercion;
pub mod demand;
pub mod method;
mod upvar;
mod wfcheck;
mod cast;
mod closure;
mod callee;
mod compare_method;
mod intrinsic;
mod op;

/// closures defined within the function.  For example:
///
///     fn foo() {
///         bar(move|| { ... })
///     }
///
/// Here, the function `foo()` and the closure passed to
/// `bar()` will each have their own `FnCtxt`, but they will
/// share the inherited fields.
pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
    ccx: &'a CrateCtxt<'a, 'gcx>,
    infcx: InferCtxt<'a, 'gcx, 'tcx>,
    locals: RefCell<NodeMap<Ty<'tcx>>>,

    fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,

    // When we process a call like `c()` where `c` is a closure type,
    // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
    // `FnOnce` closure. In that case, we defer full resolution of the
    // call until upvar inference can kick in and make the
    // decision. We keep these deferred resolutions grouped by the
    // def-id of the closure, so that once we decide, we can easily go
    // back and process them.
    deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'gcx, 'tcx>>>>,

    deferred_cast_checks: RefCell<Vec<cast::CastCheck<'tcx>>>,
}

impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> {
    type Target = InferCtxt<'a, 'gcx, 'tcx>;
    fn deref(&self) -> &Self::Target {
        &self.infcx
    }
}

trait DeferredCallResolution<'gcx, 'tcx> {
    fn resolve<'a>(&mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>);
}

type DeferredCallResolutionHandler<'gcx, 'tcx> = Box<DeferredCallResolution<'gcx, 'tcx>+'tcx>;

/// When type-checking an expression, we propagate downward
/// whatever type hint we are able in the form of an `Expectation`.
#[derive(Copy, Clone, Debug)]
pub enum Expectation<'tcx> {
    /// We know nothing about what type this expression should have.
    NoExpectation,

    /// This expression should have the type given (or some subtype)
    ExpectHasType(Ty<'tcx>),

    /// This expression will be cast to the `Ty`
    ExpectCastableToType(Ty<'tcx>),

    /// This rvalue expression will be wrapped in `&` or `Box` and coerced
    /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
    ExpectRvalueLikeUnsized(Ty<'tcx>),
}

impl<'a, 'gcx, 'tcx> Expectation<'tcx> {
    // Disregard "castable to" expectations because they
    // can lead us astray. Consider for example `if cond
    // {22} else {c} as u8` -- if we propagate the
    // "castable to u8" constraint to 22, it will pick the
    // type 22u8, which is overly constrained (c might not
    // be a u8). In effect, the problem is that the
    // "castable to" expectation is not the tightest thing
    // we can say, so we want to drop it in this case.
    // The tightest thing we can say is "must unify with
    // else branch". Note that in the case of a "has type"
    // constraint, this limitation does not hold.

    // If the expected type is just a type variable, then don't use
    // an expected type. Otherwise, we might write parts of the type
    // when checking the 'then' block which are incompatible with the
    // 'else' branch.
    fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Expectation<'tcx> {
        match *self {
            ExpectHasType(ety) => {
                let ety = fcx.shallow_resolve(ety);
                if !ety.is_ty_var() {
                    ExpectHasType(ety)
                } else {
                    NoExpectation
                }
            }
            ExpectRvalueLikeUnsized(ety) => {
                ExpectRvalueLikeUnsized(ety)
            }
            _ => NoExpectation
        }
    }

    /// Provide an expectation for an rvalue expression given an *optional*
    /// hint, which is not required for type safety (the resulting type might
    /// be checked higher up, as is the case with `&expr` and `box expr`), but
    /// is useful in determining the concrete type.
    ///
    /// The primary use case is where the expected type is a fat pointer,
    /// like `&[isize]`. For example, consider the following statement:
    ///
    ///    let x: &[isize] = &[1, 2, 3];
    ///
    /// In this case, the expected type for the `&[1, 2, 3]` expression is
    /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the
    /// expectation `ExpectHasType([isize])`, that would be too strong --
    /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`.
    /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
    /// to the type `&[isize]`. Therefore, we propagate this more limited hint,
    /// which still is useful, because it informs integer literals and the like.
    /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
    /// for examples of where this comes up,.
    fn rvalue_hint(fcx: &FnCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
        match fcx.tcx.struct_tail(ty).sty {
            ty::TySlice(_) | ty::TyStr | ty::TyTrait(..) => {
                ExpectRvalueLikeUnsized(ty)
            }
            _ => ExpectHasType(ty)
        }
    }

    // Resolves `expected` by a single level if it is a variable. If
    // there is no expected type or resolution is not possible (e.g.,
    // no constraints yet present), just returns `None`.
    fn resolve(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Expectation<'tcx> {
        match self {
            NoExpectation => {
                NoExpectation
            }
            ExpectCastableToType(t) => {
                ExpectCastableToType(fcx.resolve_type_vars_if_possible(&t))
            }
            ExpectHasType(t) => {
                ExpectHasType(fcx.resolve_type_vars_if_possible(&t))
            }
            ExpectRvalueLikeUnsized(t) => {
                ExpectRvalueLikeUnsized(fcx.resolve_type_vars_if_possible(&t))
            }
        }
    }

    fn to_option(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>> {
        match self.resolve(fcx) {
            NoExpectation => None,
            ExpectCastableToType(ty) |
            ExpectHasType(ty) |
            ExpectRvalueLikeUnsized(ty) => Some(ty),
        }
    }

    fn only_has_type(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>> {
        match self.resolve(fcx) {
            ExpectHasType(ty) => Some(ty),
            _ => None
        }
    }
}

#[derive(Copy, Clone)]
pub struct UnsafetyState {
    pub def: ast::NodeId,
    pub unsafety: hir::Unsafety,
    pub unsafe_push_count: u32,
    from_fn: bool
}

impl UnsafetyState {
    pub fn function(unsafety: hir::Unsafety, def: ast::NodeId) -> UnsafetyState {
        UnsafetyState { def: def, unsafety: unsafety, unsafe_push_count: 0, from_fn: true }
    }

    pub fn recurse(&mut self, blk: &hir::Block) -> UnsafetyState {
        match self.unsafety {
            // If this unsafe, then if the outer function was already marked as
            // unsafe we shouldn't attribute the unsafe'ness to the block. This
            // way the block can be warned about instead of ignoring this
            // extraneous block (functions are never warned about).
            hir::Unsafety::Unsafe if self.from_fn => *self,

            unsafety => {
                let (unsafety, def, count) = match blk.rules {
                    hir::PushUnsafeBlock(..) =>
                        (unsafety, blk.id, self.unsafe_push_count.checked_add(1).unwrap()),
                    hir::PopUnsafeBlock(..) =>
                        (unsafety, blk.id, self.unsafe_push_count.checked_sub(1).unwrap()),
                    hir::UnsafeBlock(..) =>
                        (hir::Unsafety::Unsafe, blk.id, self.unsafe_push_count),
                    hir::DefaultBlock | hir::PushUnstableBlock | hir:: PopUnstableBlock =>
                        (unsafety, self.def, self.unsafe_push_count),
                };
                UnsafetyState{ def: def,
                               unsafety: unsafety,
                               unsafe_push_count: count,
                               from_fn: false }
            }
        }
    }
}

#[derive(Clone)]
pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
    ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,

    body_id: ast::NodeId,

    // This flag is set to true if, during the writeback phase, we encounter
    // a type error in this function.
    writeback_errors: Cell<bool>,

    // Number of errors that had been reported when we started
    // checking this function. On exit, if we find that *more* errors
    // have been reported, we will skip regionck and other work that
    // expects the types within the function to be consistent.
    err_count_on_creation: usize,

    ret_ty: ty::FnOutput<'tcx>,

    ps: RefCell<UnsafetyState>,

    inh: &'a Inherited<'a, 'gcx, 'tcx>,
}

impl<'a, 'gcx, 'tcx> Deref for FnCtxt<'a, 'gcx, 'tcx> {
    type Target = Inherited<'a, 'gcx, 'tcx>;
    fn deref(&self) -> &Self::Target {
        &self.inh
    }
}

/// Helper type of a temporary returned by ccx.inherited(...).
/// Necessary because we can't write the following bound:
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Inherited<'b, 'gcx, 'tcx>).
pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
    ccx: &'a CrateCtxt<'a, 'gcx>,
    infcx: infer::InferCtxtBuilder<'a, 'gcx, 'tcx>
}

impl<'a, 'gcx, 'tcx> CrateCtxt<'a, 'gcx> {
    pub fn inherited(&'a self, param_env: Option<ty::ParameterEnvironment<'gcx>>)
                     -> InheritedBuilder<'a, 'gcx, 'tcx> {
        InheritedBuilder {
            ccx: self,
            infcx: self.tcx.infer_ctxt(Some(ty::Tables::empty()),
                                       param_env,
                                       ProjectionMode::AnyFinal)
        }
    }
}

impl<'a, 'gcx, 'tcx> InheritedBuilder<'a, 'gcx, 'tcx> {
    fn enter<F, R>(&'tcx mut self, f: F) -> R
        where F: for<'b> FnOnce(Inherited<'b, 'gcx, 'tcx>) -> R
    {
        let ccx = self.ccx;
        self.infcx.enter(|infcx| {
            f(Inherited {
                ccx: ccx,
                infcx: infcx,
                fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
                locals: RefCell::new(NodeMap()),
                deferred_call_resolutions: RefCell::new(DefIdMap()),
                deferred_cast_checks: RefCell::new(Vec::new()),
            })
        })
    }
}

impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
    fn normalize_associated_types_in<T>(&self,
                                        span: Span,
                                        body_id: ast::NodeId,
                                        value: &T)
                                        -> T
        where T : TypeFoldable<'tcx>
    {
        assoc::normalize_associated_types_in(self,
                                             &mut self.fulfillment_cx.borrow_mut(),
                                             span,
                                             body_id,
                                             value)
    }

}

struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
struct CheckItemBodiesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }

impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
    fn visit_item(&mut self, i: &'tcx hir::Item) {
        check_item_type(self.ccx, i);
        intravisit::walk_item(self, i);
    }

    fn visit_ty(&mut self, t: &'tcx hir::Ty) {
        match t.node {
            hir::TyFixedLengthVec(_, ref expr) => {
                check_const_in_type(self.ccx, &expr, self.ccx.tcx.types.usize);
            }
            _ => {}
        }

        intravisit::walk_ty(self, t);
    }
}

impl<'a, 'tcx> Visitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
    fn visit_item(&mut self, i: &'tcx hir::Item) {
        check_item_body(self.ccx, i);
    }
}

pub fn check_wf_new(ccx: &CrateCtxt) -> CompileResult {
    ccx.tcx.sess.track_errors(|| {
        let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(ccx);
        ccx.tcx.visit_all_items_in_krate(DepNode::WfCheck, &mut visit);
    })
}

pub fn check_item_types(ccx: &CrateCtxt) -> CompileResult {
    ccx.tcx.sess.track_errors(|| {
        let mut visit = CheckItemTypesVisitor { ccx: ccx };
        ccx.tcx.visit_all_items_in_krate(DepNode::TypeckItemType, &mut visit);
    })
}

pub fn check_item_bodies(ccx: &CrateCtxt) -> CompileResult {
    ccx.tcx.sess.track_errors(|| {
        let mut visit = CheckItemBodiesVisitor { ccx: ccx };
        ccx.tcx.visit_all_items_in_krate(DepNode::TypeckItemBody, &mut visit);
    })
}

pub fn check_drop_impls(ccx: &CrateCtxt) -> CompileResult {
    ccx.tcx.sess.track_errors(|| {
        let _task = ccx.tcx.dep_graph.in_task(DepNode::Dropck);
        let drop_trait = match ccx.tcx.lang_items.drop_trait() {
            Some(id) => ccx.tcx.lookup_trait_def(id), None => { return }
        };
        drop_trait.for_each_impl(ccx.tcx, |drop_impl_did| {
            let _task = ccx.tcx.dep_graph.in_task(DepNode::DropckImpl(drop_impl_did));
            if drop_impl_did.is_local() {
                match dropck::check_drop_impl(ccx, drop_impl_did) {
                    Ok(()) => {}
                    Err(()) => {
                        assert!(ccx.tcx.sess.has_errors());
                    }
                }
            }
        });
    })
}

fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                           decl: &'tcx hir::FnDecl,
                           body: &'tcx hir::Block,
                           fn_id: ast::NodeId,
                           fn_span: Span,
                           raw_fty: Ty<'tcx>,
                           param_env: ty::ParameterEnvironment<'tcx>)
{
    let fn_ty = match raw_fty.sty {
        ty::TyFnDef(_, _, f) => f,
        _ => span_bug!(body.span, "check_bare_fn: function type expected")
    };

    ccx.inherited(Some(param_env)).enter(|inh| {
        // Compute the fty from point of view of inside fn.
        let fn_scope = inh.tcx.region_maps.call_site_extent(fn_id, body.id);
        let fn_sig =
            fn_ty.sig.subst(inh.tcx, &inh.parameter_environment.free_substs);
        let fn_sig =
            inh.tcx.liberate_late_bound_regions(fn_scope, &fn_sig);
        let fn_sig =
            inh.normalize_associated_types_in(body.span, body.id, &fn_sig);

        let fcx = check_fn(&inh, fn_ty.unsafety, fn_id, &fn_sig, decl, fn_id, body);

        fcx.select_all_obligations_and_apply_defaults();
        fcx.closure_analyze_fn(body);
        fcx.select_obligations_where_possible();
        fcx.check_casts();
        fcx.select_all_obligations_or_error(); // Casts can introduce new obligations.

        fcx.regionck_fn(fn_id, fn_span, decl, body);
        fcx.resolve_type_vars_in_fn(decl, body);
    });
}

struct GatherLocalsVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
    fcx: &'a FnCtxt<'a, 'gcx, 'tcx>
}

impl<'a, 'gcx, 'tcx> GatherLocalsVisitor<'a, 'gcx, 'tcx> {
    fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
        match ty_opt {
            None => {
                // infer the variable's type
                let var_ty = self.fcx.next_ty_var();
                self.fcx.locals.borrow_mut().insert(nid, var_ty);
                var_ty
            }
            Some(typ) => {
                // take type that the user specified
                self.fcx.locals.borrow_mut().insert(nid, typ);
                typ
            }
        }
    }
}

impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
    // Add explicitly-declared locals.
    fn visit_local(&mut self, local: &'gcx hir::Local) {
        let o_ty = match local.ty {
            Some(ref ty) => Some(self.fcx.to_ty(&ty)),
            None => None
        };
        self.assign(local.span, local.id, o_ty);
        debug!("Local variable {:?} is assigned type {}",
               local.pat,
               self.fcx.ty_to_string(
                   self.fcx.locals.borrow().get(&local.id).unwrap().clone()));
        intravisit::walk_local(self, local);
    }

    // Add pattern bindings.
    fn visit_pat(&mut self, p: &'gcx hir::Pat) {
        if let PatKind::Binding(_, ref path1, _) = p.node {
            let var_ty = self.assign(p.span, p.id, None);

            self.fcx.require_type_is_sized(var_ty, p.span,
                                           traits::VariableType(p.id));

            debug!("Pattern binding {} is assigned to {} with type {:?}",
                   path1.node,
                   self.fcx.ty_to_string(
                       self.fcx.locals.borrow().get(&p.id).unwrap().clone()),
                   var_ty);
        }
        intravisit::walk_pat(self, p);
    }

    fn visit_block(&mut self, b: &'gcx hir::Block) {
        // non-obvious: the `blk` variable maps to region lb, so
        // we have to keep this up-to-date.  This
        // is... unfortunate.  It'd be nice to not need this.
        intravisit::walk_block(self, b);
    }

    // Since an expr occurs as part of the type fixed size arrays we
    // need to record the type for that node
    fn visit_ty(&mut self, t: &'gcx hir::Ty) {
        match t.node {
            hir::TyFixedLengthVec(ref ty, ref count_expr) => {
                self.visit_ty(&ty);
                self.fcx.check_expr_with_hint(&count_expr, self.fcx.tcx.types.usize);
            }
            hir::TyBareFn(ref function_declaration) => {
                intravisit::walk_fn_decl_nopat(self, &function_declaration.decl);
                walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes);
            }
            _ => intravisit::walk_ty(self, t)
        }
    }

    // Don't descend into the bodies of nested closures
    fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl,
                _: &'gcx hir::Block, _: Span, _: ast::NodeId) { }
}

/// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
/// body and returns the function context used for that purpose, since in the case of a fn item
/// there is still a bit more to do.
///
/// * ...
/// * inherited: other fields inherited from the enclosing fn (if any)
fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
                            unsafety: hir::Unsafety,
                            unsafety_id: ast::NodeId,
                            fn_sig: &ty::FnSig<'tcx>,
                            decl: &'gcx hir::FnDecl,
                            fn_id: ast::NodeId,
                            body: &'gcx hir::Block)
                            -> FnCtxt<'a, 'gcx, 'tcx>
{
    let arg_tys = &fn_sig.inputs;
    let ret_ty = fn_sig.output;

    debug!("check_fn(arg_tys={:?}, ret_ty={:?}, fn_id={})",
           arg_tys,
           ret_ty,
           fn_id);

    // Create the function context.  This is either derived from scratch or,
    // in the case of function expressions, based on the outer context.
    let fcx = FnCtxt::new(inherited, ret_ty, body.id);
    *fcx.ps.borrow_mut() = UnsafetyState::function(unsafety, unsafety_id);

    if let ty::FnConverging(ret_ty) = ret_ty {
        fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
    }

    debug!("fn-sig-map: fn_id={} fn_sig={:?}", fn_id, fn_sig);

    inherited.tables.borrow_mut().liberated_fn_sigs.insert(fn_id, fn_sig.clone());

    {
        let mut visit = GatherLocalsVisitor { fcx: &fcx, };

        // Add formal parameters.
        for (arg_ty, input) in arg_tys.iter().zip(&decl.inputs) {
            // The type of the argument must be well-formed.
            //
            // NB -- this is now checked in wfcheck, but that
            // currently only results in warnings, so we issue an
            // old-style WF obligation here so that we still get the
            // errors that we used to get.
            fcx.register_old_wf_obligation(arg_ty, input.ty.span, traits::MiscObligation);

            // Create type variables for each argument.
            pat_util::pat_bindings(&input.pat, |_bm, pat_id, sp, _path| {
                let var_ty = visit.assign(sp, pat_id, None);
                fcx.require_type_is_sized(var_ty, sp, traits::VariableType(pat_id));
            });

            // Check the pattern.
            fcx.check_pat(&input.pat, *arg_ty);
        }

        visit.visit_block(body);
    }

    fcx.check_block_with_expected(body, match ret_ty {
        ty::FnConverging(result_type) => ExpectHasType(result_type),
        ty::FnDiverging => NoExpectation
    });

    for (input, arg) in decl.inputs.iter().zip(arg_tys) {
        fcx.write_ty(input.id, arg);
    }

    fcx
}

pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
    let tcx = ccx.tcx;

    check_representable(tcx, span, id, "struct");

    if tcx.lookup_simd(ccx.tcx.map.local_def_id(id)) {
        check_simd(tcx, span, id);
    }
}

pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
    debug!("check_item_type(it.id={}, it.name={})",
           it.id,
           ccx.tcx.item_path_str(ccx.tcx.map.local_def_id(it.id)));
    let _indenter = indenter();
    match it.node {
      // Consts can play a role in type-checking, so they are included here.
      hir::ItemStatic(_, _, ref e) |
      hir::ItemConst(_, ref e) => check_const(ccx, it.span, &e, it.id),
      hir::ItemEnum(ref enum_definition, _) => {
        check_enum_variants(ccx,
                            it.span,
                            &enum_definition.variants,
                            it.id);
      }
      hir::ItemFn(..) => {} // entirely within check_item_body
      hir::ItemImpl(_, _, _, _, _, ref impl_items) => {
          debug!("ItemImpl {} with id {}", it.name, it.id);
          let impl_def_id = ccx.tcx.map.local_def_id(it.id);
          match ccx.tcx.impl_trait_ref(impl_def_id) {
              Some(impl_trait_ref) => {
                  let trait_def_id = impl_trait_ref.def_id;

                  check_impl_items_against_trait(ccx,
                                                 it.span,
                                                 impl_def_id,
                                                 &impl_trait_ref,
                                                 impl_items);
                  check_on_unimplemented(
                      ccx,
                      &ccx.tcx.lookup_trait_def(trait_def_id).generics,
                      it,
                      ccx.tcx.item_name(trait_def_id));
              }
              None => { }
          }
      }
      hir::ItemTrait(..) => {
        let def_id = ccx.tcx.map.local_def_id(it.id);
        let generics = &ccx.tcx.lookup_trait_def(def_id).generics;
        check_on_unimplemented(ccx, generics, it, it.name);
      }
      hir::ItemStruct(..) => {
        check_struct(ccx, it.id, it.span);
      }
      hir::ItemTy(_, ref generics) => {
        let pty_ty = ccx.tcx.node_id_to_type(it.id);
        check_bounds_are_used(ccx, &generics.ty_params, pty_ty);
      }
      hir::ItemForeignMod(ref m) => {
        if m.abi == Abi::RustIntrinsic {
            for item in &m.items {
                intrinsic::check_intrinsic_type(ccx, item);
            }
        } else if m.abi == Abi::PlatformIntrinsic {
            for item in &m.items {
                intrinsic::check_platform_intrinsic_type(ccx, item);
            }
        } else {
            for item in &m.items {
                let pty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(item.id));
                if !pty.generics.types.is_empty() {
                    let mut err = struct_span_err!(ccx.tcx.sess, item.span, E0044,
                        "foreign items may not have type parameters");
                    span_help!(&mut err, item.span,
                        "consider using specialization instead of \
                        type parameters");
                    err.emit();
                }

                if let hir::ForeignItemFn(ref fn_decl, _) = item.node {
                    require_c_abi_if_variadic(ccx.tcx, fn_decl, m.abi, item.span);
                }
            }
        }
      }
      _ => {/* nothing to do */ }
    }
}

pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
    debug!("check_item_body(it.id={}, it.name={})",
           it.id,
           ccx.tcx.item_path_str(ccx.tcx.map.local_def_id(it.id)));
    let _indenter = indenter();
    match it.node {
      hir::ItemFn(ref decl, _, _, _, _, ref body) => {
        let fn_pty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(it.id));
        let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
        check_bare_fn(ccx, &decl, &body, it.id, it.span, fn_pty.ty, param_env);
      }
      hir::ItemImpl(_, _, _, _, _, ref impl_items) => {
        debug!("ItemImpl {} with id {}", it.name, it.id);

        let impl_pty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(it.id));

        for impl_item in impl_items {
            match impl_item.node {
                hir::ImplItemKind::Const(_, ref expr) => {
                    check_const(ccx, impl_item.span, &expr, impl_item.id)
                }
                hir::ImplItemKind::Method(ref sig, ref body) => {
                    check_method_body(ccx, &impl_pty.generics, sig, body,
                                      impl_item.id, impl_item.span);
                }
                hir::ImplItemKind::Type(_) => {
                    // Nothing to do here.
                }
            }
        }
      }
      hir::ItemTrait(_, _, _, ref trait_items) => {
        let trait_def = ccx.tcx.lookup_trait_def(ccx.tcx.map.local_def_id(it.id));
        for trait_item in trait_items {
            match trait_item.node {
                hir::ConstTraitItem(_, Some(ref expr)) => {
                    check_const(ccx, trait_item.span, &expr, trait_item.id)
                }
                hir::MethodTraitItem(ref sig, Some(ref body)) => {
                    check_trait_fn_not_const(ccx, trait_item.span, sig.constness);

                    check_method_body(ccx, &trait_def.generics, sig, body,
                                      trait_item.id, trait_item.span);
                }
                hir::MethodTraitItem(ref sig, None) => {
                    check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
                }
                hir::ConstTraitItem(_, None) |
                hir::TypeTraitItem(..) => {
                    // Nothing to do.
                }
            }
        }
      }
      _ => {/* nothing to do */ }
    }
}

fn check_trait_fn_not_const<'a,'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                     span: Span,
                                     constness: hir::Constness)
{
    match constness {
        hir::Constness::NotConst => {
            // good
        }
        hir::Constness::Const => {
            span_err!(ccx.tcx.sess, span, E0379, "trait fns cannot be declared const");
        }
    }
}

fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                    generics: &ty::Generics,
                                    item: &hir::Item,
                                    name: ast::Name) {
    if let Some(ref attr) = item.attrs.iter().find(|a| {
        a.check_name("rustc_on_unimplemented")
    }) {
        if let Some(ref istring) = attr.value_str() {
            let parser = Parser::new(&istring);
            let types = &generics.types;
            for token in parser {
                match token {
                    Piece::String(_) => (), // Normal string, no need to check it
                    Piece::NextArgument(a) => match a.position {
                        // `{Self}` is allowed
                        Position::ArgumentNamed(s) if s == "Self" => (),
                        // So is `{A}` if A is a type parameter
                        Position::ArgumentNamed(s) => match types.iter().find(|t| {
                            t.name.as_str() == s
                        }) {
                            Some(_) => (),
                            None => {
                                span_err!(ccx.tcx.sess, attr.span, E0230,
                                                 "there is no type parameter \
                                                          {} on trait {}",
                                                           s, name);
                            }
                        },
                        // `{:1}` and `{}` are not to be used
                        Position::ArgumentIs(_) => {
                            span_err!(ccx.tcx.sess, attr.span, E0231,
                                                  "only named substitution \
                                                   parameters are allowed");
                        }
                    }
                }
            }
        } else {
            span_err!(ccx.tcx.sess, attr.span, E0232,
                                  "this attribute must have a value, \
                                   eg `#[rustc_on_unimplemented = \"foo\"]`")
        }
    }
}

/// Type checks a method body.
///
/// # Parameters
///
/// * `item_generics`: generics defined on the impl/trait that contains
///   the method
/// * `self_bound`: bound for the `Self` type parameter, if any
/// * `method`: the method definition
fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                               item_generics: &ty::Generics<'tcx>,
                               sig: &'tcx hir::MethodSig,
                               body: &'tcx hir::Block,
                               id: ast::NodeId, span: Span) {
    debug!("check_method_body(item_generics={:?}, id={})",
            item_generics, id);
    let param_env = ParameterEnvironment::for_item(ccx.tcx, id);

    let fty = ccx.tcx.node_id_to_type(id);
    debug!("check_method_body: fty={:?}", fty);

    check_bare_fn(ccx, &sig.decl, body, id, span, fty, param_env);
}

fn report_forbidden_specialization<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                             impl_item: &hir::ImplItem,
                                             parent_impl: DefId)
{
    let mut err = struct_span_err!(
        tcx.sess, impl_item.span, E0520,
        "item `{}` is provided by an `impl` that specializes \
         another, but the item in the parent `impl` is not \
         marked `default` and so it cannot be specialized.",
        impl_item.name);

    match tcx.span_of_impl(parent_impl) {
        Ok(span) => {
            err.span_note(span, "parent implementation is here:");
        }
        Err(cname) => {
            err.note(&format!("parent implementation is in crate `{}`", cname));
        }
    }

    err.emit();
}

fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                           trait_def: &ty::TraitDef<'tcx>,
                                           impl_id: DefId,
                                           impl_item: &hir::ImplItem)
{
    let ancestors = trait_def.ancestors(impl_id);

    let parent = match impl_item.node {
        hir::ImplItemKind::Const(..) => {
            ancestors.const_defs(tcx, impl_item.name).skip(1).next()
                .map(|node_item| node_item.map(|parent| parent.defaultness))
        }
        hir::ImplItemKind::Method(..) => {
            ancestors.fn_defs(tcx, impl_item.name).skip(1).next()
                .map(|node_item| node_item.map(|parent| parent.defaultness))

        }
        hir::ImplItemKind::Type(_) => {
            ancestors.type_defs(tcx, impl_item.name).skip(1).next()
                .map(|node_item| node_item.map(|parent| parent.defaultness))
        }
    };

    if let Some(parent) = parent {
        if parent.item.is_final() {
            report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
        }
    }

}

fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                            impl_span: Span,
                                            impl_id: DefId,
                                            impl_trait_ref: &ty::TraitRef<'tcx>,
                                            impl_items: &[hir::ImplItem]) {
    // If the trait reference itself is erroneous (so the compilation is going
    // to fail), skip checking the items here -- the `impl_item` table in `tcx`
    // isn't populated for such impls.
    if impl_trait_ref.references_error() { return; }

    // Locate trait definition and items
    let tcx = ccx.tcx;
    let trait_def = tcx.lookup_trait_def(impl_trait_ref.def_id);
    let trait_items = tcx.trait_items(impl_trait_ref.def_id);
    let mut overridden_associated_type = None;

    // Check existing impl methods to see if they are both present in trait
    // and compatible with trait signature
    for impl_item in impl_items {
        let ty_impl_item = ccx.tcx.impl_or_trait_item(ccx.tcx.map.local_def_id(impl_item.id));
        let ty_trait_item = trait_items.iter()
            .find(|ac| ac.name() == ty_impl_item.name());

        // Check that impl definition matches trait definition
        if let Some(ty_trait_item) = ty_trait_item {
            match impl_item.node {
                hir::ImplItemKind::Const(..) => {
                    let impl_const = match ty_impl_item {
                        ty::ConstTraitItem(ref cti) => cti,
                        _ => span_bug!(impl_item.span, "non-const impl-item for const")
                    };

                    // Find associated const definition.
                    if let &ty::ConstTraitItem(ref trait_const) = ty_trait_item {
                        compare_const_impl(ccx,
                                           &impl_const,
                                           impl_item.span,
                                           trait_const,
                                           &impl_trait_ref);
                    } else {
                        span_err!(tcx.sess, impl_item.span, E0323,
                                  "item `{}` is an associated const, \
                                  which doesn't match its trait `{:?}`",
                                  impl_const.name,
                                  impl_trait_ref)
                    }
                }
                hir::ImplItemKind::Method(ref sig, ref body) => {
                    check_trait_fn_not_const(ccx, impl_item.span, sig.constness);

                    let impl_method = match ty_impl_item {
                        ty::MethodTraitItem(ref mti) => mti,
                        _ => span_bug!(impl_item.span, "non-method impl-item for method")
                    };

                    if let &ty::MethodTraitItem(ref trait_method) = ty_trait_item {
                        compare_impl_method(ccx,
                                            &impl_method,
                                            impl_item.span,
                                            body.id,
                                            &trait_method,
                                            &impl_trait_ref);
                    } else {
                        span_err!(tcx.sess, impl_item.span, E0324,
                                  "item `{}` is an associated method, \
                                  which doesn't match its trait `{:?}`",
                                  impl_method.name,
                                  impl_trait_ref)
                    }
                }
                hir::ImplItemKind::Type(_) => {
                    let impl_type = match ty_impl_item {
                        ty::TypeTraitItem(ref tti) => tti,
                        _ => span_bug!(impl_item.span, "non-type impl-item for type")
                    };

                    if let &ty::TypeTraitItem(ref at) = ty_trait_item {
                        if let Some(_) = at.ty {
                            overridden_associated_type = Some(impl_item);
                        }
                    } else {
                        span_err!(tcx.sess, impl_item.span, E0325,
                                  "item `{}` is an associated type, \
                                  which doesn't match its trait `{:?}`",
                                  impl_type.name,
                                  impl_trait_ref)
                    }
                }
            }
        }

        check_specialization_validity(tcx, trait_def, impl_id, impl_item);
    }

    // Check for missing items from trait
    let provided_methods = tcx.provided_trait_methods(impl_trait_ref.def_id);
    let mut missing_items = Vec::new();
    let mut invalidated_items = Vec::new();
    let associated_type_overridden = overridden_associated_type.is_some();
    for trait_item in trait_items.iter() {
        let is_implemented;
        let is_provided;

        match *trait_item {
            ty::ConstTraitItem(ref associated_const) => {
                is_provided = associated_const.has_value;
                is_implemented = impl_items.iter().any(|ii| {
                    match ii.node {
                        hir::ImplItemKind::Const(..) => {
                            ii.name == associated_const.name
                        }
                        _ => false,
                    }
                });
            }
            ty::MethodTraitItem(ref trait_method) => {
                is_provided = provided_methods.iter().any(|m| m.name == trait_method.name);
                is_implemented = trait_def.ancestors(impl_id)
                    .fn_defs(tcx, trait_method.name)
                    .next()
                    .map(|node_item| !node_item.node.is_from_trait())
                    .unwrap_or(false);
            }
            ty::TypeTraitItem(ref trait_assoc_ty) => {
                is_provided = trait_assoc_ty.ty.is_some();
                is_implemented = trait_def.ancestors(impl_id)
                    .type_defs(tcx, trait_assoc_ty.name)
                    .next()
                    .map(|node_item| !node_item.node.is_from_trait())
                    .unwrap_or(false);
            }
        }

        if !is_implemented {
            if !is_provided {
                missing_items.push(trait_item.name());
            } else if associated_type_overridden {
                invalidated_items.push(trait_item.name());
            }
        }
    }

    if !missing_items.is_empty() {
        span_err!(tcx.sess, impl_span, E0046,
            "not all trait items implemented, missing: `{}`",
            missing_items.iter()
                  .map(|name| name.to_string())
                  .collect::<Vec<_>>().join("`, `"))
    }

    if !invalidated_items.is_empty() {
        let invalidator = overridden_associated_type.unwrap();
        span_err!(tcx.sess, invalidator.span, E0399,
                  "the following trait items need to be reimplemented \
                   as `{}` was overridden: `{}`",
                  invalidator.name,
                  invalidated_items.iter()
                                   .map(|name| name.to_string())
                                   .collect::<Vec<_>>().join("`, `"))
    }
}

/// Checks a constant appearing in a type. At the moment this is just the
/// length expression in a fixed-length vector, but someday it might be
/// extended to type-level numeric literals.
fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
                                expr: &'tcx hir::Expr,
                                expected_type: Ty<'tcx>) {
    ccx.inherited(None).enter(|inh| {
        let fcx = FnCtxt::new(&inh, ty::FnConverging(expected_type), expr.id);
        fcx.check_const_with_ty(expr.span, expr, expected_type);
    });
}

fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                        sp: Span,
                        e: &'tcx hir::Expr,
                        id: ast::NodeId) {
    let param_env = ParameterEnvironment::for_item(ccx.tcx, id);
    ccx.inherited(Some(param_env)).enter(|inh| {
        let rty = ccx.tcx.node_id_to_type(id);
        let fcx = FnCtxt::new(&inh, ty::FnConverging(rty), e.id);
        let declty = fcx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(id)).ty;
        fcx.require_type_is_sized(declty, e.span, traits::ConstSized);
        fcx.check_const_with_ty(sp, e, declty);
    });
}

/// Checks whether a type can be represented in memory. In particular, it
/// identifies types that contain themselves without indirection through a
/// pointer, which would mean their size is unbounded.
pub fn check_representable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                     sp: Span,
                                     item_id: ast::NodeId,
                                     _designation: &str) -> bool {
    let rty = tcx.node_id_to_type(item_id);

    // Check that it is possible to represent this type. This call identifies
    // (1) types that contain themselves and (2) types that contain a different
    // recursive type. It is only necessary to throw an error on those that
    // contain themselves. For case 2, there must be an inner type that will be
    // caught by case 1.
    match rty.is_representable(tcx, sp) {
        Representability::SelfRecursive => {
            let item_def_id = tcx.map.local_def_id(item_id);
            tcx.recursive_type_with_infinite_size_error(item_def_id).emit();
            return false
        }
        Representability::Representable | Representability::ContainsRecursive => (),
    }
    return true
}

pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, id: ast::NodeId) {
    let t = tcx.node_id_to_type(id);
    match t.sty {
        ty::TyStruct(def, substs) => {
            let fields = &def.struct_variant().fields;
            if fields.is_empty() {
                span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
                return;
            }
            let e = fields[0].ty(tcx, substs);
            if !fields.iter().all(|f| f.ty(tcx, substs) == e) {
                span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
                return;
            }
            match e.sty {
                ty::TyParam(_) => { /* struct<T>(T, T, T, T) is ok */ }
                _ if e.is_machine()  => { /* struct(u8, u8, u8, u8) is ok */ }
                _ => {
                    span_err!(tcx.sess, sp, E0077,
                              "SIMD vector element type should be machine type");
                    return;
                }
            }
        }
        _ => ()
    }
}

#[allow(trivial_numeric_casts)]
pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                    sp: Span,
                                    vs: &'tcx [hir::Variant],
                                    id: ast::NodeId) {
    let def_id = ccx.tcx.map.local_def_id(id);
    let hint = *ccx.tcx.lookup_repr_hints(def_id).get(0).unwrap_or(&attr::ReprAny);

    if hint != attr::ReprAny && vs.is_empty() {
        span_err!(ccx.tcx.sess, sp, E0084,
            "unsupported representation for zero-variant enum");
    }

    ccx.inherited(None).enter(|inh| {
        let rty = ccx.tcx.node_id_to_type(id);
        let fcx = FnCtxt::new(&inh, ty::FnConverging(rty), id);

        let repr_type_ty = ccx.tcx.enum_repr_type(Some(&hint)).to_ty(ccx.tcx);
        for v in vs {
            if let Some(ref e) = v.node.disr_expr {
                fcx.check_const_with_ty(e.span, e, repr_type_ty);
            }
        }

        let def_id = ccx.tcx.map.local_def_id(id);

        let variants = &ccx.tcx.lookup_adt_def(def_id).variants;
        let mut disr_vals: Vec<ty::Disr> = Vec::new();
        for (v, variant) in vs.iter().zip(variants.iter()) {
            let current_disr_val = variant.disr_val;

            // Check for duplicate discriminant values
            if let Some(i) = disr_vals.iter().position(|&x| x == current_disr_val) {
                let mut err = struct_span_err!(ccx.tcx.sess, v.span, E0081,
                    "discriminant value `{}` already exists", disr_vals[i]);
                let variant_i_node_id = ccx.tcx.map.as_local_node_id(variants[i].did).unwrap();
                span_note!(&mut err, ccx.tcx.map.span(variant_i_node_id),
                    "conflicting discriminant here");
                err.emit();
            }
            disr_vals.push(current_disr_val);
        }
    });

    check_representable(ccx.tcx, sp, id, "enum");
}

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

    fn ast_ty_to_ty_cache(&self) -> &RefCell<NodeMap<Ty<'tcx>>> {
        &self.ast_ty_to_ty_cache
    }

    fn get_item_type_scheme(&self, _: Span, id: DefId)
                            -> Result<ty::TypeScheme<'tcx>, ErrorReported>
    {
        Ok(self.tcx().lookup_item_type(id))
    }

    fn get_trait_def(&self, _: Span, id: DefId)
                     -> Result<&'tcx ty::TraitDef<'tcx>, ErrorReported>
    {
        Ok(self.tcx().lookup_trait_def(id))
    }

    fn ensure_super_predicates(&self, _: Span, _: DefId) -> Result<(), ErrorReported> {
        // all super predicates are ensured during collect pass
        Ok(())
    }

    fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
        Some(&self.parameter_environment.free_substs)
    }

    fn get_type_parameter_bounds(&self,
                                 _: Span,
                                 node_id: ast::NodeId)
                                 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
    {
        let def = self.tcx.type_parameter_def(node_id);
        let r = self.parameter_environment
                                  .caller_bounds
                                  .iter()
                                  .filter_map(|predicate| {
                                      match *predicate {
                                          ty::Predicate::Trait(ref data) => {
                                              if data.0.self_ty().is_param(def.space, def.index) {
                                                  Some(data.to_poly_trait_ref())
                                              } else {
                                                  None
                                              }
                                          }
                                          _ => {
                                              None
                                          }
                                      }
                                  })
                                  .collect();
        Ok(r)
    }

    fn trait_defines_associated_type_named(&self,
                                           trait_def_id: DefId,
                                           assoc_name: ast::Name)
                                           -> bool
    {
        let trait_def = self.tcx().lookup_trait_def(trait_def_id);
        trait_def.associated_type_names.contains(&assoc_name)
    }

    fn ty_infer(&self,
                ty_param_def: Option<ty::TypeParameterDef<'tcx>>,
                substs: Option<&mut subst::Substs<'tcx>>,
                space: Option<subst::ParamSpace>,
                span: Span) -> Ty<'tcx> {
        // Grab the default doing subsitution
        let default = ty_param_def.and_then(|def| {
            def.default.map(|ty| type_variable::Default {
                ty: ty.subst_spanned(self.tcx(), substs.as_ref().unwrap(), Some(span)),
                origin_span: span,
                def_id: def.default_def_id
            })
        });

        let ty_var = self.next_ty_var_with_default(default);

        // Finally we add the type variable to the substs
        match substs {
            None => ty_var,
            Some(substs) => { substs.types.push(space.unwrap(), ty_var); ty_var }
        }
    }

    fn projected_ty_from_poly_trait_ref(&self,
                                        span: Span,
                                        poly_trait_ref: ty::PolyTraitRef<'tcx>,
                                        item_name: ast::Name)
                                        -> Ty<'tcx>
    {
        let (trait_ref, _) =
            self.replace_late_bound_regions_with_fresh_var(
                span,
                infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
                &poly_trait_ref);

        self.normalize_associated_type(span, trait_ref, item_name)
    }

    fn projected_ty(&self,
                    span: Span,
                    trait_ref: ty::TraitRef<'tcx>,
                    item_name: ast::Name)
                    -> Ty<'tcx>
    {
        self.normalize_associated_type(span, trait_ref, item_name)
    }

    fn set_tainted_by_errors(&self) {
        self.infcx.set_tainted_by_errors()
    }
}

impl<'a, 'gcx, 'tcx> RegionScope for FnCtxt<'a, 'gcx, 'tcx> {
    fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
        Some(self.base_object_lifetime_default(span))
    }

    fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
        // RFC #599 specifies that object lifetime defaults take
        // precedence over other defaults. But within a fn body we
        // don't have a *default* region, rather we use inference to
        // find the *correct* region, which is strictly more general
        // (and anyway, within a fn body the right region may not even
        // be something the user can write explicitly, since it might
        // be some expression).
        self.next_region_var(infer::MiscVariable(span))
    }

    fn anon_regions(&self, span: Span, count: usize)
                    -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
        Ok((0..count).map(|_| {
            self.next_region_var(infer::MiscVariable(span))
        }).collect())
    }
}

/// Controls whether the arguments are tupled. This is used for the call
/// operator.
///
/// Tupling means that all call-side arguments are packed into a tuple and
/// passed as a single parameter. For example, if tupling is enabled, this
/// function:
///
///     fn f(x: (isize, isize))
///
/// Can be called as:
///
///     f(1, 2);
///
/// Instead of:
///
///     f((1, 2));
#[derive(Clone, Eq, PartialEq)]
enum TupleArgumentsFlag {
    DontTupleArguments,
    TupleArguments,
}

impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
    pub fn new(inh: &'a Inherited<'a, 'gcx, 'tcx>,
               rty: ty::FnOutput<'tcx>,
               body_id: ast::NodeId)
               -> FnCtxt<'a, 'gcx, 'tcx> {
        FnCtxt {
            ast_ty_to_ty_cache: RefCell::new(NodeMap()),
            body_id: body_id,
            writeback_errors: Cell::new(false),
            err_count_on_creation: inh.tcx.sess.err_count(),
            ret_ty: rty,
            ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal, 0)),
            inh: inh,
        }
    }

    pub fn param_env(&self) -> &ty::ParameterEnvironment<'tcx> {
        &self.parameter_environment
    }

    pub fn sess(&self) -> &Session {
        &self.tcx.sess
    }

    pub fn err_count_since_creation(&self) -> usize {
        self.tcx.sess.err_count() - self.err_count_on_creation
    }

    /// Resolves type variables in `ty` if possible. Unlike the infcx
    /// version (resolve_type_vars_if_possible), this version will
    /// also select obligations if it seems useful, in an effort
    /// to get more type information.
    fn resolve_type_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
        debug!("resolve_type_vars_with_obligations(ty={:?})", ty);

        // No TyInfer()? Nothing needs doing.
        if !ty.has_infer_types() {
            debug!("resolve_type_vars_with_obligations: ty={:?}", ty);
            return ty;
        }

        // If `ty` is a type variable, see whether we already know what it is.
        ty = self.resolve_type_vars_if_possible(&ty);
        if !ty.has_infer_types() {
            debug!("resolve_type_vars_with_obligations: ty={:?}", ty);
            return ty;
        }

        // If not, try resolving pending obligations as much as
        // possible. This can help substantially when there are
        // indirect dependencies that don't seem worth tracking
        // precisely.
        self.select_obligations_where_possible();
        ty = self.resolve_type_vars_if_possible(&ty);

        debug!("resolve_type_vars_with_obligations: ty={:?}", ty);
        ty
    }

    fn record_deferred_call_resolution(&self,
                                       closure_def_id: DefId,
                                       r: DeferredCallResolutionHandler<'gcx, 'tcx>) {
        let mut deferred_call_resolutions = self.deferred_call_resolutions.borrow_mut();
        deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r);
    }

    fn remove_deferred_call_resolutions(&self,
                                        closure_def_id: DefId)
                                        -> Vec<DeferredCallResolutionHandler<'gcx, 'tcx>>
    {
        let mut deferred_call_resolutions = self.deferred_call_resolutions.borrow_mut();
        deferred_call_resolutions.remove(&closure_def_id).unwrap_or(Vec::new())
    }

    pub fn tag(&self) -> String {
        let self_ptr: *const FnCtxt = self;
        format!("{:?}", self_ptr)
    }

    pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
        match self.locals.borrow().get(&nid) {
            Some(&t) => t,
            None => {
                span_err!(self.tcx.sess, span, E0513,
                          "no type for local variable {}",
                          nid);
                self.tcx.types.err
            }
        }
    }

    #[inline]
    pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
        debug!("write_ty({}, {:?}) in fcx {}",
               node_id, ty, self.tag());
        self.tables.borrow_mut().node_types.insert(node_id, ty);
    }

    pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
        if !substs.substs.is_noop() {
            debug!("write_substs({}, {:?}) in fcx {}",
                   node_id,
                   substs,
                   self.tag());

            self.tables.borrow_mut().item_substs.insert(node_id, substs);
        }
    }

    pub fn write_autoderef_adjustment(&self,
                                      node_id: ast::NodeId,
                                      derefs: usize) {
        self.write_adjustment(
            node_id,
            adjustment::AdjustDerefRef(adjustment::AutoDerefRef {
                autoderefs: derefs,
                autoref: None,
                unsize: None
            })
        );
    }

    pub fn write_adjustment(&self,
                            node_id: ast::NodeId,
                            adj: adjustment::AutoAdjustment<'tcx>) {
        debug!("write_adjustment(node_id={}, adj={:?})", node_id, adj);

        if adj.is_identity() {
            return;
        }

        self.tables.borrow_mut().adjustments.insert(node_id, adj);
    }

    /// Basically whenever we are converting from a type scheme into
    /// the fn body space, we always want to normalize associated
    /// types as well. This function combines the two.
    fn instantiate_type_scheme<T>(&self,
                                  span: Span,
                                  substs: &Substs<'tcx>,
                                  value: &T)
                                  -> T
        where T : TypeFoldable<'tcx>
    {
        let value = value.subst(self.tcx, substs);
        let result = self.normalize_associated_types_in(span, &value);
        debug!("instantiate_type_scheme(value={:?}, substs={:?}) = {:?}",
               value,
               substs,
               result);
        result
    }

    /// As `instantiate_type_scheme`, but for the bounds found in a
    /// generic type scheme.
    fn instantiate_bounds(&self,
                          span: Span,
                          substs: &Substs<'tcx>,
                          bounds: &ty::GenericPredicates<'tcx>)
                          -> ty::InstantiatedPredicates<'tcx>
    {
        ty::InstantiatedPredicates {
            predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates)
        }
    }


    fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
        where T : TypeFoldable<'tcx>
    {
        self.inh.normalize_associated_types_in(span, self.body_id, value)
    }

    fn normalize_associated_type(&self,
                                 span: Span,
                                 trait_ref: ty::TraitRef<'tcx>,
                                 item_name: ast::Name)
                                 -> Ty<'tcx>
    {
        let cause = traits::ObligationCause::new(span,
                                                 self.body_id,
                                                 traits::ObligationCauseCode::MiscObligation);
        self.fulfillment_cx
            .borrow_mut()
            .normalize_projection_type(self,
                                       ty::ProjectionTy {
                                           trait_ref: trait_ref,
                                           item_name: item_name,
                                       },
                                       cause)
    }

    /// Instantiates the type in `did` with the generics in `path` and returns
    /// it (registering the necessary trait obligations along the way).
    ///
    /// Note that this function is only intended to be used with type-paths,
    /// not with value-paths.
    pub fn instantiate_type_path(&self,
                                 did: DefId,
                                 path: &hir::Path,
                                 node_id: ast::NodeId)
                                 -> Ty<'tcx> {
        debug!("instantiate_type_path(did={:?}, path={:?})", did, path);
        let type_scheme = self.tcx.lookup_item_type(did);
        let type_predicates = self.tcx.lookup_predicates(did);
        let substs = AstConv::ast_path_substs_for_ty(self, self,
                                                     path.span,
                                                     PathParamMode::Optional,
                                                     &type_scheme.generics,
                                                     path.segments.last().unwrap());
        let substs = self.tcx.mk_substs(substs);
        debug!("instantiate_type_path: ty={:?} substs={:?}", &type_scheme.ty, substs);
        let bounds = self.instantiate_bounds(path.span, substs, &type_predicates);
        let cause = traits::ObligationCause::new(path.span, self.body_id,
                                                 traits::ItemObligation(did));
        self.add_obligations_for_parameters(cause, &bounds);

        let ty_substituted = self.instantiate_type_scheme(path.span, substs, &type_scheme.ty);
        self.write_ty(node_id, ty_substituted);
        self.write_substs(node_id, ty::ItemSubsts {
            substs: substs
        });
        ty_substituted
    }

    pub fn write_nil(&self, node_id: ast::NodeId) {
        self.write_ty(node_id, self.tcx.mk_nil());
    }
    pub fn write_error(&self, node_id: ast::NodeId) {
        self.write_ty(node_id, self.tcx.types.err);
    }

    pub fn require_type_meets(&self,
                              ty: Ty<'tcx>,
                              span: Span,
                              code: traits::ObligationCauseCode<'tcx>,
                              bound: ty::BuiltinBound)
    {
        self.register_builtin_bound(
            ty,
            bound,
            traits::ObligationCause::new(span, self.body_id, code));
    }

    pub fn require_type_is_sized(&self,
                                 ty: Ty<'tcx>,
                                 span: Span,
                                 code: traits::ObligationCauseCode<'tcx>)
    {
        self.require_type_meets(ty, span, code, ty::BoundSized);
    }

    pub fn require_expr_have_sized_type(&self,
                                        expr: &hir::Expr,
                                        code: traits::ObligationCauseCode<'tcx>)
    {
        self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
    }

    pub fn register_builtin_bound(&self,
                                  ty: Ty<'tcx>,
                                  builtin_bound: ty::BuiltinBound,
                                  cause: traits::ObligationCause<'tcx>)
    {
        self.fulfillment_cx.borrow_mut()
            .register_builtin_bound(self, ty, builtin_bound, cause);
    }

    pub fn register_predicate(&self,
                              obligation: traits::PredicateObligation<'tcx>)
    {
        debug!("register_predicate({:?})",
               obligation);
        self.fulfillment_cx
            .borrow_mut()
            .register_predicate_obligation(self, obligation);
    }

    pub fn to_ty(&self, ast_t: &hir::Ty) -> Ty<'tcx> {
        let t = AstConv::ast_ty_to_ty(self, self, ast_t);
        self.register_wf_obligation(t, ast_t.span, traits::MiscObligation);
        t
    }

    pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> {
        match self.tables.borrow().node_types.get(&ex.id) {
            Some(&t) => t,
            None => {
                bug!("no type for expr in fcx {}", self.tag());
            }
        }
    }

    /// Apply `adjustment` to the type of `expr`
    pub fn adjust_expr_ty(&self,
                          expr: &hir::Expr,
                          adjustment: Option<&adjustment::AutoAdjustment<'tcx>>)
                          -> Ty<'tcx>
    {
        let raw_ty = self.expr_ty(expr);
        let raw_ty = self.shallow_resolve(raw_ty);
        let resolve_ty = |ty: Ty<'tcx>| self.resolve_type_vars_if_possible(&ty);
        raw_ty.adjust(self.tcx, expr.span, expr.id, adjustment, |method_call| {
            self.tables.borrow().method_map.get(&method_call)
                                        .map(|method| resolve_ty(method.ty))
        })
    }

    pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
        match self.tables.borrow().node_types.get(&id) {
            Some(&t) => t,
            None if self.err_count_since_creation() != 0 => self.tcx.types.err,
            None => {
                bug!("no type for node {}: {} in fcx {}",
                     id, self.tcx.map.node_to_string(id),
                     self.tag());
            }
        }
    }

    pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
        // NOTE: @jroesch this is hack that appears to be fixed on nightly, will monitor if
        // it changes when we upgrade the snapshot compiler
        fn project_item_susbts<'a, 'tcx>(tables: &'a ty::Tables<'tcx>)
                                        -> &'a NodeMap<ty::ItemSubsts<'tcx>> {
            &tables.item_substs
        }

        Ref::map(self.tables.borrow(), project_item_susbts)
    }

    pub fn opt_node_ty_substs<F>(&self,
                                 id: ast::NodeId,
                                 f: F) where
        F: FnOnce(&ty::ItemSubsts<'tcx>),
    {
        match self.tables.borrow().item_substs.get(&id) {
            Some(s) => { f(s) }
            None => { }
        }
    }

    /// Registers an obligation for checking later, during regionck, that the type `ty` must
    /// outlive the region `r`.
    pub fn register_region_obligation(&self,
                                      ty: Ty<'tcx>,
                                      region: ty::Region,
                                      cause: traits::ObligationCause<'tcx>)
    {
        let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
        fulfillment_cx.register_region_obligation(ty, region, cause);
    }

    /// Registers an obligation for checking later, during regionck, that the type `ty` must
    /// outlive the region `r`.
    pub fn register_wf_obligation(&self,
                                  ty: Ty<'tcx>,
                                  span: Span,
                                  code: traits::ObligationCauseCode<'tcx>)
    {
        // WF obligations never themselves fail, so no real need to give a detailed cause:
        let cause = traits::ObligationCause::new(span, self.body_id, code);
        self.register_predicate(traits::Obligation::new(cause, ty::Predicate::WellFormed(ty)));
    }

    pub fn register_old_wf_obligation(&self,
                                      ty: Ty<'tcx>,
                                      span: Span,
                                      code: traits::ObligationCauseCode<'tcx>)
    {
        // Registers an "old-style" WF obligation that uses the
        // implicator code.  This is basically a buggy version of
        // `register_wf_obligation` that is being kept around
        // temporarily just to help with phasing in the newer rules.
        //
        // FIXME(#27579) all uses of this should be migrated to register_wf_obligation eventually
        let cause = traits::ObligationCause::new(span, self.body_id, code);
        self.register_region_obligation(ty, ty::ReEmpty, cause);
    }

    /// Registers obligations that all types appearing in `substs` are well-formed.
    pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &hir::Expr)
    {
        for &ty in &substs.types {
            self.register_wf_obligation(ty, expr.span, traits::MiscObligation);
        }
    }

    /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
    /// type/region parameter was instantiated (`substs`), creates and registers suitable
    /// trait/region obligations.
    ///
    /// For example, if there is a function:
    ///
    /// ```
    /// fn foo<'a,T:'a>(...)
    /// ```
    ///
    /// and a reference:
    ///
    /// ```
    /// let f = foo;
    /// ```
    ///
    /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
    /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
    pub fn add_obligations_for_parameters(&self,
                                          cause: traits::ObligationCause<'tcx>,
                                          predicates: &ty::InstantiatedPredicates<'tcx>)
    {
        assert!(!predicates.has_escaping_regions());

        debug!("add_obligations_for_parameters(predicates={:?})",
               predicates);

        for obligation in traits::predicates_for_generics(cause, predicates) {
            self.register_predicate(obligation);
        }
    }

    // FIXME(arielb1): use this instead of field.ty everywhere
    // Only for fields! Returns <none> for methods>
    // Indifferent to privacy flags
    pub fn field_ty(&self,
                    span: Span,
                    field: ty::FieldDef<'tcx>,
                    substs: &Substs<'tcx>)
                    -> Ty<'tcx>
    {
        self.normalize_associated_types_in(span,
                                           &field.ty(self.tcx, substs))
    }

    fn check_casts(&self) {
        let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
        for cast in deferred_cast_checks.drain(..) {
            cast.check(self);
        }
    }

    /// Apply "fallbacks" to some types
    /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
    fn default_type_parameters(&self) {
        use rustc::ty::error::UnconstrainedNumeric::Neither;
        use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};

        // Defaulting inference variables becomes very dubious if we have
        // encountered type-checking errors. Therefore, if we think we saw
        // some errors in this function, just resolve all uninstanted type
        // varibles to TyError.
        if self.is_tainted_by_errors() {
            for ty in &self.unsolved_variables() {
                if let ty::TyInfer(_) = self.shallow_resolve(ty).sty {
                    debug!("default_type_parameters: defaulting `{:?}` to error", ty);
                    self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx().types.err);
                }
            }
            return;
        }

        for ty in &self.unsolved_variables() {
            let resolved = self.resolve_type_vars_if_possible(ty);
            if self.type_var_diverges(resolved) {
                debug!("default_type_parameters: defaulting `{:?}` to `()` because it diverges",
                       resolved);
                self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.mk_nil());
            } else {
                match self.type_is_unconstrained_numeric(resolved) {
                    UnconstrainedInt => {
                        debug!("default_type_parameters: defaulting `{:?}` to `i32`",
                               resolved);
                        self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.i32)
                    },
                    UnconstrainedFloat => {
                        debug!("default_type_parameters: defaulting `{:?}` to `f32`",
                               resolved);
                        self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.f64)
                    }
                    Neither => { }
                }
            }
        }
    }

    fn select_all_obligations_and_apply_defaults(&self) {
        if self.tcx.sess.features.borrow().default_type_parameter_fallback {
            self.new_select_all_obligations_and_apply_defaults();
        } else {
            self.old_select_all_obligations_and_apply_defaults();
        }
    }

    // Implements old type inference fallback algorithm
    fn old_select_all_obligations_and_apply_defaults(&self) {
        self.select_obligations_where_possible();
        self.default_type_parameters();
        self.select_obligations_where_possible();
    }

    fn new_select_all_obligations_and_apply_defaults(&self) {
        use rustc::ty::error::UnconstrainedNumeric::Neither;
        use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};

        // For the time being this errs on the side of being memory wasteful but provides better
        // error reporting.
        // let type_variables = self.type_variables.clone();

        // There is a possibility that this algorithm will have to run an arbitrary number of times
        // to terminate so we bound it by the compiler's recursion limit.
        for _ in 0..self.tcx.sess.recursion_limit.get() {
            // First we try to solve all obligations, it is possible that the last iteration
            // has made it possible to make more progress.
            self.select_obligations_where_possible();

            let mut conflicts = Vec::new();

            // Collect all unsolved type, integral and floating point variables.
            let unsolved_variables = self.unsolved_variables();

            // We must collect the defaults *before* we do any unification. Because we have
            // directly attached defaults to the type variables any unification that occurs
            // will erase defaults causing conflicting defaults to be completely ignored.
            let default_map: FnvHashMap<_, _> =
                unsolved_variables
                    .iter()
                    .filter_map(|t| self.default(t).map(|d| (t, d)))
                    .collect();

            let mut unbound_tyvars = HashSet::new();

            debug!("select_all_obligations_and_apply_defaults: defaults={:?}", default_map);

            // We loop over the unsolved variables, resolving them and if they are
            // and unconstrainted numeric type we add them to the set of unbound
            // variables. We do this so we only apply literal fallback to type
            // variables without defaults.
            for ty in &unsolved_variables {
                let resolved = self.resolve_type_vars_if_possible(ty);
                if self.type_var_diverges(resolved) {
                    self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.mk_nil());
                } else {
                    match self.type_is_unconstrained_numeric(resolved) {
                        UnconstrainedInt | UnconstrainedFloat => {
                            unbound_tyvars.insert(resolved);
                        },
                        Neither => {}
                    }
                }
            }

            // We now remove any numeric types that also have defaults, and instead insert
            // the type variable with a defined fallback.
            for ty in &unsolved_variables {
                if let Some(_default) = default_map.get(ty) {
                    let resolved = self.resolve_type_vars_if_possible(ty);

                    debug!("select_all_obligations_and_apply_defaults: \
                            ty: {:?} with default: {:?}",
                             ty, _default);

                    match resolved.sty {
                        ty::TyInfer(ty::TyVar(_)) => {
                            unbound_tyvars.insert(ty);
                        }

                        ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) => {
                            unbound_tyvars.insert(ty);
                            if unbound_tyvars.contains(resolved) {
                                unbound_tyvars.remove(resolved);
                            }
                        }

                        _ => {}
                    }
                }
            }

            // If there are no more fallbacks to apply at this point we have applied all possible
            // defaults and type inference will proceed as normal.
            if unbound_tyvars.is_empty() {
                break;
            }

            // Finally we go through each of the unbound type variables and unify them with
            // the proper fallback, reporting a conflicting default error if any of the
            // unifications fail. We know it must be a conflicting default because the
            // variable would only be in `unbound_tyvars` and have a concrete value if
            // it had been solved by previously applying a default.

            // We wrap this in a transaction for error reporting, if we detect a conflict
            // we will rollback the inference context to its prior state so we can probe
            // for conflicts and correctly report them.


            let _ = self.commit_if_ok(|_: &infer::CombinedSnapshot| {
                for ty in &unbound_tyvars {
                    if self.type_var_diverges(ty) {
                        self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.mk_nil());
                    } else {
                        match self.type_is_unconstrained_numeric(ty) {
                            UnconstrainedInt => {
                                self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.i32)
                            },
                            UnconstrainedFloat => {
                                self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.f64)
                            }
                            Neither => {
                                if let Some(default) = default_map.get(ty) {
                                    let default = default.clone();
                                    match self.eq_types(false,
                                            TypeOrigin::Misc(default.origin_span),
                                            ty, default.ty) {
                                        Ok(InferOk { obligations, .. }) => {
                                            // FIXME(#32730) propagate obligations
                                            assert!(obligations.is_empty())
                                        },
                                        Err(_) => {
                                            conflicts.push((*ty, default));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                // If there are conflicts we rollback, otherwise commit
                if conflicts.len() > 0 {
                    Err(())
                } else {
                    Ok(())
                }
            });

            if conflicts.len() > 0 {
                // Loop through each conflicting default, figuring out the default that caused
                // a unification failure and then report an error for each.
                for (conflict, default) in conflicts {
                    let conflicting_default =
                        self.find_conflicting_default(&unbound_tyvars, &default_map, conflict)
                            .unwrap_or(type_variable::Default {
                                ty: self.next_ty_var(),
                                origin_span: syntax_pos::DUMMY_SP,
                                def_id: self.tcx.map.local_def_id(0) // what do I put here?
                            });

                    // This is to ensure that we elimnate any non-determinism from the error
                    // reporting by fixing an order, it doesn't matter what order we choose
                    // just that it is consistent.
                    let (first_default, second_default) =
                        if default.def_id < conflicting_default.def_id {
                            (default, conflicting_default)
                        } else {
                            (conflicting_default, default)
                        };


                    self.report_conflicting_default_types(
                        first_default.origin_span,
                        first_default,
                        second_default)
                }
            }
        }

        self.select_obligations_where_possible();
    }

    // For use in error handling related to default type parameter fallback. We explicitly
    // apply the default that caused conflict first to a local version of the type variable
    // table then apply defaults until we find a conflict. That default must be the one
    // that caused conflict earlier.
    fn find_conflicting_default(&self,
                                unbound_vars: &HashSet<Ty<'tcx>>,
                                default_map: &FnvHashMap<&Ty<'tcx>, type_variable::Default<'tcx>>,
                                conflict: Ty<'tcx>)
                                -> Option<type_variable::Default<'tcx>> {
        use rustc::ty::error::UnconstrainedNumeric::Neither;
        use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};

        // Ensure that we apply the conflicting default first
        let mut unbound_tyvars = Vec::with_capacity(unbound_vars.len() + 1);
        unbound_tyvars.push(conflict);
        unbound_tyvars.extend(unbound_vars.iter());

        let mut result = None;
        // We run the same code as above applying defaults in order, this time when
        // we find the conflict we just return it for error reporting above.

        // We also run this inside snapshot that never commits so we can do error
        // reporting for more then one conflict.
        for ty in &unbound_tyvars {
            if self.type_var_diverges(ty) {
                self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.mk_nil());
            } else {
                match self.type_is_unconstrained_numeric(ty) {
                    UnconstrainedInt => {
                        self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.i32)
                    },
                    UnconstrainedFloat => {
                        self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.f64)
                    },
                    Neither => {
                        if let Some(default) = default_map.get(ty) {
                            let default = default.clone();
                            match self.eq_types(false,
                                    TypeOrigin::Misc(default.origin_span),
                                    ty, default.ty) {
                                // FIXME(#32730) propagate obligations
                                Ok(InferOk { obligations, .. }) => assert!(obligations.is_empty()),
                                Err(_) => {
                                    result = Some(default);
                                }
                            }
                        }
                    }
                }
            }
        }

        return result;
    }

    fn select_all_obligations_or_error(&self) {
        debug!("select_all_obligations_or_error");

        // upvar inference should have ensured that all deferred call
        // resolutions are handled by now.
        assert!(self.deferred_call_resolutions.borrow().is_empty());

        self.select_all_obligations_and_apply_defaults();

        let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
        match fulfillment_cx.select_all_or_error(self) {
            Ok(()) => { }
            Err(errors) => { self.report_fulfillment_errors(&errors); }
        }

        if let Err(ref errors) = fulfillment_cx.select_rfc1592_obligations(self) {
            self.report_fulfillment_errors_as_warnings(errors, self.body_id);
        }
    }

    /// Select as many obligations as we can at present.
    fn select_obligations_where_possible(&self) {
        match self.fulfillment_cx.borrow_mut().select_where_possible(self) {
            Ok(()) => { }
            Err(errors) => { self.report_fulfillment_errors(&errors); }
        }
    }

    /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait
    /// returns a type of `&T`, but the actual type we assign to the
    /// *expression* is `T`. So this function just peels off the return
    /// type by one layer to yield `T`.
    fn make_overloaded_lvalue_return_type(&self,
                                          method: MethodCallee<'tcx>)
                                          -> ty::TypeAndMut<'tcx>
    {
        // extract method return type, which will be &T;
        // all LB regions should have been instantiated during method lookup
        let ret_ty = method.ty.fn_ret();
        let ret_ty = self.tcx.no_late_bound_regions(&ret_ty).unwrap().unwrap();

        // method returns &T, but the type as visible to user is T, so deref
        ret_ty.builtin_deref(true, NoPreference).unwrap()
    }

    fn lookup_indexing(&self,
                       expr: &hir::Expr,
                       base_expr: &'gcx hir::Expr,
                       base_ty: Ty<'tcx>,
                       idx_ty: Ty<'tcx>,
                       lvalue_pref: LvaluePreference)
                       -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
    {
        // FIXME(#18741) -- this is almost but not quite the same as the
        // autoderef that normal method probing does. They could likely be
        // consolidated.

        let mut autoderef = self.autoderef(base_expr.span, base_ty);

        while let Some((adj_ty, autoderefs)) = autoderef.next() {
            if let Some(final_mt) = self.try_index_step(
                MethodCall::expr(expr.id),
                expr, base_expr, adj_ty, autoderefs,
                false, lvalue_pref, idx_ty)
            {
                autoderef.finalize(lvalue_pref, Some(base_expr));
                return Some(final_mt);
            }

            if let ty::TyArray(element_ty, _) = adj_ty.sty {
                autoderef.finalize(lvalue_pref, Some(base_expr));
                let adjusted_ty = self.tcx.mk_slice(element_ty);
                return self.try_index_step(
                    MethodCall::expr(expr.id), expr, base_expr,
                    adjusted_ty, autoderefs, true, lvalue_pref, idx_ty);
            }
        }
        autoderef.unambiguous_final_ty();
        None
    }

    /// To type-check `base_expr[index_expr]`, we progressively autoderef
    /// (and otherwise adjust) `base_expr`, looking for a type which either
    /// supports builtin indexing or overloaded indexing.
    /// This loop implements one step in that search; the autoderef loop
    /// is implemented by `lookup_indexing`.
    fn try_index_step(&self,
                      method_call: MethodCall,
                      expr: &hir::Expr,
                      base_expr: &'gcx hir::Expr,
                      adjusted_ty: Ty<'tcx>,
                      autoderefs: usize,
                      unsize: bool,
                      lvalue_pref: LvaluePreference,
                      index_ty: Ty<'tcx>)
                      -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
    {
        let tcx = self.tcx;
        debug!("try_index_step(expr={:?}, base_expr.id={:?}, adjusted_ty={:?}, \
                               autoderefs={}, unsize={}, index_ty={:?})",
               expr,
               base_expr,
               adjusted_ty,
               autoderefs,
               unsize,
               index_ty);

        let input_ty = self.next_ty_var();

        // First, try built-in indexing.
        match (adjusted_ty.builtin_index(), &index_ty.sty) {
            (Some(ty), &ty::TyUint(ast::UintTy::Us)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
                debug!("try_index_step: success, using built-in indexing");
                // If we had `[T; N]`, we should've caught it before unsizing to `[T]`.
                assert!(!unsize);
                self.write_autoderef_adjustment(base_expr.id, autoderefs);
                return Some((tcx.types.usize, ty));
            }
            _ => {}
        }

        // Try `IndexMut` first, if preferred.
        let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
            (PreferMutLvalue, Some(trait_did)) => {
                self.lookup_method_in_trait_adjusted(expr.span,
                                                     Some(&base_expr),
                                                     token::intern("index_mut"),
                                                     trait_did,
                                                     autoderefs,
                                                     unsize,
                                                     adjusted_ty,
                                                     Some(vec![input_ty]))
            }
            _ => None,
        };

        // Otherwise, fall back to `Index`.
        let method = match (method, tcx.lang_items.index_trait()) {
            (None, Some(trait_did)) => {
                self.lookup_method_in_trait_adjusted(expr.span,
                                                     Some(&base_expr),
                                                     token::intern("index"),
                                                     trait_did,
                                                     autoderefs,
                                                     unsize,
                                                     adjusted_ty,
                                                     Some(vec![input_ty]))
            }
            (method, _) => method,
        };

        // If some lookup succeeds, write callee into table and extract index/element
        // type from the method signature.
        // If some lookup succeeded, install method in table
        method.map(|method| {
            debug!("try_index_step: success, using overloaded indexing");
            self.tables.borrow_mut().method_map.insert(method_call, method);
            (input_ty, self.make_overloaded_lvalue_return_type(method).ty)
        })
    }

    fn check_method_argument_types(&self,
                                   sp: Span,
                                   method_fn_ty: Ty<'tcx>,
                                   callee_expr: &'gcx hir::Expr,
                                   args_no_rcvr: &'gcx [P<hir::Expr>],
                                   tuple_arguments: TupleArgumentsFlag,
                                   expected: Expectation<'tcx>)
                                   -> ty::FnOutput<'tcx> {
        if method_fn_ty.references_error() {
            let err_inputs = self.err_args(args_no_rcvr.len());

            let err_inputs = match tuple_arguments {
                DontTupleArguments => err_inputs,
                TupleArguments => vec![self.tcx.mk_tup(err_inputs)],
            };

            self.check_argument_types(sp, &err_inputs[..], &[], args_no_rcvr,
                                      false, tuple_arguments);
            ty::FnConverging(self.tcx.types.err)
        } else {
            match method_fn_ty.sty {
                ty::TyFnDef(_, _, ref fty) => {
                    // HACK(eddyb) ignore self in the definition (see above).
                    let expected_arg_tys = self.expected_types_for_fn_args(sp, expected,
                                                                           fty.sig.0.output,
                                                                           &fty.sig.0.inputs[1..]);
                    self.check_argument_types(sp, &fty.sig.0.inputs[1..], &expected_arg_tys[..],
                                              args_no_rcvr, fty.sig.0.variadic, tuple_arguments);
                    fty.sig.0.output
                }
                _ => {
                    span_bug!(callee_expr.span, "method without bare fn type");
                }
            }
        }
    }

    /// Generic function that factors out common logic from function calls,
    /// method calls and overloaded operators.
    fn check_argument_types(&self,
                            sp: Span,
                            fn_inputs: &[Ty<'tcx>],
                            expected_arg_tys: &[Ty<'tcx>],
                            args: &'gcx [P<hir::Expr>],
                            variadic: bool,
                            tuple_arguments: TupleArgumentsFlag) {
        let tcx = self.tcx;

        // Grab the argument types, supplying fresh type variables
        // if the wrong number of arguments were supplied
        let supplied_arg_count = if tuple_arguments == DontTupleArguments {
            args.len()
        } else {
            1
        };

        // All the input types from the fn signature must outlive the call
        // so as to validate implied bounds.
        for &fn_input_ty in fn_inputs {
            self.register_wf_obligation(fn_input_ty, sp, traits::MiscObligation);
        }

        let mut expected_arg_tys = expected_arg_tys;
        let expected_arg_count = fn_inputs.len();

        fn parameter_count_error<'tcx>(sess: &Session, sp: Span, fn_inputs: &[Ty<'tcx>],
                                       expected_count: usize, arg_count: usize, error_code: &str,
                                       variadic: bool) {
            let mut err = sess.struct_span_err_with_code(sp,
                &format!("this function takes {}{} parameter{} but {} parameter{} supplied",
                    if variadic {"at least "} else {""},
                    expected_count,
                    if expected_count == 1 {""} else {"s"},
                    arg_count,
                    if arg_count == 1 {" was"} else {"s were"}),
                error_code);
            let input_types = fn_inputs.iter().map(|i| format!("{:?}", i)).collect::<Vec<String>>();
            if input_types.len() > 0 {
                err.note(&format!("the following parameter type{} expected: {}",
                        if expected_count == 1 {" was"} else {"s were"},
                        input_types.join(", ")));
            }
            err.emit();
        }

        let formal_tys = if tuple_arguments == TupleArguments {
            let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]);
            match tuple_type.sty {
                ty::TyTuple(arg_types) if arg_types.len() != args.len() => {
                    parameter_count_error(tcx.sess, sp, fn_inputs, arg_types.len(), args.len(),
                                          "E0057", false);
                    expected_arg_tys = &[];
                    self.err_args(args.len())
                }
                ty::TyTuple(arg_types) => {
                    expected_arg_tys = match expected_arg_tys.get(0) {
                        Some(&ty) => match ty.sty {
                            ty::TyTuple(ref tys) => &tys,
                            _ => &[]
                        },
                        None => &[]
                    };
                    arg_types.to_vec()
                }
                _ => {
                    span_err!(tcx.sess, sp, E0059,
                        "cannot use call notation; the first type parameter \
                         for the function trait is neither a tuple nor unit");
                    expected_arg_tys = &[];
                    self.err_args(args.len())
                }
            }
        } else if expected_arg_count == supplied_arg_count {
            fn_inputs.to_vec()
        } else if variadic {
            if supplied_arg_count >= expected_arg_count {
                fn_inputs.to_vec()
            } else {
                parameter_count_error(tcx.sess, sp, fn_inputs, expected_arg_count,
                                      supplied_arg_count, "E0060", true);
                expected_arg_tys = &[];
                self.err_args(supplied_arg_count)
            }
        } else {
            parameter_count_error(tcx.sess, sp, fn_inputs, expected_arg_count, supplied_arg_count,
                                  "E0061", false);
            expected_arg_tys = &[];
            self.err_args(supplied_arg_count)
        };

        debug!("check_argument_types: formal_tys={:?}",
               formal_tys.iter().map(|t| self.ty_to_string(*t)).collect::<Vec<String>>());

        // Check the arguments.
        // We do this in a pretty awful way: first we typecheck any arguments
        // that are not anonymous functions, then we typecheck the anonymous
        // functions. This is so that we have more information about the types
        // of arguments when we typecheck the functions. This isn't really the
        // right way to do this.
        let xs = [false, true];
        let mut any_diverges = false; // has any of the arguments diverged?
        let mut warned = false; // have we already warned about unreachable code?
        for check_blocks in &xs {
            let check_blocks = *check_blocks;
            debug!("check_blocks={}", check_blocks);

            // More awful hacks: before we check argument types, try to do
            // an "opportunistic" vtable resolution of any trait bounds on
            // the call. This helps coercions.
            if check_blocks {
                self.select_obligations_where_possible();
            }

            // For variadic functions, we don't have a declared type for all of
            // the arguments hence we only do our usual type checking with
            // the arguments who's types we do know.
            let t = if variadic {
                expected_arg_count
            } else if tuple_arguments == TupleArguments {
                args.len()
            } else {
                supplied_arg_count
            };
            for (i, arg) in args.iter().take(t).enumerate() {
                if any_diverges && !warned {
                    self.tcx
                        .sess
                        .add_lint(lint::builtin::UNREACHABLE_CODE,
                                  arg.id,
                                  arg.span,
                                  "unreachable expression".to_string());
                    warned = true;
                }
                let is_block = match arg.node {
                    hir::ExprClosure(..) => true,
                    _ => false
                };

                if is_block == check_blocks {
                    debug!("checking the argument");
                    let formal_ty = formal_tys[i];

                    // The special-cased logic below has three functions:
                    // 1. Provide as good of an expected type as possible.
                    let expected = expected_arg_tys.get(i).map(|&ty| {
                        Expectation::rvalue_hint(self, ty)
                    });

                    self.check_expr_with_expectation(&arg,
                        expected.unwrap_or(ExpectHasType(formal_ty)));
                    // 2. Coerce to the most detailed type that could be coerced
                    //    to, which is `expected_ty` if `rvalue_hint` returns an
                    //    `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
                    let coerce_ty = expected.and_then(|e| e.only_has_type(self));
                    self.demand_coerce(&arg, coerce_ty.unwrap_or(formal_ty));

                    // 3. Relate the expected type and the formal one,
                    //    if the expected type was used for the coercion.
                    coerce_ty.map(|ty| self.demand_suptype(arg.span, formal_ty, ty));
                }

                if let Some(&arg_ty) = self.tables.borrow().node_types.get(&arg.id) {
                    any_diverges = any_diverges || self.type_var_diverges(arg_ty);
                }
            }
            if any_diverges && !warned {
                let parent = self.tcx.map.get_parent_node(args[0].id);
                self.tcx
                    .sess
                    .add_lint(lint::builtin::UNREACHABLE_CODE,
                              parent,
                              sp,
                              "unreachable call".to_string());
                warned = true;
            }

        }

        // We also need to make sure we at least write the ty of the other
        // arguments which we skipped above.
        if variadic {
            for arg in args.iter().skip(expected_arg_count) {
                self.check_expr(&arg);

                // There are a few types which get autopromoted when passed via varargs
                // in C but we just error out instead and require explicit casts.
                let arg_ty = self.structurally_resolved_type(arg.span,
                                                             self.expr_ty(&arg));
                match arg_ty.sty {
                    ty::TyFloat(ast::FloatTy::F32) => {
                        self.type_error_message(arg.span, |t| {
                            format!("can't pass an `{}` to variadic \
                                     function, cast to `c_double`", t)
                        }, arg_ty);
                    }
                    ty::TyInt(ast::IntTy::I8) | ty::TyInt(ast::IntTy::I16) | ty::TyBool => {
                        self.type_error_message(arg.span, |t| {
                            format!("can't pass `{}` to variadic \
                                     function, cast to `c_int`",
                                           t)
                        }, arg_ty);
                    }
                    ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => {
                        self.type_error_message(arg.span, |t| {
                            format!("can't pass `{}` to variadic \
                                     function, cast to `c_uint`",
                                           t)
                        }, arg_ty);
                    }
                    ty::TyFnDef(_, _, f) => {
                        let ptr_ty = self.tcx.mk_fn_ptr(f);
                        let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty);
                        self.type_error_message(arg.span,
                                                |t| {
                            format!("can't pass `{}` to variadic \
                                     function, cast to `{}`", t, ptr_ty)
                        }, arg_ty);
                    }
                    _ => {}
                }
            }
        }
    }

    fn err_args(&self, len: usize) -> Vec<Ty<'tcx>> {
        (0..len).map(|_| self.tcx.types.err).collect()
    }

    fn write_call(&self,
                  call_expr: &hir::Expr,
                  output: ty::FnOutput<'tcx>) {
        self.write_ty(call_expr.id, match output {
            ty::FnConverging(output_ty) => output_ty,
            ty::FnDiverging => self.next_diverging_ty_var()
        });
    }

    // AST fragment checking
    fn check_lit(&self,
                 lit: &ast::Lit,
                 expected: Expectation<'tcx>)
                 -> Ty<'tcx>
    {
        let tcx = self.tcx;

        match lit.node {
            ast::LitKind::Str(..) => tcx.mk_static_str(),
            ast::LitKind::ByteStr(ref v) => {
                tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic),
                                tcx.mk_array(tcx.types.u8, v.len()))
            }
            ast::LitKind::Byte(_) => tcx.types.u8,
            ast::LitKind::Char(_) => tcx.types.char,
            ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => tcx.mk_mach_int(t),
            ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => tcx.mk_mach_uint(t),
            ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => {
                let opt_ty = expected.to_option(self).and_then(|ty| {
                    match ty.sty {
                        ty::TyInt(_) | ty::TyUint(_) => Some(ty),
                        ty::TyChar => Some(tcx.types.u8),
                        ty::TyRawPtr(..) => Some(tcx.types.usize),
                        ty::TyFnDef(..) | ty::TyFnPtr(_) => Some(tcx.types.usize),
                        _ => None
                    }
                });
                opt_ty.unwrap_or_else(
                    || tcx.mk_int_var(self.next_int_var_id()))
            }
            ast::LitKind::Float(_, t) => tcx.mk_mach_float(t),
            ast::LitKind::FloatUnsuffixed(_) => {
                let opt_ty = expected.to_option(self).and_then(|ty| {
                    match ty.sty {
                        ty::TyFloat(_) => Some(ty),
                        _ => None
                    }
                });
                opt_ty.unwrap_or_else(
                    || tcx.mk_float_var(self.next_float_var_id()))
            }
            ast::LitKind::Bool(_) => tcx.types.bool
        }
    }

    fn check_expr_eq_type(&self,
                          expr: &'gcx hir::Expr,
                          expected: Ty<'tcx>) {
        self.check_expr_with_hint(expr, expected);
        self.demand_eqtype(expr.span, expected, self.expr_ty(expr));
    }

    pub fn check_expr_has_type(&self,
                               expr: &'gcx hir::Expr,
                               expected: Ty<'tcx>) {
        self.check_expr_with_hint(expr, expected);
        self.demand_suptype(expr.span, expected, self.expr_ty(expr));
    }

    fn check_expr_coercable_to_type(&self,
                                    expr: &'gcx hir::Expr,
                                    expected: Ty<'tcx>) {
        self.check_expr_with_hint(expr, expected);
        self.demand_coerce(expr, expected);
    }

    fn check_expr_with_hint(&self, expr: &'gcx hir::Expr,
                            expected: Ty<'tcx>) {
        self.check_expr_with_expectation(expr, ExpectHasType(expected))
    }

    fn check_expr_with_expectation(&self,
                                   expr: &'gcx hir::Expr,
                                   expected: Expectation<'tcx>) {
        self.check_expr_with_expectation_and_lvalue_pref(expr, expected, NoPreference)
    }

    fn check_expr(&self, expr: &'gcx hir::Expr)  {
        self.check_expr_with_expectation(expr, NoExpectation)
    }

    fn check_expr_with_lvalue_pref(&self, expr: &'gcx hir::Expr,
                                   lvalue_pref: LvaluePreference)  {
        self.check_expr_with_expectation_and_lvalue_pref(expr, NoExpectation, lvalue_pref)
    }

    // determine the `self` type, using fresh variables for all variables
    // declared on the impl declaration e.g., `impl<A,B> for Vec<(A,B)>`
    // would return ($0, $1) where $0 and $1 are freshly instantiated type
    // variables.
    pub fn impl_self_ty(&self,
                        span: Span, // (potential) receiver for this impl
                        did: DefId)
                        -> TypeAndSubsts<'tcx> {
        let tcx = self.tcx;

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

        debug!("impl_self_ty: tps={:?} rps={:?} raw_ty={:?}", tps, rps, raw_ty);

        let rps = self.region_vars_for_defs(span, rps);
        let mut substs = subst::Substs::new(
            VecPerParamSpace::empty(),
            VecPerParamSpace::new(rps, Vec::new(), Vec::new()));
        self.type_vars_for_defs(span, ParamSpace::TypeSpace, &mut substs, tps);
        let substd_ty = self.instantiate_type_scheme(span, &substs, &raw_ty);

        TypeAndSubsts { substs: substs, ty: substd_ty }
    }

    /// Unifies the return type with the expected type early, for more coercions
    /// and forward type information on the argument expressions.
    fn expected_types_for_fn_args(&self,
                                  call_span: Span,
                                  expected_ret: Expectation<'tcx>,
                                  formal_ret: ty::FnOutput<'tcx>,
                                  formal_args: &[Ty<'tcx>])
                                  -> Vec<Ty<'tcx>> {
        let expected_args = expected_ret.only_has_type(self).and_then(|ret_ty| {
            if let ty::FnConverging(formal_ret_ty) = formal_ret {
                self.commit_regions_if_ok(|| {
                    // Attempt to apply a subtyping relationship between the formal
                    // return type (likely containing type variables if the function
                    // is polymorphic) and the expected return type.
                    // No argument expectations are produced if unification fails.
                    let origin = TypeOrigin::Misc(call_span);
                    let ures = self.sub_types(false, origin, formal_ret_ty, ret_ty);
                    // FIXME(#15760) can't use try! here, FromError doesn't default
                    // to identity so the resulting type is not constrained.
                    match ures {
                        // FIXME(#32730) propagate obligations
                        Ok(InferOk { obligations, .. }) => assert!(obligations.is_empty()),
                        Err(e) => return Err(e),
                    }

                    // Record all the argument types, with the substitutions
                    // produced from the above subtyping unification.
                    Ok(formal_args.iter().map(|ty| {
                        self.resolve_type_vars_if_possible(ty)
                    }).collect())
                }).ok()
            } else {
                None
            }
        }).unwrap_or(vec![]);
        debug!("expected_types_for_fn_args(formal={:?} -> {:?}, expected={:?} -> {:?})",
               formal_args, formal_ret,
               expected_args, expected_ret);
        expected_args
    }

    // Checks a method call.
    fn check_method_call(&self,
                         expr: &'gcx hir::Expr,
                         method_name: Spanned<ast::Name>,
                         args: &'gcx [P<hir::Expr>],
                         tps: &[P<hir::Ty>],
                         expected: Expectation<'tcx>,
                         lvalue_pref: LvaluePreference) {
        let rcvr = &args[0];
        self.check_expr_with_lvalue_pref(&rcvr, lvalue_pref);

        // no need to check for bot/err -- callee does that
        let expr_t = self.structurally_resolved_type(expr.span, self.expr_ty(&rcvr));

        let tps = tps.iter().map(|ast_ty| self.to_ty(&ast_ty)).collect::<Vec<_>>();
        let fn_ty = match self.lookup_method(method_name.span,
                                             method_name.node,
                                             expr_t,
                                             tps,
                                             expr,
                                             rcvr) {
            Ok(method) => {
                let method_ty = method.ty;
                let method_call = MethodCall::expr(expr.id);
                self.tables.borrow_mut().method_map.insert(method_call, method);
                method_ty
            }
            Err(error) => {
                if method_name.node != keywords::Invalid.name() {
                    self.report_method_error(method_name.span, expr_t,
                                             method_name.node, Some(rcvr), error);
                }
                self.write_error(expr.id);
                self.tcx.types.err
            }
        };

        // Call the generic checker.
        let ret_ty = self.check_method_argument_types(method_name.span, fn_ty,
                                                      expr, &args[1..],
                                                      DontTupleArguments,
                                                      expected);

        self.write_call(expr, ret_ty);
    }

    // A generic function for checking the then and else in an if
    // or if-else.
    fn check_then_else(&self,
                       cond_expr: &'gcx hir::Expr,
                       then_blk: &'gcx hir::Block,
                       opt_else_expr: Option<&'gcx hir::Expr>,
                       id: ast::NodeId,
                       sp: Span,
                       expected: Expectation<'tcx>) {
        self.check_expr_has_type(cond_expr, self.tcx.types.bool);

        let expected = expected.adjust_for_branches(self);
        self.check_block_with_expected(then_blk, expected);
        let then_ty = self.node_ty(then_blk.id);

        let unit = self.tcx.mk_nil();
        let (origin, expected, found, result) =
        if let Some(else_expr) = opt_else_expr {
            self.check_expr_with_expectation(else_expr, expected);
            let else_ty = self.expr_ty(else_expr);
            let origin = TypeOrigin::IfExpression(sp);

            // Only try to coerce-unify if we have a then expression
            // to assign coercions to, otherwise it's () or diverging.
            let result = if let Some(ref then) = then_blk.expr {
                let res = self.try_find_coercion_lub(origin, || Some(&**then),
                                                     then_ty, else_expr);

                // In case we did perform an adjustment, we have to update
                // the type of the block, because old trans still uses it.
                let adj = self.tables.borrow().adjustments.get(&then.id).cloned();
                if res.is_ok() && adj.is_some() {
                    self.write_ty(then_blk.id, self.adjust_expr_ty(then, adj.as_ref()));
                }

                res
            } else {
                self.commit_if_ok(|_| {
                    let trace = TypeTrace::types(origin, true, then_ty, else_ty);
                    self.lub(true, trace, &then_ty, &else_ty)
                        .map(|InferOk { value, obligations }| {
                            // FIXME(#32730) propagate obligations
                            assert!(obligations.is_empty());
                            value
                        })
                })
            };
            (origin, then_ty, else_ty, result)
        } else {
            let origin = TypeOrigin::IfExpressionWithNoElse(sp);
            (origin, unit, then_ty,
             self.eq_types(true, origin, unit, then_ty)
                 .map(|InferOk { obligations, .. }| {
                     // FIXME(#32730) propagate obligations
                     assert!(obligations.is_empty());
                     unit
                 }))
        };

        let if_ty = match result {
            Ok(ty) => {
                if self.expr_ty(cond_expr).references_error() {
                    self.tcx.types.err
                } else {
                    ty
                }
            }
            Err(e) => {
                self.report_mismatched_types(origin, expected, found, e);
                self.tcx.types.err
            }
        };

        self.write_ty(id, if_ty);
    }

    // Check field access expressions
    fn check_field(&self,
                   expr: &'gcx hir::Expr,
                   lvalue_pref: LvaluePreference,
                   base: &'gcx hir::Expr,
                   field: &Spanned<ast::Name>) {
        self.check_expr_with_lvalue_pref(base, lvalue_pref);
        let expr_t = self.structurally_resolved_type(expr.span,
                                                     self.expr_ty(base));
        let mut private_candidate = None;
        let mut autoderef = self.autoderef(expr.span, expr_t);
        while let Some((base_t, autoderefs)) = autoderef.next() {
            if let ty::TyStruct(base_def, substs) = base_t.sty {
                debug!("struct named {:?}",  base_t);
                if let Some(field) = base_def.struct_variant().find_field_named(field.node) {
                    let field_ty = self.field_ty(expr.span, field, substs);
                    if field.vis.is_accessible_from(self.body_id, &self.tcx().map) {
                        autoderef.finalize(lvalue_pref, Some(base));
                        self.write_ty(expr.id, field_ty);
                        self.write_autoderef_adjustment(base.id, autoderefs);
                        return;
                    }
                    private_candidate = Some((base_def.did, field_ty));
                }
            }
        }
        autoderef.unambiguous_final_ty();

        if let Some((did, field_ty)) = private_candidate {
            let struct_path = self.tcx().item_path_str(did);
            self.write_ty(expr.id, field_ty);
            let msg = format!("field `{}` of struct `{}` is private", field.node, struct_path);
            let mut err = self.tcx().sess.struct_span_err(expr.span, &msg);
            // Also check if an accessible method exists, which is often what is meant.
            if self.method_exists(field.span, field.node, expr_t, expr.id, false) {
                err.note(&format!("a method `{}` also exists, perhaps you wish to call it",
                                  field.node));
            }
            err.emit();
        } else if field.node == keywords::Invalid.name() {
            self.write_error(expr.id);
        } else if self.method_exists(field.span, field.node, expr_t, expr.id, true) {
            self.type_error_struct(field.span, |actual| {
                format!("attempted to take value of method `{}` on type \
                         `{}`", field.node, actual)
            }, expr_t)
                .help("maybe a `()` to call it is missing? \
                       If not, try an anonymous function")
                .emit();
            self.write_error(expr.id);
        } else {
            let mut err = self.type_error_struct(expr.span, |actual| {
                format!("attempted access of field `{}` on type `{}`, \
                         but no field with that name was found",
                        field.node, actual)
            }, expr_t);
            if let ty::TyStruct(def, _) = expr_t.sty {
                Self::suggest_field_names(&mut err, def.struct_variant(), field, vec![]);
            }
            err.emit();
            self.write_error(expr.id);
        }
    }

    // displays hints about the closest matches in field names
    fn suggest_field_names(err: &mut DiagnosticBuilder,
                           variant: ty::VariantDef<'tcx>,
                           field: &Spanned<ast::Name>,
                           skip : Vec<InternedString>) {
        let name = field.node.as_str();
        let names = variant.fields.iter().filter_map(|field| {
            // ignore already set fields and private fields from non-local crates
            if skip.iter().any(|x| *x == field.name.as_str()) ||
               (variant.did.krate != LOCAL_CRATE && field.vis != Visibility::Public) {
                None
            } else {
                Some(&field.name)
            }
        });

        // only find fits with at least one matching letter
        if let Some(name) = find_best_match_for_name(names, &name, Some(name.len())) {
            err.span_help(field.span,
                          &format!("did you mean `{}`?", name));
        }
    }

    // Check tuple index expressions
    fn check_tup_field(&self,
                       expr: &'gcx hir::Expr,
                       lvalue_pref: LvaluePreference,
                       base: &'gcx hir::Expr,
                       idx: codemap::Spanned<usize>) {
        self.check_expr_with_lvalue_pref(base, lvalue_pref);
        let expr_t = self.structurally_resolved_type(expr.span,
                                                     self.expr_ty(base));
        let mut private_candidate = None;
        let mut tuple_like = false;
        let mut autoderef = self.autoderef(expr.span, expr_t);
        while let Some((base_t, autoderefs)) = autoderef.next() {
            let field = match base_t.sty {
                ty::TyStruct(base_def, substs) => {
                    tuple_like = base_def.struct_variant().kind == ty::VariantKind::Tuple;
                    if !tuple_like { continue }

                    debug!("tuple struct named {:?}",  base_t);
                    base_def.struct_variant().fields.get(idx.node).and_then(|field| {
                        let field_ty = self.field_ty(expr.span, field, substs);
                        private_candidate = Some((base_def.did, field_ty));
                        if field.vis.is_accessible_from(self.body_id, &self.tcx().map) {
                            Some(field_ty)
                        } else {
                            None
                        }
                    })
                }
                ty::TyTuple(ref v) => {
                    tuple_like = true;
                    v.get(idx.node).cloned()
                }
                _ => continue
            };

            if let Some(field_ty) = field {
                autoderef.finalize(lvalue_pref, Some(base));
                self.write_ty(expr.id, field_ty);
                self.write_autoderef_adjustment(base.id, autoderefs);
                return;
            }
        }
        autoderef.unambiguous_final_ty();

        if let Some((did, field_ty)) = private_candidate {
            let struct_path = self.tcx().item_path_str(did);
            let msg = format!("field `{}` of struct `{}` is private", idx.node, struct_path);
            self.tcx().sess.span_err(expr.span, &msg);
            self.write_ty(expr.id, field_ty);
            return;
        }

        self.type_error_message(
            expr.span,
            |actual| {
                if tuple_like {
                    format!("attempted out-of-bounds tuple index `{}` on \
                                    type `{}`",
                                   idx.node,
                                   actual)
                } else {
                    format!("attempted tuple index `{}` on type `{}`, but the \
                                     type was not a tuple or tuple struct",
                                    idx.node,
                                    actual)
                }
            },
            expr_t);

        self.write_error(expr.id);
    }

    fn report_unknown_field(&self,
                            ty: Ty<'tcx>,
                            variant: ty::VariantDef<'tcx>,
                            field: &hir::Field,
                            skip_fields: &[hir::Field]) {
        let mut err = self.type_error_struct_with_diag(
            field.name.span,
            |actual| if let ty::TyEnum(..) = ty.sty {
                struct_span_err!(self.tcx.sess, field.name.span, E0559,
                                 "struct variant `{}::{}` has no field named `{}`",
                                 actual, variant.name.as_str(), field.name.node)
            } else {
                struct_span_err!(self.tcx.sess, field.name.span, E0560,
                                 "structure `{}` has no field named `{}`",
                                 actual, field.name.node)
            },
            ty);
        // prevent all specified fields from being suggested
        let skip_fields = skip_fields.iter().map(|ref x| x.name.node.as_str());
        Self::suggest_field_names(&mut err, variant, &field.name, skip_fields.collect());
        err.emit();
    }

    fn check_expr_struct_fields(&self,
                                adt_ty: Ty<'tcx>,
                                span: Span,
                                variant: ty::VariantDef<'tcx>,
                                ast_fields: &'gcx [hir::Field],
                                check_completeness: bool) {
        let tcx = self.tcx;
        let substs = match adt_ty.sty {
            ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
            _ => span_bug!(span, "non-ADT passed to check_expr_struct_fields")
        };

        let mut remaining_fields = FnvHashMap();
        for field in &variant.fields {
            remaining_fields.insert(field.name, field);
        }

        let mut error_happened = false;

        // Typecheck each field.
        for field in ast_fields {
            let expected_field_type;

            if let Some(v_field) = remaining_fields.remove(&field.name.node) {
                expected_field_type = self.field_ty(field.span, v_field, substs);
            } else {
                error_happened = true;
                expected_field_type = tcx.types.err;
                if let Some(_) = variant.find_field_named(field.name.node) {
                    span_err!(self.tcx.sess, field.name.span, E0062,
                        "field `{}` specified more than once",
                        field.name.node);
                } else {
                    self.report_unknown_field(adt_ty, variant, field, ast_fields);
                }
            }

            // Make sure to give a type to the field even if there's
            // an error, so we can continue typechecking
            self.check_expr_coercable_to_type(&field.expr, expected_field_type);
        }

            // Make sure the programmer specified all the fields.
        if check_completeness &&
            !error_happened &&
            !remaining_fields.is_empty()
        {
            span_err!(tcx.sess, span, E0063,
                      "missing field{} {} in initializer of `{}`",
                      if remaining_fields.len() == 1 {""} else {"s"},
                      remaining_fields.keys()
                                      .map(|n| format!("`{}`", n))
                                      .collect::<Vec<_>>()
                                      .join(", "),
                      adt_ty);
        }

    }

    fn check_struct_fields_on_error(&self,
                                    id: ast::NodeId,
                                    fields: &'gcx [hir::Field],
                                    base_expr: &'gcx Option<P<hir::Expr>>) {
        // Make sure to still write the types
        // otherwise we might ICE
        self.write_error(id);
        for field in fields {
            self.check_expr(&field.expr);
        }
        match *base_expr {
            Some(ref base) => self.check_expr(&base),
            None => {}
        }
    }

    pub fn check_struct_path(&self,
                         path: &hir::Path,
                         node_id: ast::NodeId,
                         span: Span)
                         -> Option<(ty::VariantDef<'tcx>,  Ty<'tcx>)> {
        let def = self.finish_resolving_struct_path(path, node_id, span);
        let variant = match def {
            Def::Err => {
                self.set_tainted_by_errors();
                return None;
            }
            Def::Variant(..) | Def::Struct(..) => {
                Some(self.tcx.expect_variant_def(def))
            }
            Def::TyAlias(did) | Def::AssociatedTy(_, did) => {
                if let Some(&ty::TyStruct(adt, _)) = self.tcx.opt_lookup_item_type(did)
                                                             .map(|scheme| &scheme.ty.sty) {
                    Some(adt.struct_variant())
                } else {
                    None
                }
            }
            _ => None
        };
        if variant.is_none() || variant.unwrap().kind == ty::VariantKind::Tuple {
            // Reject tuple structs for now, braced and unit structs are allowed.
            span_err!(self.tcx.sess, span, E0071,
                      "`{}` does not name a struct or a struct variant",
                      pprust::path_to_string(path));
            return None;
        }

        let ty = self.instantiate_type_path(def.def_id(), path, node_id);
        Some((variant.unwrap(), ty))
    }

    fn check_expr_struct(&self,
                         expr: &hir::Expr,
                         path: &hir::Path,
                         fields: &'gcx [hir::Field],
                         base_expr: &'gcx Option<P<hir::Expr>>)
    {
        // Find the relevant variant
        let (variant, expr_ty) = if let Some(variant_ty) = self.check_struct_path(path, expr.id,
                                                                                  expr.span) {
            variant_ty
        } else {
            self.check_struct_fields_on_error(expr.id, fields, base_expr);
            return;
        };

        self.check_expr_struct_fields(expr_ty, path.span, variant, fields,
                                      base_expr.is_none());
        if let &Some(ref base_expr) = base_expr {
            self.check_expr_has_type(base_expr, expr_ty);
            match expr_ty.sty {
                ty::TyStruct(adt, substs) => {
                    self.tables.borrow_mut().fru_field_types.insert(
                        expr.id,
                        adt.struct_variant().fields.iter().map(|f| {
                            self.normalize_associated_types_in(
                                expr.span, &f.ty(self.tcx, substs)
                            )
                        }).collect()
                    );
                }
                _ => {
                    span_err!(self.tcx.sess, base_expr.span, E0436,
                              "functional record update syntax requires a struct");
                }
            }
        }
    }


    /// Invariant:
    /// If an expression has any sub-expressions that result in a type error,
    /// inspecting that expression's type with `ty.references_error()` will return
    /// true. Likewise, if an expression is known to diverge, inspecting its
    /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
    /// strict, _|_ can appear in the type of an expression that does not,
    /// itself, diverge: for example, fn() -> _|_.)
    /// Note that inspecting a type's structure *directly* may expose the fact
    /// that there are actually multiple representations for `TyError`, so avoid
    /// that when err needs to be handled differently.
    fn check_expr_with_expectation_and_lvalue_pref(&self,
                                                   expr: &'gcx hir::Expr,
                                                   expected: Expectation<'tcx>,
                                                   lvalue_pref: LvaluePreference) {
        debug!(">> typechecking: expr={:?} expected={:?}",
               expr, expected);

        let tcx = self.tcx;
        let id = expr.id;
        match expr.node {
          hir::ExprBox(ref subexpr) => {
            let expected_inner = expected.to_option(self).map_or(NoExpectation, |ty| {
                match ty.sty {
                    ty::TyBox(ty) => Expectation::rvalue_hint(self, ty),
                    _ => NoExpectation
                }
            });
            self.check_expr_with_expectation(subexpr, expected_inner);
            let referent_ty = self.expr_ty(&subexpr);
            self.write_ty(id, tcx.mk_box(referent_ty));
          }

          hir::ExprLit(ref lit) => {
            let typ = self.check_lit(&lit, expected);
            self.write_ty(id, typ);
          }
          hir::ExprBinary(op, ref lhs, ref rhs) => {
            self.check_binop(expr, op, lhs, rhs);
          }
          hir::ExprAssignOp(op, ref lhs, ref rhs) => {
            self.check_binop_assign(expr, op, lhs, rhs);
          }
          hir::ExprUnary(unop, ref oprnd) => {
            let expected_inner = match unop {
                hir::UnNot | hir::UnNeg => {
                    expected
                }
                hir::UnDeref => {
                    NoExpectation
                }
            };
            let lvalue_pref = match unop {
                hir::UnDeref => lvalue_pref,
                _ => NoPreference
            };
            self.check_expr_with_expectation_and_lvalue_pref(&oprnd,
                                                             expected_inner,
                                                             lvalue_pref);
            let mut oprnd_t = self.expr_ty(&oprnd);

            if !oprnd_t.references_error() {
                match unop {
                    hir::UnDeref => {
                        oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t);

                        if let Some(mt) = oprnd_t.builtin_deref(true, NoPreference) {
                            oprnd_t = mt.ty;
                        } else if let Some(method) = self.try_overloaded_deref(
                                expr.span, Some(&oprnd), oprnd_t, lvalue_pref) {
                            oprnd_t = self.make_overloaded_lvalue_return_type(method).ty;
                            self.tables.borrow_mut().method_map.insert(MethodCall::expr(expr.id),
                                                                           method);
                        } else {
                            self.type_error_message(expr.span, |actual| {
                                format!("type `{}` cannot be \
                                        dereferenced", actual)
                            }, oprnd_t);
                            oprnd_t = tcx.types.err;
                        }
                    }
                    hir::UnNot => {
                        oprnd_t = self.structurally_resolved_type(oprnd.span,
                                                                  oprnd_t);
                        if !(oprnd_t.is_integral() || oprnd_t.sty == ty::TyBool) {
                            oprnd_t = self.check_user_unop("!", "not",
                                                           tcx.lang_items.not_trait(),
                                                           expr, &oprnd, oprnd_t, unop);
                        }
                    }
                    hir::UnNeg => {
                        oprnd_t = self.structurally_resolved_type(oprnd.span,
                                                                  oprnd_t);
                        if !(oprnd_t.is_integral() || oprnd_t.is_fp()) {
                            oprnd_t = self.check_user_unop("-", "neg",
                                                           tcx.lang_items.neg_trait(),
                                                           expr, &oprnd, oprnd_t, unop);
                        }
                    }
                }
            }
            self.write_ty(id, oprnd_t);
          }
          hir::ExprAddrOf(mutbl, ref oprnd) => {
            let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
                match ty.sty {
                    ty::TyRef(_, ref mt) | ty::TyRawPtr(ref mt) => {
                        if self.tcx.expr_is_lval(&oprnd) {
                            // Lvalues may legitimately have unsized types.
                            // For example, dereferences of a fat pointer and
                            // the last field of a struct can be unsized.
                            ExpectHasType(mt.ty)
                        } else {
                            Expectation::rvalue_hint(self, mt.ty)
                        }
                    }
                    _ => NoExpectation
                }
            });
            let lvalue_pref = LvaluePreference::from_mutbl(mutbl);
            self.check_expr_with_expectation_and_lvalue_pref(&oprnd, hint, lvalue_pref);

            let tm = ty::TypeAndMut { ty: self.expr_ty(&oprnd), mutbl: mutbl };
            let oprnd_t = if tm.ty.references_error() {
                tcx.types.err
            } else {
                // Note: at this point, we cannot say what the best lifetime
                // is to use for resulting pointer.  We want to use the
                // shortest lifetime possible so as to avoid spurious borrowck
                // errors.  Moreover, the longest lifetime will depend on the
                // precise details of the value whose address is being taken
                // (and how long it is valid), which we don't know yet until type
                // inference is complete.
                //
                // Therefore, here we simply generate a region variable.  The
                // region inferencer will then select the ultimate value.
                // Finally, borrowck is charged with guaranteeing that the
                // value whose address was taken can actually be made to live
                // as long as it needs to live.
                let region = self.next_region_var(infer::AddrOfRegion(expr.span));
                tcx.mk_ref(tcx.mk_region(region), tm)
            };
            self.write_ty(id, oprnd_t);
          }
          hir::ExprPath(ref opt_qself, ref path) => {
              let opt_self_ty = opt_qself.as_ref().map(|qself| self.to_ty(&qself.ty));
              let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
                                                                         expr.id, expr.span);
              if def != Def::Err {
                  let (scheme, predicates) = self.type_scheme_and_predicates_for_def(expr.span,
                                                                                     def);
                  self.instantiate_value_path(segments, scheme, &predicates,
                                              opt_ty, def, expr.span, id);
              } else {
                  self.set_tainted_by_errors();
                  self.write_error(id);
              }

              // We always require that the type provided as the value for
              // a type parameter outlives the moment of instantiation.
              self.opt_node_ty_substs(expr.id, |item_substs| {
                  self.add_wf_bounds(&item_substs.substs, expr);
              });
          }
          hir::ExprInlineAsm(_, ref outputs, ref inputs) => {
              for output in outputs {
                  self.check_expr(output);
              }
              for input in inputs {
                  self.check_expr(input);
              }
              self.write_nil(id);
          }
          hir::ExprBreak(_) => { self.write_ty(id, self.next_diverging_ty_var()); }
          hir::ExprAgain(_) => { self.write_ty(id, self.next_diverging_ty_var()); }
          hir::ExprRet(ref expr_opt) => {
            match self.ret_ty {
                ty::FnConverging(result_type) => {
                    if let Some(ref e) = *expr_opt {
                        self.check_expr_coercable_to_type(&e, result_type);
                    } else {
                        let eq_result = self.eq_types(false,
                                                      TypeOrigin::Misc(expr.span),
                                                      result_type,
                                                      tcx.mk_nil())
                            // FIXME(#32730) propagate obligations
                            .map(|InferOk { obligations, .. }| assert!(obligations.is_empty()));
                        if eq_result.is_err() {
                            span_err!(tcx.sess, expr.span, E0069,
                                      "`return;` in a function whose return type is not `()`");
                        }
                    }
                }
                ty::FnDiverging => {
                    if let Some(ref e) = *expr_opt {
                        self.check_expr(&e);
                    }
                    span_err!(tcx.sess, expr.span, E0166,
                        "`return` in a function declared as diverging");
                }
            }
            self.write_ty(id, self.next_diverging_ty_var());
          }
          hir::ExprAssign(ref lhs, ref rhs) => {
            self.check_expr_with_lvalue_pref(&lhs, PreferMutLvalue);

            let tcx = self.tcx;
            if !tcx.expr_is_lval(&lhs) {
                span_err!(tcx.sess, expr.span, E0070,
                    "invalid left-hand side expression");
            }

            let lhs_ty = self.expr_ty(&lhs);
            self.check_expr_coercable_to_type(&rhs, lhs_ty);
            let rhs_ty = self.expr_ty(&rhs);

            self.require_expr_have_sized_type(&lhs, traits::AssignmentLhsSized);

            if lhs_ty.references_error() || rhs_ty.references_error() {
                self.write_error(id);
            } else {
                self.write_nil(id);
            }
          }
          hir::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
            self.check_then_else(&cond, &then_blk, opt_else_expr.as_ref().map(|e| &**e),
                                 id, expr.span, expected);
          }
          hir::ExprWhile(ref cond, ref body, _) => {
            self.check_expr_has_type(&cond, tcx.types.bool);
            self.check_block_no_value(&body);
            let cond_ty = self.expr_ty(&cond);
            let body_ty = self.node_ty(body.id);
            if cond_ty.references_error() || body_ty.references_error() {
                self.write_error(id);
            }
            else {
                self.write_nil(id);
            }
          }
          hir::ExprLoop(ref body, _) => {
            self.check_block_no_value(&body);
            if !may_break(tcx, expr.id, &body) {
                self.write_ty(id, self.next_diverging_ty_var());
            } else {
                self.write_nil(id);
            }
          }
          hir::ExprMatch(ref discrim, ref arms, match_src) => {
            self.check_match(expr, &discrim, arms, expected, match_src);
          }
          hir::ExprClosure(capture, ref decl, ref body, _) => {
              self.check_expr_closure(expr, capture, &decl, &body, expected);
          }
          hir::ExprBlock(ref b) => {
            self.check_block_with_expected(&b, expected);
            self.write_ty(id, self.node_ty(b.id));
          }
          hir::ExprCall(ref callee, ref args) => {
              self.check_call(expr, &callee, &args[..], expected);

              // we must check that return type of called functions is WF:
              let ret_ty = self.expr_ty(expr);
              self.register_wf_obligation(ret_ty, expr.span, traits::MiscObligation);
          }
          hir::ExprMethodCall(name, ref tps, ref args) => {
              self.check_method_call(expr, name, &args[..], &tps[..], expected, lvalue_pref);
              let arg_tys = args.iter().map(|a| self.expr_ty(&a));
              let args_err = arg_tys.fold(false, |rest_err, a| rest_err || a.references_error());
              if args_err {
                  self.write_error(id);
              }
          }
          hir::ExprCast(ref e, ref t) => {
            if let hir::TyFixedLengthVec(_, ref count_expr) = t.node {
                self.check_expr_with_hint(&count_expr, tcx.types.usize);
            }

            // Find the type of `e`. Supply hints based on the type we are casting to,
            // if appropriate.
            let t_cast = self.to_ty(t);
            let t_cast = self.resolve_type_vars_if_possible(&t_cast);
            self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));
            let t_expr = self.expr_ty(e);
            let t_cast = self.resolve_type_vars_if_possible(&t_cast);

            // Eagerly check for some obvious errors.
            if t_expr.references_error() || t_cast.references_error() {
                self.write_error(id);
            } else {
                // Write a type for the whole expression, assuming everything is going
                // to work out Ok.
                self.write_ty(id, t_cast);

                // Defer other checks until we're done type checking.
                let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
                match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) {
                    Ok(cast_check) => {
                        deferred_cast_checks.push(cast_check);
                    }
                    Err(ErrorReported) => {
                        self.write_error(id);
                    }
                }
            }
          }
          hir::ExprType(ref e, ref t) => {
            let typ = self.to_ty(&t);
            self.check_expr_eq_type(&e, typ);
            self.write_ty(id, typ);
          }
          hir::ExprVec(ref args) => {
            let uty = expected.to_option(self).and_then(|uty| {
                match uty.sty {
                    ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
                    _ => None
                }
            });

            let mut unified = self.next_ty_var();
            let coerce_to = uty.unwrap_or(unified);

            for (i, e) in args.iter().enumerate() {
                self.check_expr_with_hint(e, coerce_to);
                let e_ty = self.expr_ty(e);
                let origin = TypeOrigin::Misc(e.span);

                // Special-case the first element, as it has no "previous expressions".
                let result = if i == 0 {
                    self.try_coerce(e, coerce_to)
                } else {
                    let prev_elems = || args[..i].iter().map(|e| &**e);
                    self.try_find_coercion_lub(origin, prev_elems, unified, e)
                };

                match result {
                    Ok(ty) => unified = ty,
                    Err(e) => {
                        self.report_mismatched_types(origin, unified, e_ty, e);
                    }
                }
            }
            self.write_ty(id, tcx.mk_array(unified, args.len()));
          }
          hir::ExprRepeat(ref element, ref count_expr) => {
            self.check_expr_has_type(&count_expr, tcx.types.usize);
            let count = eval_length(self.tcx.global_tcx(), &count_expr, "repeat count")
                  .unwrap_or(0);

            let uty = match expected {
                ExpectHasType(uty) => {
                    match uty.sty {
                        ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
                        _ => None
                    }
                }
                _ => None
            };

            let (element_ty, t) = match uty {
                Some(uty) => {
                    self.check_expr_coercable_to_type(&element, uty);
                    (uty, uty)
                }
                None => {
                    let t: Ty = self.next_ty_var();
                    self.check_expr_has_type(&element, t);
                    (self.expr_ty(&element), t)
                }
            };

            if count > 1 {
                // For [foo, ..n] where n > 1, `foo` must have
                // Copy type:
                self.require_type_meets(t, expr.span, traits::RepeatVec, ty::BoundCopy);
            }

            if element_ty.references_error() {
                self.write_error(id);
            } else {
                let t = tcx.mk_array(t, count);
                self.write_ty(id, t);
            }
          }
          hir::ExprTup(ref elts) => {
            let flds = expected.only_has_type(self).and_then(|ty| {
                match ty.sty {
                    ty::TyTuple(ref flds) => Some(&flds[..]),
                    _ => None
                }
            });
            let mut err_field = false;

            let elt_ts = elts.iter().enumerate().map(|(i, e)| {
                let t = match flds {
                    Some(ref fs) if i < fs.len() => {
                        let ety = fs[i];
                        self.check_expr_coercable_to_type(&e, ety);
                        ety
                    }
                    _ => {
                        self.check_expr_with_expectation(&e, NoExpectation);
                        self.expr_ty(&e)
                    }
                };
                err_field = err_field || t.references_error();
                t
            }).collect();
            if err_field {
                self.write_error(id);
            } else {
                let typ = tcx.mk_tup(elt_ts);
                self.write_ty(id, typ);
            }
          }
          hir::ExprStruct(ref path, ref fields, ref base_expr) => {
            self.check_expr_struct(expr, path, fields, base_expr);

            self.require_expr_have_sized_type(expr, traits::StructInitializerSized);
          }
          hir::ExprField(ref base, ref field) => {
            self.check_field(expr, lvalue_pref, &base, field);
          }
          hir::ExprTupField(ref base, idx) => {
            self.check_tup_field(expr, lvalue_pref, &base, idx);
          }
          hir::ExprIndex(ref base, ref idx) => {
              self.check_expr_with_lvalue_pref(&base, lvalue_pref);
              self.check_expr(&idx);

              let base_t = self.expr_ty(&base);
              let idx_t = self.expr_ty(&idx);

              if base_t.references_error() {
                  self.write_ty(id, base_t);
              } else if idx_t.references_error() {
                  self.write_ty(id, idx_t);
              } else {
                  let base_t = self.structurally_resolved_type(expr.span, base_t);
                  match self.lookup_indexing(expr, base, base_t, idx_t, lvalue_pref) {
                      Some((index_ty, element_ty)) => {
                          let idx_expr_ty = self.expr_ty(idx);
                          self.demand_eqtype(expr.span, index_ty, idx_expr_ty);
                          self.write_ty(id, element_ty);
                      }
                      None => {
                          self.check_expr_has_type(&idx, self.tcx.types.err);
                          let mut err = self.type_error_struct(
                              expr.span,
                              |actual| {
                                  format!("cannot index a value of type `{}`",
                                          actual)
                              },
                              base_t);
                          // Try to give some advice about indexing tuples.
                          if let ty::TyTuple(_) = base_t.sty {
                              let mut needs_note = true;
                              // If the index is an integer, we can show the actual
                              // fixed expression:
                              if let hir::ExprLit(ref lit) = idx.node {
                                  if let ast::LitKind::Int(i,
                                            ast::LitIntType::Unsuffixed) = lit.node {
                                      let snip = tcx.sess.codemap().span_to_snippet(base.span);
                                      if let Ok(snip) = snip {
                                          err.span_suggestion(expr.span,
                                                              "to access tuple elements, \
                                                               use tuple indexing syntax \
                                                               as shown",
                                                              format!("{}.{}", snip, i));
                                          needs_note = false;
                                      }
                                  }
                              }
                              if needs_note {
                                  err.help("to access tuple elements, use tuple indexing \
                                            syntax (e.g. `tuple.0`)");
                              }
                          }
                          err.emit();
                          self.write_ty(id, self.tcx().types.err);
                      }
                  }
              }
           }
        }

        debug!("type of expr({}) {} is...", expr.id,
               pprust::expr_to_string(expr));
        debug!("... {:?}, expected is {:?}",
               self.expr_ty(expr),
               expected);
    }

    // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
    // The newly resolved definition is written into `def_map`.
    pub fn finish_resolving_struct_path(&self,
                                        path: &hir::Path,
                                        node_id: ast::NodeId,
                                        span: Span)
                                        -> Def
    {
        let path_res = self.tcx().expect_resolution(node_id);
        if path_res.depth == 0 {
            // If fully resolved already, we don't have to do anything.
            path_res.base_def
        } else {
            let base_ty_end = path.segments.len() - path_res.depth;
            let (_ty, def) = AstConv::finish_resolving_def_to_ty(self, self, span,
                                                                 PathParamMode::Optional,
                                                                 path_res.base_def,
                                                                 None,
                                                                 node_id,
                                                                 &path.segments[..base_ty_end],
                                                                 &path.segments[base_ty_end..]);
            // Write back the new resolution.
            self.tcx().def_map.borrow_mut().insert(node_id, PathResolution::new(def));
            def
        }
    }

    // Resolve associated value path into a base type and associated constant or method definition.
    // The newly resolved definition is written into `def_map`.
    pub fn resolve_ty_and_def_ufcs<'b>(&self,
                                       opt_self_ty: Option<Ty<'tcx>>,
                                       path: &'b hir::Path,
                                       node_id: ast::NodeId,
                                       span: Span)
                                       -> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment])
    {
        let path_res = self.tcx().expect_resolution(node_id);
        if path_res.depth == 0 {
            // If fully resolved already, we don't have to do anything.
            (path_res.base_def, opt_self_ty, &path.segments)
        } else {
            // Try to resolve everything except for the last segment as a type.
            let ty_segments = path.segments.split_last().unwrap().1;
            let base_ty_end = path.segments.len() - path_res.depth;
            let (ty, _def) = AstConv::finish_resolving_def_to_ty(self, self, span,
                                                                 PathParamMode::Optional,
                                                                 path_res.base_def,
                                                                 opt_self_ty,
                                                                 node_id,
                                                                 &ty_segments[..base_ty_end],
                                                                 &ty_segments[base_ty_end..]);

            // Resolve an associated constant or method on the previously resolved type.
            let item_segment = path.segments.last().unwrap();
            let item_name = item_segment.name;
            let def = match self.resolve_ufcs(span, item_name, ty, node_id) {
                Ok(def) => def,
                Err(error) => {
                    let def = match error {
                        method::MethodError::PrivateMatch(def) => def,
                        _ => Def::Err,
                    };
                    if item_name != keywords::Invalid.name() {
                        self.report_method_error(span, ty, item_name, None, error);
                    }
                    def
                }
            };

            // Write back the new resolution.
            self.tcx().def_map.borrow_mut().insert(node_id, PathResolution::new(def));
            (def, Some(ty), slice::ref_slice(item_segment))
        }
    }

    pub fn check_decl_initializer(&self,
                                  local: &'gcx hir::Local,
                                  init: &'gcx hir::Expr)
    {
        let ref_bindings = self.tcx.pat_contains_ref_binding(&local.pat);

        let local_ty = self.local_ty(init.span, local.id);
        if let Some(m) = ref_bindings {
            // Somewhat subtle: if we have a `ref` binding in the pattern,
            // we want to avoid introducing coercions for the RHS. This is
            // both because it helps preserve sanity and, in the case of
            // ref mut, for soundness (issue #23116). In particular, in
            // the latter case, we need to be clear that the type of the
            // referent for the reference that results is *equal to* the
            // type of the lvalue it is referencing, and not some
            // supertype thereof.
            self.check_expr_with_lvalue_pref(init, LvaluePreference::from_mutbl(m));
            let init_ty = self.expr_ty(init);
            self.demand_eqtype(init.span, init_ty, local_ty);
        } else {
            self.check_expr_coercable_to_type(init, local_ty)
        };
    }

    pub fn check_decl_local(&self, local: &'gcx hir::Local)  {
        let t = self.local_ty(local.span, local.id);
        self.write_ty(local.id, t);

        if let Some(ref init) = local.init {
            self.check_decl_initializer(local, &init);
            let init_ty = self.expr_ty(&init);
            if init_ty.references_error() {
                self.write_ty(local.id, init_ty);
            }
        }

        self.check_pat(&local.pat, t);
        let pat_ty = self.node_ty(local.pat.id);
        if pat_ty.references_error() {
            self.write_ty(local.id, pat_ty);
        }
    }

    pub fn check_stmt(&self, stmt: &'gcx hir::Stmt)  {
        let node_id;
        let mut saw_bot = false;
        let mut saw_err = false;
        match stmt.node {
          hir::StmtDecl(ref decl, id) => {
            node_id = id;
            match decl.node {
              hir::DeclLocal(ref l) => {
                  self.check_decl_local(&l);
                  let l_t = self.node_ty(l.id);
                  saw_bot = saw_bot || self.type_var_diverges(l_t);
                  saw_err = saw_err || l_t.references_error();
              }
              hir::DeclItem(_) => {/* ignore for now */ }
            }
          }
          hir::StmtExpr(ref expr, id) => {
            node_id = id;
            // Check with expected type of ()
            self.check_expr_has_type(&expr, self.tcx.mk_nil());
            let expr_ty = self.expr_ty(&expr);
            saw_bot = saw_bot || self.type_var_diverges(expr_ty);
            saw_err = saw_err || expr_ty.references_error();
          }
          hir::StmtSemi(ref expr, id) => {
            node_id = id;
            self.check_expr(&expr);
            let expr_ty = self.expr_ty(&expr);
            saw_bot |= self.type_var_diverges(expr_ty);
            saw_err |= expr_ty.references_error();
          }
        }
        if saw_bot {
            self.write_ty(node_id, self.next_diverging_ty_var());
        }
        else if saw_err {
            self.write_error(node_id);
        }
        else {
            self.write_nil(node_id)
        }
    }

    pub fn check_block_no_value(&self, blk: &'gcx hir::Block)  {
        self.check_block_with_expected(blk, ExpectHasType(self.tcx.mk_nil()));
        let blkty = self.node_ty(blk.id);
        if blkty.references_error() {
            self.write_error(blk.id);
        } else {
            let nilty = self.tcx.mk_nil();
            self.demand_suptype(blk.span, nilty, blkty);
        }
    }

    fn check_block_with_expected(&self,
                                 blk: &'gcx hir::Block,
                                 expected: Expectation<'tcx>) {
        let prev = {
            let mut fcx_ps = self.ps.borrow_mut();
            let unsafety_state = fcx_ps.recurse(blk);
            replace(&mut *fcx_ps, unsafety_state)
        };

        let mut warned = false;
        let mut any_diverges = false;
        let mut any_err = false;
        for s in &blk.stmts {
            self.check_stmt(s);
            let s_id = s.node.id();
            let s_ty = self.node_ty(s_id);
            if any_diverges && !warned && match s.node {
                hir::StmtDecl(ref decl, _) => {
                    match decl.node {
                        hir::DeclLocal(_) => true,
                        _ => false,
                    }
                }
                hir::StmtExpr(_, _) | hir::StmtSemi(_, _) => true,
            } {
                self.tcx
                    .sess
                    .add_lint(lint::builtin::UNREACHABLE_CODE,
                              s_id,
                              s.span,
                              "unreachable statement".to_string());
                warned = true;
            }
            any_diverges = any_diverges || self.type_var_diverges(s_ty);
            any_err = any_err || s_ty.references_error();
        }
        match blk.expr {
            None => if any_err {
                self.write_error(blk.id);
            } else if any_diverges {
                self.write_ty(blk.id, self.next_diverging_ty_var());
            } else {
                self.write_nil(blk.id);
            },
            Some(ref e) => {
                if any_diverges && !warned {
                    self.tcx
                        .sess
                        .add_lint(lint::builtin::UNREACHABLE_CODE,
                                  e.id,
                                  e.span,
                                  "unreachable expression".to_string());
                }
                let ety = match expected {
                    ExpectHasType(ety) => {
                        self.check_expr_coercable_to_type(&e, ety);
                        ety
                    }
                    _ => {
                        self.check_expr_with_expectation(&e, expected);
                        self.expr_ty(&e)
                    }
                };

                if any_err {
                    self.write_error(blk.id);
                } else if any_diverges {
                    self.write_ty(blk.id, self.next_diverging_ty_var());
                } else {
                    self.write_ty(blk.id, ety);
                }
            }
        };

        *self.ps.borrow_mut() = prev;
    }


    fn check_const_with_ty(&self,
                           _: Span,
                           e: &'gcx hir::Expr,
                           declty: Ty<'tcx>) {
        // Gather locals in statics (because of block expressions).
        // This is technically unnecessary because locals in static items are forbidden,
        // but prevents type checking from blowing up before const checking can properly
        // emit an error.
        GatherLocalsVisitor { fcx: self }.visit_expr(e);

        self.check_expr_coercable_to_type(e, declty);

        self.select_all_obligations_and_apply_defaults();
        self.closure_analyze_const(e);
        self.select_obligations_where_possible();
        self.check_casts();
        self.select_all_obligations_or_error();

        self.regionck_expr(e);
        self.resolve_type_vars_in_expr(e);
    }

    // Returns the type parameter count and the type for the given definition.
    fn type_scheme_and_predicates_for_def(&self,
                                          sp: Span,
                                          defn: Def)
                                          -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
        match defn {
            Def::Local(_, nid) | Def::Upvar(_, nid, _, _) => {
                let typ = self.local_ty(sp, nid);
                (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
                 ty::GenericPredicates::empty())
            }
            Def::Fn(id) | Def::Method(id) |
            Def::Static(id, _) | Def::Variant(_, id) |
            Def::Struct(id) | Def::Const(id) | Def::AssociatedConst(id) => {
                (self.tcx.lookup_item_type(id), self.tcx.lookup_predicates(id))
            }
            Def::Trait(_) |
            Def::Enum(..) |
            Def::TyAlias(..) |
            Def::AssociatedTy(..) |
            Def::PrimTy(_) |
            Def::TyParam(..) |
            Def::Mod(..) |
            Def::ForeignMod(..) |
            Def::Label(..) |
            Def::SelfTy(..) |
            Def::Err => {
                span_bug!(sp, "expected value, found {:?}", defn);
            }
        }
    }

    // Instantiates the given path, which must refer to an item with the given
    // number of type parameters and type.
    pub fn instantiate_value_path(&self,
                                  segments: &[hir::PathSegment],
                                  type_scheme: TypeScheme<'tcx>,
                                  type_predicates: &ty::GenericPredicates<'tcx>,
                                  opt_self_ty: Option<Ty<'tcx>>,
                                  def: Def,
                                  span: Span,
                                  node_id: ast::NodeId)
                                  -> Ty<'tcx> {
        debug!("instantiate_value_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
               segments,
               def,
               node_id,
               type_scheme);

        // We need to extract the type parameters supplied by the user in
        // the path `path`. Due to the current setup, this is a bit of a
        // tricky-process; the problem is that resolve only tells us the
        // end-point of the path resolution, and not the intermediate steps.
        // Luckily, we can (at least for now) deduce the intermediate steps
        // just from the end-point.
        //
        // There are basically four cases to consider:
        //
        // 1. Reference to a *type*, such as a struct or enum:
        //
        //        mod a { struct Foo<T> { ... } }
        //
        //    Because we don't allow types to be declared within one
        //    another, a path that leads to a type will always look like
        //    `a::b::Foo<T>` where `a` and `b` are modules. This implies
        //    that only the final segment can have type parameters, and
        //    they are located in the TypeSpace.
        //
        //    *Note:* Generally speaking, references to types don't
        //    actually pass through this function, but rather the
        //    `ast_ty_to_ty` function in `astconv`. However, in the case
        //    of struct patterns (and maybe literals) we do invoke
        //    `instantiate_value_path` to get the general type of an instance of
        //    a struct. (In these cases, there are actually no type
        //    parameters permitted at present, but perhaps we will allow
        //    them in the future.)
        //
        // 1b. Reference to an enum variant or tuple-like struct:
        //
        //        struct foo<T>(...)
        //        enum E<T> { foo(...) }
        //
        //    In these cases, the parameters are declared in the type
        //    space.
        //
        // 2. Reference to a *fn item*:
        //
        //        fn foo<T>() { }
        //
        //    In this case, the path will again always have the form
        //    `a::b::foo::<T>` where only the final segment should have
        //    type parameters. However, in this case, those parameters are
        //    declared on a value, and hence are in the `FnSpace`.
        //
        // 3. Reference to a *method*:
        //
        //        impl<A> SomeStruct<A> {
        //            fn foo<B>(...)
        //        }
        //
        //    Here we can have a path like
        //    `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
        //    may appear in two places. The penultimate segment,
        //    `SomeStruct::<A>`, contains parameters in TypeSpace, and the
        //    final segment, `foo::<B>` contains parameters in fn space.
        //
        // 4. Reference to an *associated const*:
        //
        // impl<A> AnotherStruct<A> {
        // const FOO: B = BAR;
        // }
        //
        // The path in this case will look like
        // `a::b::AnotherStruct::<A>::FOO`, so the penultimate segment
        // only will have parameters in TypeSpace.
        //
        // The first step then is to categorize the segments appropriately.

        assert!(!segments.is_empty());

        let mut ufcs_associated = None;
        let mut segment_spaces: Vec<_>;
        match def {
            // Case 1 and 1b. Reference to a *type* or *enum variant*.
            Def::SelfTy(..) |
            Def::Struct(..) |
            Def::Variant(..) |
            Def::Enum(..) |
            Def::TyAlias(..) |
            Def::AssociatedTy(..) |
            Def::Trait(..) |
            Def::PrimTy(..) |
            Def::TyParam(..) => {
                // Everything but the final segment should have no
                // parameters at all.
                segment_spaces = vec![None; segments.len() - 1];
                segment_spaces.push(Some(subst::TypeSpace));
            }

            // Case 2. Reference to a top-level value.
            Def::Fn(..) |
            Def::Const(..) |
            Def::Static(..) => {
                segment_spaces = vec![None; segments.len() - 1];
                segment_spaces.push(Some(subst::FnSpace));
            }

            // Case 3. Reference to a method.
            Def::Method(def_id) => {
                let container = self.tcx.impl_or_trait_item(def_id).container();
                match container {
                    ty::TraitContainer(trait_did) => {
                        callee::check_legal_trait_for_method_call(self.ccx, span, trait_did)
                    }
                    ty::ImplContainer(_) => {}
                }

                if segments.len() >= 2 {
                    segment_spaces = vec![None; segments.len() - 2];
                    segment_spaces.push(Some(subst::TypeSpace));
                    segment_spaces.push(Some(subst::FnSpace));
                } else {
                    // `<T>::method` will end up here, and so can `T::method`.
                    let self_ty = opt_self_ty.expect("UFCS sugared method missing Self");
                    segment_spaces = vec![Some(subst::FnSpace)];
                    ufcs_associated = Some((container, self_ty));
                }
            }

            Def::AssociatedConst(def_id) => {
                let container = self.tcx.impl_or_trait_item(def_id).container();
                match container {
                    ty::TraitContainer(trait_did) => {
                        callee::check_legal_trait_for_method_call(self.ccx, span, trait_did)
                    }
                    ty::ImplContainer(_) => {}
                }

                if segments.len() >= 2 {
                    segment_spaces = vec![None; segments.len() - 2];
                    segment_spaces.push(Some(subst::TypeSpace));
                    segment_spaces.push(None);
                } else {
                    // `<T>::CONST` will end up here, and so can `T::CONST`.
                    let self_ty = opt_self_ty.expect("UFCS sugared const missing Self");
                    segment_spaces = vec![None];
                    ufcs_associated = Some((container, self_ty));
                }
            }

            // Other cases. Various nonsense that really shouldn't show up
            // here. If they do, an error will have been reported
            // elsewhere. (I hope)
            Def::Mod(..) |
            Def::ForeignMod(..) |
            Def::Local(..) |
            Def::Label(..) |
            Def::Upvar(..) => {
                segment_spaces = vec![None; segments.len()];
            }

            Def::Err => {
                self.set_tainted_by_errors();
                segment_spaces = vec![None; segments.len()];
            }
        }
        assert_eq!(segment_spaces.len(), segments.len());

        // In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but
        // `opt_self_ty` can also be Some for `Foo::method`, where Foo's
        // type parameters are not mandatory.
        let require_type_space = opt_self_ty.is_some() && ufcs_associated.is_none();

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

        // Next, examine the definition, and determine how many type
        // parameters we expect from each space.
        let type_defs = &type_scheme.generics.types;
        let region_defs = &type_scheme.generics.regions;

        // Now that we have categorized what space the parameters for each
        // segment belong to, let's sort out the parameters that the user
        // provided (if any) into their appropriate spaces. We'll also report
        // errors if type parameters are provided in an inappropriate place.
        let mut substs = Substs::empty();
        for (&opt_space, segment) in segment_spaces.iter().zip(segments) {
            if let Some(space) = opt_space {
                self.push_explicit_parameters_from_segment_to_substs(space,
                                                                     span,
                                                                     type_defs,
                                                                     region_defs,
                                                                     segment,
                                                                     &mut substs);
            } else {
                self.tcx.prohibit_type_params(slice::ref_slice(segment));
            }
        }
        if let Some(self_ty) = opt_self_ty {
            if type_defs.len(subst::SelfSpace) == 1 {
                substs.types.push(subst::SelfSpace, self_ty);
            }
        }

        // Now we have to compare the types that the user *actually*
        // provided against the types that were *expected*. If the user
        // did not provide any types, then we want to substitute inference
        // variables. If the user provided some types, we may still need
        // to add defaults. If the user provided *too many* types, that's
        // a problem.
        for &space in &[subst::SelfSpace, subst::TypeSpace, subst::FnSpace] {
            self.adjust_type_parameters(span, space, type_defs,
                                        require_type_space, &mut substs);
            assert_eq!(substs.types.len(space), type_defs.len(space));

            self.adjust_region_parameters(span, space, region_defs, &mut substs);
            assert_eq!(substs.regions.len(space), region_defs.len(space));
        }

        // The things we are substituting into the type should not contain
        // escaping late-bound regions, and nor should the base type scheme.
        let substs = self.tcx.mk_substs(substs);
        assert!(!substs.has_regions_escaping_depth(0));
        assert!(!type_scheme.has_escaping_regions());

        // Add all the obligations that are required, substituting and
        // normalized appropriately.
        let bounds = self.instantiate_bounds(span, &substs, &type_predicates);
        self.add_obligations_for_parameters(
            traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def.def_id())),
            &bounds);

        // Substitute the values for the type parameters into the type of
        // the referenced item.
        let ty_substituted = self.instantiate_type_scheme(span, &substs, &type_scheme.ty);


        if let Some((ty::ImplContainer(impl_def_id), self_ty)) = ufcs_associated {
            // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
            // is inherent, there is no `Self` parameter, instead, the impl needs
            // type parameters, which we can infer by unifying the provided `Self`
            // with the substituted impl type.
            let impl_scheme = self.tcx.lookup_item_type(impl_def_id);
            assert_eq!(substs.types.len(subst::TypeSpace),
                       impl_scheme.generics.types.len(subst::TypeSpace));
            assert_eq!(substs.regions.len(subst::TypeSpace),
                       impl_scheme.generics.regions.len(subst::TypeSpace));

            let impl_ty = self.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
            match self.sub_types(false, TypeOrigin::Misc(span), self_ty, impl_ty) {
                Ok(InferOk { obligations, .. }) => {
                    // FIXME(#32730) propagate obligations
                    assert!(obligations.is_empty());
                }
                Err(_) => {
                    span_bug!(span,
                        "instantiate_value_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
                        self_ty,
                        impl_ty);
                }
            }
        }

        debug!("instantiate_value_path: type of {:?} is {:?}",
               node_id,
               ty_substituted);
        self.write_ty(node_id, ty_substituted);
        self.write_substs(node_id, ty::ItemSubsts {
            substs: substs
        });
        ty_substituted
    }

    /// Finds the parameters that the user provided and adds them to `substs`. If too many
    /// parameters are provided, then reports an error and clears the output vector.
    ///
    /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
    /// use inference variables. This seems less likely to lead to derived errors.
    ///
    /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
    /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
    /// here because we can easily use the precise span of the N+1'th parameter.
    fn push_explicit_parameters_from_segment_to_substs(&self,
        space: subst::ParamSpace,
        span: Span,
        type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
        region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
        segment: &hir::PathSegment,
        substs: &mut Substs<'tcx>)
    {
        match segment.parameters {
            hir::AngleBracketedParameters(ref data) => {
                self.push_explicit_angle_bracketed_parameters_from_segment_to_substs(
                    space, type_defs, region_defs, data, substs);
            }

            hir::ParenthesizedParameters(ref data) => {
                span_err!(self.tcx.sess, span, E0238,
                    "parenthesized parameters may only be used with a trait");
                self.push_explicit_parenthesized_parameters_from_segment_to_substs(
                    space, span, type_defs, data, substs);
            }
        }
    }

    fn push_explicit_angle_bracketed_parameters_from_segment_to_substs(&self,
        space: subst::ParamSpace,
        type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
        region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
        data: &hir::AngleBracketedParameterData,
        substs: &mut Substs<'tcx>)
    {
        {
            let type_count = type_defs.len(space);
            assert_eq!(substs.types.len(space), 0);
            for (i, typ) in data.types.iter().enumerate() {
                let t = self.to_ty(&typ);
                if i < type_count {
                    substs.types.push(space, t);
                } else if i == type_count {
                    span_err!(self.tcx.sess, typ.span, E0087,
                        "too many type parameters provided: \
                         expected at most {} parameter{}, \
                         found {} parameter{}",
                         type_count,
                         if type_count == 1 {""} else {"s"},
                         data.types.len(),
                         if data.types.len() == 1 {""} else {"s"});
                    substs.types.truncate(space, 0);
                    break;
                }
            }
        }

        if !data.bindings.is_empty() {
            span_err!(self.tcx.sess, data.bindings[0].span, E0182,
                      "unexpected binding of associated item in expression path \
                       (only allowed in type paths)");
        }

        {
            let region_count = region_defs.len(space);
            assert_eq!(substs.regions.len(space), 0);
            for (i, lifetime) in data.lifetimes.iter().enumerate() {
                let r = ast_region_to_region(self.tcx, lifetime);
                if i < region_count {
                    substs.regions.push(space, r);
                } else if i == region_count {
                    span_err!(self.tcx.sess, lifetime.span, E0088,
                        "too many lifetime parameters provided: \
                         expected {} parameter{}, found {} parameter{}",
                        region_count,
                        if region_count == 1 {""} else {"s"},
                        data.lifetimes.len(),
                        if data.lifetimes.len() == 1 {""} else {"s"});
                    substs.regions.truncate(space, 0);
                    break;
                }
            }
        }
    }

    /// As with
    /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
    /// but intended for `Foo(A,B) -> C` form. This expands to
    /// roughly the same thing as `Foo<(A,B),C>`. One important
    /// difference has to do with the treatment of anonymous
    /// regions, which are translated into bound regions (NYI).
    fn push_explicit_parenthesized_parameters_from_segment_to_substs(&self,
        space: subst::ParamSpace,
        span: Span,
        type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
        data: &hir::ParenthesizedParameterData,
        substs: &mut Substs<'tcx>)
    {
        let type_count = type_defs.len(space);
        if type_count < 2 {
            span_err!(self.tcx.sess, span, E0167,
                      "parenthesized form always supplies 2 type parameters, \
                      but only {} parameter(s) were expected",
                      type_count);
        }

        let input_tys: Vec<Ty> =
            data.inputs.iter().map(|ty| self.to_ty(&ty)).collect();

        let tuple_ty = self.tcx.mk_tup(input_tys);

        if type_count >= 1 {
            substs.types.push(space, tuple_ty);
        }

        let output_ty: Option<Ty> =
            data.output.as_ref().map(|ty| self.to_ty(&ty));

        let output_ty =
            output_ty.unwrap_or(self.tcx.mk_nil());

        if type_count >= 2 {
            substs.types.push(space, output_ty);
        }
    }

    fn adjust_type_parameters(&self,
        span: Span,
        space: ParamSpace,
        defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
        require_type_space: bool,
        substs: &mut Substs<'tcx>)
    {
        let provided_len = substs.types.len(space);
        let desired = defs.get_slice(space);
        let required_len = desired.iter()
                              .take_while(|d| d.default.is_none())
                              .count();

        debug!("adjust_type_parameters(space={:?}, \
               provided_len={}, \
               desired_len={}, \
               required_len={})",
               space,
               provided_len,
               desired.len(),
               required_len);

        // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
        assert!(provided_len <= desired.len());

        // Nothing specified at all: supply inference variables for
        // everything.
        if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
            substs.types.replace(space, Vec::new());
            self.type_vars_for_defs(span, space, substs, &desired[..]);
            return;
        }

        // Too few parameters specified: report an error and use Err
        // for everything.
        if provided_len < required_len {
            let qualifier =
                if desired.len() != required_len { "at least " } else { "" };
            span_err!(self.tcx.sess, span, E0089,
                "too few type parameters provided: expected {}{} parameter{}, \
                 found {} parameter{}",
                qualifier, required_len,
                if required_len == 1 {""} else {"s"},
                provided_len,
                if provided_len == 1 {""} else {"s"});
            substs.types.replace(space, vec![self.tcx.types.err; desired.len()]);
            return;
        }

        // Otherwise, add in any optional parameters that the user
        // omitted. The case of *too many* parameters is handled
        // already by
        // push_explicit_parameters_from_segment_to_substs(). Note
        // that the *default* type are expressed in terms of all prior
        // parameters, so we have to substitute as we go with the
        // partial substitution that we have built up.
        for i in provided_len..desired.len() {
            let default = desired[i].default.unwrap();
            let default = default.subst_spanned(self.tcx, substs, Some(span));
            substs.types.push(space, default);
        }
        assert_eq!(substs.types.len(space), desired.len());

        debug!("Final substs: {:?}", substs);
    }

    fn adjust_region_parameters(&self,
        span: Span,
        space: ParamSpace,
        defs: &VecPerParamSpace<ty::RegionParameterDef>,
        substs: &mut Substs)
    {
        let provided_len = substs.regions.len(space);
        let desired = defs.get_slice(space);

        // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
        assert!(provided_len <= desired.len());

        // If nothing was provided, just use inference variables.
        if provided_len == 0 {
            substs.regions.replace(
                space,
                self.region_vars_for_defs(span, desired));
            return;
        }

        // If just the right number were provided, everybody is happy.
        if provided_len == desired.len() {
            return;
        }

        // Otherwise, too few were provided. Report an error and then
        // use inference variables.
        span_err!(self.tcx.sess, span, E0090,
            "too few lifetime parameters provided: expected {} parameter{}, \
             found {} parameter{}",
            desired.len(),
            if desired.len() == 1 {""} else {"s"},
            provided_len,
            if provided_len == 1 {""} else {"s"});

        substs.regions.replace(
            space,
            self.region_vars_for_defs(span, desired));
    }

    fn structurally_resolve_type_or_else<F>(&self, sp: Span, ty: Ty<'tcx>, f: F)
                                            -> Ty<'tcx>
        where F: Fn() -> Ty<'tcx>
    {
        let mut ty = self.resolve_type_vars_with_obligations(ty);

        if ty.is_ty_var() {
            let alternative = f();

            // If not, error.
            if alternative.is_ty_var() || alternative.references_error() {
                if !self.is_tainted_by_errors() {
                    self.type_error_message(sp, |_actual| {
                        "the type of this value must be known in this context".to_string()
                    }, ty);
                }
                self.demand_suptype(sp, self.tcx.types.err, ty);
                ty = self.tcx.types.err;
            } else {
                self.demand_suptype(sp, alternative, ty);
                ty = alternative;
            }
        }

        ty
    }

    // Resolves `typ` by a single level if `typ` is a type variable.  If no
    // resolution is possible, then an error is reported.
    pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
        self.structurally_resolve_type_or_else(sp, ty, || {
            self.tcx.types.err
        })
    }
}

// Returns true if b contains a break that can exit from b
pub fn may_break(tcx: TyCtxt, id: ast::NodeId, b: &hir::Block) -> bool {
    // First: is there an unlabeled break immediately
    // inside the loop?
    (loop_query(&b, |e| {
        match *e {
            hir::ExprBreak(None) => true,
            _ => false
        }
    })) ||
    // Second: is there a labeled break with label
    // <id> nested anywhere inside the loop?
    (block_query(b, |e| {
        if let hir::ExprBreak(Some(_)) = e.node {
            tcx.expect_def(e.id) == Def::Label(id)
        } else {
            false
        }
    }))
}

pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                       tps: &[hir::TyParam],
                                       ty: Ty<'tcx>) {
    debug!("check_bounds_are_used(n_tps={}, ty={:?})",
           tps.len(),  ty);

    // make a vector of booleans initially false, set to true when used
    if tps.is_empty() { return; }
    let mut tps_used = vec![false; tps.len()];

    for leaf_ty in ty.walk() {
        if let ty::TyParam(ParamTy {idx, ..}) = leaf_ty.sty {
            debug!("Found use of ty param num {}", idx);
            tps_used[idx as usize] = true;
        }
    }

    for (i, b) in tps_used.iter().enumerate() {
        if !*b {
            span_err!(ccx.tcx.sess, tps[i].span, E0091,
                "type parameter `{}` is unused",
                tps[i].name);
        }
    }
}
