// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Conversion from AST representation of types to the ty.rs
//! representation.  The main routine here is `ast_ty_to_ty()`: each use
//! is parameterized by an instance of `AstConv` and a `RegionScope`.
//!
//! The parameterization of `ast_ty_to_ty()` is because it behaves
//! somewhat differently during the collect and check phases,
//! particularly with respect to looking up the types of top-level
//! items.  In the collect phase, the crate context is used as the
//! `AstConv` instance; in this phase, the `get_item_type_scheme()`
//! function triggers a recursive call to `type_scheme_of_item()`
//! (note that `ast_ty_to_ty()` will detect recursive types and report
//! an error).  In the check phase, when the FnCtxt is used as the
//! `AstConv`, `get_item_type_scheme()` just looks up the item type in
//! `tcx.tcache` (using `ty::lookup_item_type`).
//!
//! The `RegionScope` trait controls what happens when the user does
//! not specify a region in some location where a region is required
//! (e.g., if the user writes `&Foo` as a type rather than `&'a Foo`).
//! See the `rscope` module for more details.
//!
//! Unlike the `AstConv` trait, the region scope can change as we descend
//! the type.  This is to accommodate the fact that (a) fn types are binding
//! scopes and (b) the default region may change.  To understand case (a),
//! consider something like:
//!
//!   type foo = { x: &a.int, y: |&a.int| }
//!
//! The type of `x` is an error because there is no region `a` in scope.
//! In the type of `y`, however, region `a` is considered a bound region
//! as it does not already appear in scope.
//!
//! Case (b) says that if you have a type:
//!   type foo<'a> = ...;
//!   type bar = fn(&foo, &a.foo)
//! The fully expanded version of type bar is:
//!   type bar = fn(&'foo &, &a.foo<'a>)
//! Note that the self region for the `foo` defaulted to `&` in the first
//! case but `&a` in the second.  Basically, defaults that appear inside
//! an rptr (`&r.T`) use the region `r` that appears in the rptr.

use rustc_const_eval::eval_length;
use hir::{self, SelfKind};
use hir::def::{Def, PathResolution};
use hir::def_id::DefId;
use hir::print as pprust;
use middle::resolve_lifetime as rl;
use rustc::lint;
use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace};
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
use rustc::ty::wf::object_region_bounds;
use rustc_back::slice;
use require_c_abi_if_variadic;
use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
             ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope,
             ElisionFailureInfo, ElidedLifetime};
use util::common::{ErrorReported, FN_OUTPUT_NAME};
use util::nodemap::{NodeMap, FnvHashSet};

use std::cell::RefCell;
use syntax::{abi, ast};
use syntax::feature_gate::{GateIssue, emit_feature_err};
use syntax::parse::token::{self, keywords};
use syntax_pos::{Span, Pos};
use errors::DiagnosticBuilder;

pub trait AstConv<'gcx, 'tcx> {
    fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;

    /// A cache used for the result of `ast_ty_to_ty_cache`
    fn ast_ty_to_ty_cache(&self) -> &RefCell<NodeMap<Ty<'tcx>>>;

    /// Identify the type scheme for an item with a type, like a type
    /// alias, fn, or struct. This allows you to figure out the set of
    /// type parameters defined on the item.
    fn get_item_type_scheme(&self, span: Span, id: DefId)
                            -> Result<ty::TypeScheme<'tcx>, ErrorReported>;

    /// Returns the `TraitDef` for a given trait. This allows you to
    /// figure out the set of type parameters defined on the trait.
    fn get_trait_def(&self, span: Span, id: DefId)
                     -> Result<&'tcx ty::TraitDef<'tcx>, ErrorReported>;

    /// Ensure that the super-predicates for the trait with the given
    /// id are available and also for the transitive set of
    /// super-predicates.
    fn ensure_super_predicates(&self, span: Span, id: DefId)
                               -> Result<(), ErrorReported>;

    /// Returns the set of bounds in scope for the type parameter with
    /// the given id.
    fn get_type_parameter_bounds(&self, span: Span, def_id: ast::NodeId)
                                 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>;

    /// Returns true if the trait with id `trait_def_id` defines an
    /// associated type with the name `name`.
    fn trait_defines_associated_type_named(&self, trait_def_id: DefId, name: ast::Name)
                                           -> bool;

    /// Return an (optional) substitution to convert bound type parameters that
    /// are in scope into free ones. This function should only return Some
    /// within a fn body.
    /// See ParameterEnvironment::free_substs for more information.
    fn get_free_substs(&self) -> Option<&Substs<'tcx>>;

    /// What type should we use when a type is omitted?
    fn ty_infer(&self,
                param_and_substs: Option<ty::TypeParameterDef<'tcx>>,
                substs: Option<&mut Substs<'tcx>>,
                space: Option<ParamSpace>,
                span: Span) -> Ty<'tcx>;

    /// Projecting an associated type from a (potentially)
    /// higher-ranked trait reference is more complicated, because of
    /// the possibility of late-bound regions appearing in the
    /// associated type binding. This is not legal in function
    /// signatures for that reason. In a function body, we can always
    /// handle it because we can use inference variables to remove the
    /// late-bound regions.
    fn projected_ty_from_poly_trait_ref(&self,
                                        span: Span,
                                        poly_trait_ref: ty::PolyTraitRef<'tcx>,
                                        item_name: ast::Name)
                                        -> Ty<'tcx>;

    /// Project an associated type from a non-higher-ranked trait reference.
    /// This is fairly straightforward and can be accommodated in any context.
    fn projected_ty(&self,
                    span: Span,
                    _trait_ref: ty::TraitRef<'tcx>,
                    _item_name: ast::Name)
                    -> Ty<'tcx>;

    /// Invoked when we encounter an error from some prior pass
    /// (e.g. resolve) that is translated into a ty-error. This is
    /// used to help suppress derived errors typeck might otherwise
    /// report.
    fn set_tainted_by_errors(&self);
}

#[derive(PartialEq, Eq)]
pub enum PathParamMode {
    // Any path in a type context.
    Explicit,
    // The `module::Type` in `module::Type::method` in an expression.
    Optional
}

struct ConvertedBinding<'tcx> {
    item_name: ast::Name,
    ty: Ty<'tcx>,
    span: Span,
}

type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>);

pub fn ast_region_to_region(tcx: TyCtxt, lifetime: &hir::Lifetime)
                            -> ty::Region {
    let r = match tcx.named_region_map.defs.get(&lifetime.id) {
        None => {
            // should have been recorded by the `resolve_lifetime` pass
            span_bug!(lifetime.span, "unresolved lifetime");
        }

        Some(&rl::DefStaticRegion) => {
            ty::ReStatic
        }

        Some(&rl::DefLateBoundRegion(debruijn, id)) => {
            // If this region is declared on a function, it will have
            // an entry in `late_bound`, but if it comes from
            // `for<'a>` in some type or something, it won't
            // necessarily have one. In that case though, we won't be
            // changed from late to early bound, so we can just
            // substitute false.
            let issue_32330 = tcx.named_region_map
                                 .late_bound
                                 .get(&id)
                                 .cloned()
                                 .unwrap_or(ty::Issue32330::WontChange);
            ty::ReLateBound(debruijn, ty::BrNamed(tcx.map.local_def_id(id),
                                                  lifetime.name,
                                                  issue_32330))
        }

        Some(&rl::DefEarlyBoundRegion(space, index, _)) => {
            ty::ReEarlyBound(ty::EarlyBoundRegion {
                space: space,
                index: index,
                name: lifetime.name
            })
        }

        Some(&rl::DefFreeRegion(scope, id)) => {
            // As in DefLateBoundRegion above, could be missing for some late-bound
            // regions, but also for early-bound regions.
            let issue_32330 = tcx.named_region_map
                                 .late_bound
                                 .get(&id)
                                 .cloned()
                                 .unwrap_or(ty::Issue32330::WontChange);
            ty::ReFree(ty::FreeRegion {
                    scope: scope.to_code_extent(&tcx.region_maps),
                    bound_region: ty::BrNamed(tcx.map.local_def_id(id),
                                              lifetime.name,
                                              issue_32330)
            })

                // (*) -- not late-bound, won't change
        }
    };

    debug!("ast_region_to_region(lifetime={:?} id={}) yields {:?}",
           lifetime,
           lifetime.id,
           r);

    r
}

fn report_elision_failure(
    db: &mut DiagnosticBuilder,
    params: Vec<ElisionFailureInfo>)
{
    let mut m = String::new();
    let len = params.len();

    let elided_params: Vec<_> = params.into_iter()
                                       .filter(|info| info.lifetime_count > 0)
                                       .collect();

    let elided_len = elided_params.len();

    for (i, info) in elided_params.into_iter().enumerate() {
        let ElisionFailureInfo {
            name, lifetime_count: n, have_bound_regions
        } = info;

        let help_name = if name.is_empty() {
            format!("argument {}", i + 1)
        } else {
            format!("`{}`", name)
        };

        m.push_str(&(if n == 1 {
            help_name
        } else {
            format!("one of {}'s {} elided {}lifetimes", help_name, n,
                    if have_bound_regions { "free " } else { "" } )
        })[..]);

        if elided_len == 2 && i == 0 {
            m.push_str(" or ");
        } else if i + 2 == elided_len {
            m.push_str(", or ");
        } else if i != elided_len - 1 {
            m.push_str(", ");
        }

    }

    if len == 0 {
        help!(db,
                   "this function's return type contains a borrowed value, but \
                    there is no value for it to be borrowed from");
        help!(db,
                   "consider giving it a 'static lifetime");
    } else if elided_len == 0 {
        help!(db,
                   "this function's return type contains a borrowed value with \
                    an elided lifetime, but the lifetime cannot be derived from \
                    the arguments");
        help!(db,
                   "consider giving it an explicit bounded or 'static \
                    lifetime");
    } else if elided_len == 1 {
        help!(db,
                   "this function's return type contains a borrowed value, but \
                    the signature does not say which {} it is borrowed from",
                   m);
    } else {
        help!(db,
                   "this function's return type contains a borrowed value, but \
                    the signature does not say whether it is borrowed from {}",
                   m);
    }
}

impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
    pub fn opt_ast_region_to_region(&self,
        rscope: &RegionScope,
        default_span: Span,
        opt_lifetime: &Option<hir::Lifetime>) -> ty::Region
    {
        let r = match *opt_lifetime {
            Some(ref lifetime) => {
                ast_region_to_region(self.tcx(), lifetime)
            }

            None => match rscope.anon_regions(default_span, 1) {
                Ok(rs) => rs[0],
                Err(params) => {
                    let mut err = struct_span_err!(self.tcx().sess, default_span, E0106,
                                                   "missing lifetime specifier");
                    if let Some(params) = params {
                        report_elision_failure(&mut err, params);
                    }
                    err.emit();
                    ty::ReStatic
                }
            }
        };

        debug!("opt_ast_region_to_region(opt_lifetime={:?}) yields {:?}",
                opt_lifetime,
                r);

        r
    }

    /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
    /// returns an appropriate set of substitutions for this particular reference to `I`.
    pub fn ast_path_substs_for_ty(&self,
        rscope: &RegionScope,
        span: Span,
        param_mode: PathParamMode,
        decl_generics: &ty::Generics<'tcx>,
        item_segment: &hir::PathSegment)
        -> Substs<'tcx>
    {
        let tcx = self.tcx();

        // ast_path_substs() is only called to convert paths that are
        // known to refer to traits, types, or structs. In these cases,
        // all type parameters defined for the item being referenced will
        // be in the TypeSpace or SelfSpace.
        //
        // Note: in the case of traits, the self parameter is also
        // defined, but we don't currently create a `type_param_def` for
        // `Self` because it is implicit.
        assert!(decl_generics.regions.all(|d| d.space == TypeSpace));
        assert!(decl_generics.types.all(|d| d.space != FnSpace));

        let (regions, types, assoc_bindings) = match item_segment.parameters {
            hir::AngleBracketedParameters(ref data) => {
                self.convert_angle_bracketed_parameters(rscope, span, decl_generics, data)
            }
            hir::ParenthesizedParameters(..) => {
                span_err!(tcx.sess, span, E0214,
                          "parenthesized parameters may only be used with a trait");
                let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
                (Substs::empty(),
                 ty_param_defs.iter().map(|_| tcx.types.err).collect(),
                 vec![])
            }
        };

        assoc_bindings.first().map(|b| self.tcx().prohibit_projection(b.span));

        self.create_substs_for_ast_path(span,
                                        param_mode,
                                        decl_generics,
                                        None,
                                        types,
                                        regions)
    }

    fn create_region_substs(&self,
        rscope: &RegionScope,
        span: Span,
        decl_generics: &ty::Generics<'tcx>,
        regions_provided: Vec<ty::Region>)
        -> Substs<'tcx>
    {
        let tcx = self.tcx();

        // If the type is parameterized by this region, then replace this
        // region with the current anon region binding (in other words,
        // whatever & would get replaced with).
        let expected_num_region_params = decl_generics.regions.len(TypeSpace);
        let supplied_num_region_params = regions_provided.len();
        let regions = if expected_num_region_params == supplied_num_region_params {
            regions_provided
        } else {
            let anon_regions =
                rscope.anon_regions(span, expected_num_region_params);

            if supplied_num_region_params != 0 || anon_regions.is_err() {
                report_lifetime_number_error(tcx, span,
                                             supplied_num_region_params,
                                             expected_num_region_params);
            }

            match anon_regions {
                Ok(anon_regions) => anon_regions,
                Err(_) => (0..expected_num_region_params).map(|_| ty::ReStatic).collect()
            }
        };
        Substs::new_type(vec![], regions)
    }

    /// Given the type/region arguments provided to some path (along with
    /// an implicit Self, if this is a trait reference) returns the complete
    /// set of substitutions. This may involve applying defaulted type parameters.
    ///
    /// Note that the type listing given here is *exactly* what the user provided.
    ///
    /// The `region_substs` should be the result of `create_region_substs`
    /// -- that is, a substitution with no types but the correct number of
    /// regions.
    fn create_substs_for_ast_path(&self,
        span: Span,
        param_mode: PathParamMode,
        decl_generics: &ty::Generics<'tcx>,
        self_ty: Option<Ty<'tcx>>,
        types_provided: Vec<Ty<'tcx>>,
        region_substs: Substs<'tcx>)
        -> Substs<'tcx>
    {
        let tcx = self.tcx();

        debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \
               types_provided={:?}, region_substs={:?})",
               decl_generics, self_ty, types_provided,
               region_substs);

        assert_eq!(region_substs.regions.len(TypeSpace), decl_generics.regions.len(TypeSpace));
        assert!(region_substs.types.is_empty());

        // Convert the type parameters supplied by the user.
        let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
        let formal_ty_param_count = ty_param_defs.len();
        let required_ty_param_count = ty_param_defs.iter()
                                                   .take_while(|x| x.default.is_none())
                                                   .count();

        let mut type_substs = self.get_type_substs_for_defs(span,
                                                            types_provided,
                                                            param_mode,
                                                            ty_param_defs,
                                                            region_substs.clone(),
                                                            self_ty);

        let supplied_ty_param_count = type_substs.len();
        check_type_argument_count(self.tcx(), span, supplied_ty_param_count,
                                  required_ty_param_count, formal_ty_param_count);

        if supplied_ty_param_count < required_ty_param_count {
            while type_substs.len() < required_ty_param_count {
                type_substs.push(tcx.types.err);
            }
        } else if supplied_ty_param_count > formal_ty_param_count {
            type_substs.truncate(formal_ty_param_count);
        }
        assert!(type_substs.len() >= required_ty_param_count &&
                type_substs.len() <= formal_ty_param_count);

        let mut substs = region_substs;
        substs.types.extend(TypeSpace, type_substs.into_iter());

        match self_ty {
            None => {
                // If no self-type is provided, it's still possible that
                // one was declared, because this could be an object type.
            }
            Some(ty) => {
                // If a self-type is provided, one should have been
                // "declared" (in other words, this should be a
                // trait-ref).
                assert!(decl_generics.types.get_self().is_some());
                substs.types.push(SelfSpace, ty);
            }
        }

        let actual_supplied_ty_param_count = substs.types.len(TypeSpace);
        for param in &ty_param_defs[actual_supplied_ty_param_count..] {
            if let Some(default) = param.default {
                // If we are converting an object type, then the
                // `Self` parameter is unknown. However, some of the
                // other type parameters may reference `Self` in their
                // defaults. This will lead to an ICE if we are not
                // careful!
                if self_ty.is_none() && default.has_self_ty() {
                    span_err!(tcx.sess, span, E0393,
                              "the type parameter `{}` must be explicitly specified \
                               in an object type because its default value `{}` references \
                               the type `Self`",
                              param.name,
                              default);
                    substs.types.push(TypeSpace, tcx.types.err);
                } else {
                    // This is a default type parameter.
                    let default = default.subst_spanned(tcx,
                                                        &substs,
                                                        Some(span));
                    substs.types.push(TypeSpace, default);
                }
            } else {
                span_bug!(span, "extra parameter without default");
            }
        }

        debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
               decl_generics, self_ty, substs);

        substs
    }

    /// Returns types_provided if it is not empty, otherwise populating the
    /// type parameters with inference variables as appropriate.
    fn get_type_substs_for_defs(&self,
                                span: Span,
                                types_provided: Vec<Ty<'tcx>>,
                                param_mode: PathParamMode,
                                ty_param_defs: &[ty::TypeParameterDef<'tcx>],
                                mut substs: Substs<'tcx>,
                                self_ty: Option<Ty<'tcx>>)
                                -> Vec<Ty<'tcx>>
    {
        fn default_type_parameter<'tcx>(p: &ty::TypeParameterDef<'tcx>, self_ty: Option<Ty<'tcx>>)
                                        -> Option<ty::TypeParameterDef<'tcx>>
        {
            if let Some(ref default) = p.default {
                if self_ty.is_none() && default.has_self_ty() {
                    // There is no suitable inference default for a type parameter
                    // that references self with no self-type provided.
                    return None;
                }
            }

            Some(p.clone())
        }

        if param_mode == PathParamMode::Optional && types_provided.is_empty() {
            ty_param_defs
                .iter()
                .map(|p| self.ty_infer(default_type_parameter(p, self_ty), Some(&mut substs),
                                       Some(TypeSpace), span))
                .collect()
        } else {
            types_provided
        }
    }

    fn convert_angle_bracketed_parameters(&self,
                                          rscope: &RegionScope,
                                          span: Span,
                                          decl_generics: &ty::Generics<'tcx>,
                                          data: &hir::AngleBracketedParameterData)
                                          -> (Substs<'tcx>,
                                              Vec<Ty<'tcx>>,
                                              Vec<ConvertedBinding<'tcx>>)
    {
        let regions: Vec<_> =
            data.lifetimes.iter()
                          .map(|l| ast_region_to_region(self.tcx(), l))
                          .collect();

        let region_substs =
            self.create_region_substs(rscope, span, decl_generics, regions);

        let types: Vec<_> =
            data.types.iter()
                      .enumerate()
                      .map(|(i,t)| self.ast_ty_arg_to_ty(rscope, decl_generics,
                                                         i, &region_substs, t))
                      .collect();

        let assoc_bindings: Vec<_> =
            data.bindings.iter()
                         .map(|b| ConvertedBinding { item_name: b.name,
                                                     ty: self.ast_ty_to_ty(rscope, &b.ty),
                                                     span: b.span })
                         .collect();

        (region_substs, types, assoc_bindings)
    }

    /// Returns the appropriate lifetime to use for any output lifetimes
    /// (if one exists) and a vector of the (pattern, number of lifetimes)
    /// corresponding to each input type/pattern.
    fn find_implied_output_region(&self,
                                  input_tys: &[Ty<'tcx>],
                                  input_pats: Vec<String>) -> ElidedLifetime
    {
        let tcx = self.tcx();
        let mut lifetimes_for_params = Vec::new();
        let mut possible_implied_output_region = None;

        for (input_type, input_pat) in input_tys.iter().zip(input_pats) {
            let mut regions = FnvHashSet();
            let have_bound_regions = tcx.collect_regions(input_type, &mut regions);

            debug!("find_implied_output_regions: collected {:?} from {:?} \
                    have_bound_regions={:?}", &regions, input_type, have_bound_regions);

            if regions.len() == 1 {
                // there's a chance that the unique lifetime of this
                // iteration will be the appropriate lifetime for output
                // parameters, so lets store it.
                possible_implied_output_region = regions.iter().cloned().next();
            }

            lifetimes_for_params.push(ElisionFailureInfo {
                name: input_pat,
                lifetime_count: regions.len(),
                have_bound_regions: have_bound_regions
            });
        }

        if lifetimes_for_params.iter().map(|e| e.lifetime_count).sum::<usize>() == 1 {
            Ok(possible_implied_output_region.unwrap())
        } else {
            Err(Some(lifetimes_for_params))
        }
    }

    fn convert_ty_with_lifetime_elision(&self,
                                        elided_lifetime: ElidedLifetime,
                                        ty: &hir::Ty)
                                        -> Ty<'tcx>
    {
        match elided_lifetime {
            Ok(implied_output_region) => {
                let rb = ElidableRscope::new(implied_output_region);
                self.ast_ty_to_ty(&rb, ty)
            }
            Err(param_lifetimes) => {
                // All regions must be explicitly specified in the output
                // if the lifetime elision rules do not apply. This saves
                // the user from potentially-confusing errors.
                let rb = UnelidableRscope::new(param_lifetimes);
                self.ast_ty_to_ty(&rb, ty)
            }
        }
    }

    fn convert_parenthesized_parameters(&self,
                                        rscope: &RegionScope,
                                        span: Span,
                                        decl_generics: &ty::Generics<'tcx>,
                                        data: &hir::ParenthesizedParameterData)
                                        -> (Substs<'tcx>,
                                            Vec<Ty<'tcx>>,
                                            Vec<ConvertedBinding<'tcx>>)
    {
        let region_substs =
            self.create_region_substs(rscope, span, decl_generics, Vec::new());

        let binding_rscope = BindingRscope::new();
        let inputs =
            data.inputs.iter()
                       .map(|a_t| self.ast_ty_arg_to_ty(&binding_rscope, decl_generics,
                                                        0, &region_substs, a_t))
                       .collect::<Vec<Ty<'tcx>>>();

        let input_params = vec![String::new(); inputs.len()];
        let implied_output_region = self.find_implied_output_region(&inputs, input_params);

        let input_ty = self.tcx().mk_tup(inputs);

        let (output, output_span) = match data.output {
            Some(ref output_ty) => {
                (self.convert_ty_with_lifetime_elision(implied_output_region, &output_ty),
                 output_ty.span)
            }
            None => {
                (self.tcx().mk_nil(), data.span)
            }
        };

        let output_binding = ConvertedBinding {
            item_name: token::intern(FN_OUTPUT_NAME),
            ty: output,
            span: output_span
        };

        (region_substs, vec![input_ty], vec![output_binding])
    }

    pub fn instantiate_poly_trait_ref(&self,
        rscope: &RegionScope,
        ast_trait_ref: &hir::PolyTraitRef,
        self_ty: Option<Ty<'tcx>>,
        poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
        -> ty::PolyTraitRef<'tcx>
    {
        let trait_ref = &ast_trait_ref.trait_ref;
        let trait_def_id = self.trait_def_id(trait_ref);
        self.ast_path_to_poly_trait_ref(rscope,
                                        trait_ref.path.span,
                                        PathParamMode::Explicit,
                                        trait_def_id,
                                        self_ty,
                                        trait_ref.ref_id,
                                        trait_ref.path.segments.last().unwrap(),
                                        poly_projections)
    }

    /// Instantiates the path for the given trait reference, assuming that it's
    /// bound to a valid trait type. Returns the def_id for the defining trait.
    /// Fails if the type is a type other than a trait type.
    ///
    /// If the `projections` argument is `None`, then assoc type bindings like `Foo<T=X>`
    /// are disallowed. Otherwise, they are pushed onto the vector given.
    pub fn instantiate_mono_trait_ref(&self,
        rscope: &RegionScope,
        trait_ref: &hir::TraitRef,
        self_ty: Option<Ty<'tcx>>)
        -> ty::TraitRef<'tcx>
    {
        let trait_def_id = self.trait_def_id(trait_ref);
        self.ast_path_to_mono_trait_ref(rscope,
                                        trait_ref.path.span,
                                        PathParamMode::Explicit,
                                        trait_def_id,
                                        self_ty,
                                        trait_ref.path.segments.last().unwrap())
    }

    fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
        let path = &trait_ref.path;
        match self.tcx().expect_def(trait_ref.ref_id) {
            Def::Trait(trait_def_id) => trait_def_id,
            Def::Err => {
                self.tcx().sess.fatal("cannot continue compilation due to previous error");
            }
            _ => {
                span_fatal!(self.tcx().sess, path.span, E0245, "`{}` is not a trait",
                            path);
            }
        }
    }

    fn object_path_to_poly_trait_ref(&self,
        rscope: &RegionScope,
        span: Span,
        param_mode: PathParamMode,
        trait_def_id: DefId,
        trait_path_ref_id: ast::NodeId,
        trait_segment: &hir::PathSegment,
        mut projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
        -> ty::PolyTraitRef<'tcx>
    {
        self.ast_path_to_poly_trait_ref(rscope,
                                        span,
                                        param_mode,
                                        trait_def_id,
                                        None,
                                        trait_path_ref_id,
                                        trait_segment,
                                        projections)
    }

    fn ast_path_to_poly_trait_ref(&self,
        rscope: &RegionScope,
        span: Span,
        param_mode: PathParamMode,
        trait_def_id: DefId,
        self_ty: Option<Ty<'tcx>>,
        path_id: ast::NodeId,
        trait_segment: &hir::PathSegment,
        poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
        -> ty::PolyTraitRef<'tcx>
    {
        debug!("ast_path_to_poly_trait_ref(trait_segment={:?})", trait_segment);
        // The trait reference introduces a binding level here, so
        // we need to shift the `rscope`. It'd be nice if we could
        // do away with this rscope stuff and work this knowledge
        // into resolve_lifetimes, as we do with non-omitted
        // lifetimes. Oh well, not there yet.
        let shifted_rscope = &ShiftedRscope::new(rscope);

        let (substs, assoc_bindings) =
            self.create_substs_for_ast_trait_ref(shifted_rscope,
                                                 span,
                                                 param_mode,
                                                 trait_def_id,
                                                 self_ty,
                                                 trait_segment);
        let poly_trait_ref = ty::Binder(ty::TraitRef::new(trait_def_id, substs));

        {
            let converted_bindings =
                assoc_bindings
                .iter()
                .filter_map(|binding| {
                    // specify type to assert that error was already reported in Err case:
                    let predicate: Result<_, ErrorReported> =
                        self.ast_type_binding_to_poly_projection_predicate(path_id,
                                                                           poly_trait_ref.clone(),
                                                                           self_ty,
                                                                           binding);
                    predicate.ok() // ok to ignore Err() because ErrorReported (see above)
                });
            poly_projections.extend(converted_bindings);
        }

        debug!("ast_path_to_poly_trait_ref(trait_segment={:?}, projections={:?}) -> {:?}",
               trait_segment, poly_projections, poly_trait_ref);
        poly_trait_ref
    }

    fn ast_path_to_mono_trait_ref(&self,
                                  rscope: &RegionScope,
                                  span: Span,
                                  param_mode: PathParamMode,
                                  trait_def_id: DefId,
                                  self_ty: Option<Ty<'tcx>>,
                                  trait_segment: &hir::PathSegment)
                                  -> ty::TraitRef<'tcx>
    {
        let (substs, assoc_bindings) =
            self.create_substs_for_ast_trait_ref(rscope,
                                                 span,
                                                 param_mode,
                                                 trait_def_id,
                                                 self_ty,
                                                 trait_segment);
        assoc_bindings.first().map(|b| self.tcx().prohibit_projection(b.span));
        ty::TraitRef::new(trait_def_id, substs)
    }

    fn create_substs_for_ast_trait_ref(&self,
                                       rscope: &RegionScope,
                                       span: Span,
                                       param_mode: PathParamMode,
                                       trait_def_id: DefId,
                                       self_ty: Option<Ty<'tcx>>,
                                       trait_segment: &hir::PathSegment)
                                       -> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
    {
        debug!("create_substs_for_ast_trait_ref(trait_segment={:?})",
               trait_segment);

        let trait_def = match self.get_trait_def(span, trait_def_id) {
            Ok(trait_def) => trait_def,
            Err(ErrorReported) => {
                // No convenient way to recover from a cycle here. Just bail. Sorry!
                self.tcx().sess.abort_if_errors();
                bug!("ErrorReported returned, but no errors reports?")
            }
        };

        let (regions, types, assoc_bindings) = match trait_segment.parameters {
            hir::AngleBracketedParameters(ref data) => {
                // For now, require that parenthetical notation be used
                // only with `Fn()` etc.
                if !self.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
                    emit_feature_err(&self.tcx().sess.parse_sess.span_diagnostic,
                                     "unboxed_closures", span, GateIssue::Language,
                                     "\
                        the precise format of `Fn`-family traits' \
                        type parameters is subject to change. \
                        Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead");
                }

                self.convert_angle_bracketed_parameters(rscope, span, &trait_def.generics, data)
            }
            hir::ParenthesizedParameters(ref data) => {
                // For now, require that parenthetical notation be used
                // only with `Fn()` etc.
                if !self.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
                    emit_feature_err(&self.tcx().sess.parse_sess.span_diagnostic,
                                     "unboxed_closures", span, GateIssue::Language,
                                     "\
                        parenthetical notation is only stable when used with `Fn`-family traits");
                }

                self.convert_parenthesized_parameters(rscope, span, &trait_def.generics, data)
            }
        };

        let substs = self.create_substs_for_ast_path(span,
                                                     param_mode,
                                                     &trait_def.generics,
                                                     self_ty,
                                                     types,
                                                     regions);

        (self.tcx().mk_substs(substs), assoc_bindings)
    }

    fn ast_type_binding_to_poly_projection_predicate(
        &self,
        path_id: ast::NodeId,
        mut trait_ref: ty::PolyTraitRef<'tcx>,
        self_ty: Option<Ty<'tcx>>,
        binding: &ConvertedBinding<'tcx>)
        -> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported>
    {
        let tcx = self.tcx();

        // Given something like `U : SomeTrait<T=X>`, we want to produce a
        // predicate like `<U as SomeTrait>::T = X`. This is somewhat
        // subtle in the event that `T` is defined in a supertrait of
        // `SomeTrait`, because in that case we need to upcast.
        //
        // That is, consider this case:
        //
        // ```
        // trait SubTrait : SuperTrait<int> { }
        // trait SuperTrait<A> { type T; }
        //
        // ... B : SubTrait<T=foo> ...
        // ```
        //
        // We want to produce `<B as SuperTrait<int>>::T == foo`.

        // Find any late-bound regions declared in `ty` that are not
        // declared in the trait-ref. These are not wellformed.
        //
        // Example:
        //
        //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
        //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
        let late_bound_in_trait_ref = tcx.collect_constrained_late_bound_regions(&trait_ref);
        let late_bound_in_ty = tcx.collect_referenced_late_bound_regions(&ty::Binder(binding.ty));
        debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
        debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
        for br in late_bound_in_ty.difference(&late_bound_in_trait_ref) {
            let br_name = match *br {
                ty::BrNamed(_, name, _) => name,
                _ => {
                    span_bug!(
                        binding.span,
                        "anonymous bound region {:?} in binding but not trait ref",
                        br);
                }
            };
            tcx.sess.add_lint(
                lint::builtin::HR_LIFETIME_IN_ASSOC_TYPE,
                path_id,
                binding.span,
                format!("binding for associated type `{}` references lifetime `{}`, \
                         which does not appear in the trait input types",
                        binding.item_name, br_name));
        }

        // Simple case: X is defined in the current trait.
        if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
            return Ok(ty::Binder(ty::ProjectionPredicate {      // <-------------------+
                projection_ty: ty::ProjectionTy {               //                     |
                    trait_ref: trait_ref.skip_binder().clone(), // Binder moved here --+
                    item_name: binding.item_name,
                },
                ty: binding.ty,
            }));
        }

        // Otherwise, we have to walk through the supertraits to find
        // those that do.  This is complicated by the fact that, for an
        // object type, the `Self` type is not present in the
        // substitutions (after all, it's being constructed right now),
        // but the `supertraits` iterator really wants one. To handle
        // this, we currently insert a dummy type and then remove it
        // later. Yuck.

        let dummy_self_ty = tcx.mk_infer(ty::FreshTy(0));
        if self_ty.is_none() { // if converting for an object type
            let mut dummy_substs = trait_ref.skip_binder().substs.clone(); // binder moved here -+
            assert!(dummy_substs.self_ty().is_none());                     //                    |
            dummy_substs.types.push(SelfSpace, dummy_self_ty);             //                    |
            trait_ref = ty::Binder(ty::TraitRef::new(trait_ref.def_id(),   // <------------+
                                                     tcx.mk_substs(dummy_substs)));
        }

        self.ensure_super_predicates(binding.span, trait_ref.def_id())?;

        let mut candidates: Vec<ty::PolyTraitRef> =
            traits::supertraits(tcx, trait_ref.clone())
            .filter(|r| self.trait_defines_associated_type_named(r.def_id(), binding.item_name))
            .collect();

        // If converting for an object type, then remove the dummy-ty from `Self` now.
        // Yuckety yuck.
        if self_ty.is_none() {
            for candidate in &mut candidates {
                let mut dummy_substs = candidate.0.substs.clone();
                assert!(dummy_substs.self_ty() == Some(dummy_self_ty));
                dummy_substs.types.pop(SelfSpace);
                *candidate = ty::Binder(ty::TraitRef::new(candidate.def_id(),
                                                          tcx.mk_substs(dummy_substs)));
            }
        }

        let candidate = self.one_bound_for_assoc_type(candidates,
                                                      &trait_ref.to_string(),
                                                      &binding.item_name.as_str(),
                                                      binding.span)?;

        Ok(ty::Binder(ty::ProjectionPredicate {             // <-------------------------+
            projection_ty: ty::ProjectionTy {               //                           |
                trait_ref: candidate.skip_binder().clone(), // binder is moved up here --+
                item_name: binding.item_name,
            },
            ty: binding.ty,
        }))
    }

    fn ast_path_to_ty(&self,
        rscope: &RegionScope,
        span: Span,
        param_mode: PathParamMode,
        did: DefId,
        item_segment: &hir::PathSegment)
        -> Ty<'tcx>
    {
        let tcx = self.tcx();
        let (generics, decl_ty) = match self.get_item_type_scheme(span, did) {
            Ok(ty::TypeScheme { generics,  ty: decl_ty }) => {
                (generics, decl_ty)
            }
            Err(ErrorReported) => {
                return tcx.types.err;
            }
        };

        let substs = self.ast_path_substs_for_ty(rscope,
                                                 span,
                                                 param_mode,
                                                 &generics,
                                                 item_segment);

        // FIXME(#12938): This is a hack until we have full support for DST.
        if Some(did) == self.tcx().lang_items.owned_box() {
            assert_eq!(substs.types.len(TypeSpace), 1);
            return self.tcx().mk_box(*substs.types.get(TypeSpace, 0));
        }

        decl_ty.subst(self.tcx(), &substs)
    }

    fn ast_ty_to_trait_ref(&self,
                           rscope: &RegionScope,
                           ty: &hir::Ty,
                           bounds: &[hir::TyParamBound])
                           -> Result<TraitAndProjections<'tcx>, ErrorReported>
    {
        /*!
         * In a type like `Foo + Send`, we want to wait to collect the
         * full set of bounds before we make the object type, because we
         * need them to infer a region bound.  (For example, if we tried
         * made a type from just `Foo`, then it wouldn't be enough to
         * infer a 'static bound, and hence the user would get an error.)
         * So this function is used when we're dealing with a sum type to
         * convert the LHS. It only accepts a type that refers to a trait
         * name, and reports an error otherwise.
         */

        match ty.node {
            hir::TyPath(None, ref path) => {
                let resolution = self.tcx().expect_resolution(ty.id);
                match resolution.base_def {
                    Def::Trait(trait_def_id) if resolution.depth == 0 => {
                        let mut projection_bounds = Vec::new();
                        let trait_ref =
                            self.object_path_to_poly_trait_ref(rscope,
                                                               path.span,
                                                               PathParamMode::Explicit,
                                                               trait_def_id,
                                                               ty.id,
                                                               path.segments.last().unwrap(),
                                                               &mut projection_bounds);
                        Ok((trait_ref, projection_bounds))
                    }
                    _ => {
                        span_err!(self.tcx().sess, ty.span, E0172,
                                  "expected a reference to a trait");
                        Err(ErrorReported)
                    }
                }
            }
            _ => {
                let mut err = struct_span_err!(self.tcx().sess, ty.span, E0178,
                                               "expected a path on the left-hand side \
                                                of `+`, not `{}`",
                                               pprust::ty_to_string(ty));
                let hi = bounds.iter().map(|x| match *x {
                    hir::TraitTyParamBound(ref tr, _) => tr.span.hi,
                    hir::RegionTyParamBound(ref r) => r.span.hi,
                }).max_by_key(|x| x.to_usize());
                let full_span = hi.map(|hi| Span {
                    lo: ty.span.lo,
                    hi: hi,
                    expn_id: ty.span.expn_id,
                });
                match (&ty.node, full_span) {
                    (&hir::TyRptr(None, ref mut_ty), Some(full_span)) => {
                        let mutbl_str = if mut_ty.mutbl == hir::MutMutable { "mut " } else { "" };
                        err.span_suggestion(full_span, "try adding parentheses (per RFC 438):",
                                            format!("&{}({} +{})",
                                                    mutbl_str,
                                                    pprust::ty_to_string(&mut_ty.ty),
                                                    pprust::bounds_to_string(bounds)));
                    }
                    (&hir::TyRptr(Some(ref lt), ref mut_ty), Some(full_span)) => {
                        let mutbl_str = if mut_ty.mutbl == hir::MutMutable { "mut " } else { "" };
                        err.span_suggestion(full_span, "try adding parentheses (per RFC 438):",
                                            format!("&{} {}({} +{})",
                                                    pprust::lifetime_to_string(lt),
                                                    mutbl_str,
                                                    pprust::ty_to_string(&mut_ty.ty),
                                                    pprust::bounds_to_string(bounds)));
                    }

                    _ => {
                        help!(&mut err,
                                   "perhaps you forgot parentheses? (per RFC 438)");
                    }
                }
                err.emit();
                Err(ErrorReported)
            }
        }
    }

    fn trait_ref_to_object_type(&self,
                                rscope: &RegionScope,
                                span: Span,
                                trait_ref: ty::PolyTraitRef<'tcx>,
                                projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
                                bounds: &[hir::TyParamBound])
                                -> Ty<'tcx>
    {
        let existential_bounds = self.conv_existential_bounds(rscope,
                                                              span,
                                                              trait_ref.clone(),
                                                              projection_bounds,
                                                              bounds);

        let result = self.make_object_type(span, trait_ref, existential_bounds);
        debug!("trait_ref_to_object_type: result={:?}",
               result);

        result
    }

    fn make_object_type(&self,
                        span: Span,
                        principal: ty::PolyTraitRef<'tcx>,
                        bounds: ty::ExistentialBounds<'tcx>)
                        -> Ty<'tcx> {
        let tcx = self.tcx();
        let object = ty::TraitTy {
            principal: principal,
            bounds: bounds
        };
        let object_trait_ref =
            object.principal_trait_ref_with_self_ty(tcx, tcx.types.err);

        // ensure the super predicates and stop if we encountered an error
        if self.ensure_super_predicates(span, principal.def_id()).is_err() {
            return tcx.types.err;
        }

        // check that there are no gross object safety violations,
        // most importantly, that the supertraits don't contain Self,
        // to avoid ICE-s.
        let object_safety_violations =
            tcx.astconv_object_safety_violations(principal.def_id());
        if !object_safety_violations.is_empty() {
            tcx.report_object_safety_error(
                span, principal.def_id(), None, object_safety_violations)
                .unwrap().emit();
            return tcx.types.err;
        }

        let mut associated_types: FnvHashSet<(DefId, ast::Name)> =
            traits::supertraits(tcx, object_trait_ref)
            .flat_map(|tr| {
                let trait_def = tcx.lookup_trait_def(tr.def_id());
                trait_def.associated_type_names
                    .clone()
                    .into_iter()
                    .map(move |associated_type_name| (tr.def_id(), associated_type_name))
            })
            .collect();

        for projection_bound in &object.bounds.projection_bounds {
            let pair = (projection_bound.0.projection_ty.trait_ref.def_id,
                        projection_bound.0.projection_ty.item_name);
            associated_types.remove(&pair);
        }

        for (trait_def_id, name) in associated_types {
            span_err!(tcx.sess, span, E0191,
                "the value of the associated type `{}` (from the trait `{}`) must be specified",
                        name,
                        tcx.item_path_str(trait_def_id));
        }

        tcx.mk_trait(object.principal, object.bounds)
    }

    fn report_ambiguous_associated_type(&self,
                                        span: Span,
                                        type_str: &str,
                                        trait_str: &str,
                                        name: &str) {
        span_err!(self.tcx().sess, span, E0223,
                  "ambiguous associated type; specify the type using the syntax \
                   `<{} as {}>::{}`",
                  type_str, trait_str, name);
    }

    // Search for a bound on a type parameter which includes the associated item
    // given by assoc_name. ty_param_node_id is the node id for the type parameter
    // (which might be `Self`, but only if it is the `Self` of a trait, not an
    // impl). This function will fail if there are no suitable bounds or there is
    // any ambiguity.
    fn find_bound_for_assoc_item(&self,
                                 ty_param_node_id: ast::NodeId,
                                 ty_param_name: ast::Name,
                                 assoc_name: ast::Name,
                                 span: Span)
                                 -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
    {
        let tcx = self.tcx();

        let bounds = match self.get_type_parameter_bounds(span, ty_param_node_id) {
            Ok(v) => v,
            Err(ErrorReported) => {
                return Err(ErrorReported);
            }
        };

        // Ensure the super predicates and stop if we encountered an error.
        if bounds.iter().any(|b| self.ensure_super_predicates(span, b.def_id()).is_err()) {
            return Err(ErrorReported);
        }

        // Check that there is exactly one way to find an associated type with the
        // correct name.
        let suitable_bounds: Vec<_> =
            traits::transitive_bounds(tcx, &bounds)
            .filter(|b| self.trait_defines_associated_type_named(b.def_id(), assoc_name))
            .collect();

        self.one_bound_for_assoc_type(suitable_bounds,
                                      &ty_param_name.as_str(),
                                      &assoc_name.as_str(),
                                      span)
    }


    // Checks that bounds contains exactly one element and reports appropriate
    // errors otherwise.
    fn one_bound_for_assoc_type(&self,
                                bounds: Vec<ty::PolyTraitRef<'tcx>>,
                                ty_param_name: &str,
                                assoc_name: &str,
                                span: Span)
        -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
    {
        if bounds.is_empty() {
            span_err!(self.tcx().sess, span, E0220,
                      "associated type `{}` not found for `{}`",
                      assoc_name,
                      ty_param_name);
            return Err(ErrorReported);
        }

        if bounds.len() > 1 {
            let mut err = struct_span_err!(self.tcx().sess, span, E0221,
                                           "ambiguous associated type `{}` in bounds of `{}`",
                                           assoc_name,
                                           ty_param_name);

            for bound in &bounds {
                span_note!(&mut err, span,
                           "associated type `{}` could derive from `{}`",
                           ty_param_name,
                           bound);
            }
            err.emit();
        }

        Ok(bounds[0].clone())
    }

    // Create a type from a path to an associated type.
    // For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C
    // and item_segment is the path segment for D. We return a type and a def for
    // the whole path.
    // Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type
    // parameter or Self.
    fn associated_path_def_to_ty(&self,
                                 span: Span,
                                 ty: Ty<'tcx>,
                                 ty_path_def: Def,
                                 item_segment: &hir::PathSegment)
                                 -> (Ty<'tcx>, Def)
    {
        let tcx = self.tcx();
        let assoc_name = item_segment.name;

        debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name);

        tcx.prohibit_type_params(slice::ref_slice(item_segment));

        // Find the type of the associated item, and the trait where the associated
        // item is declared.
        let bound = match (&ty.sty, ty_path_def) {
            (_, Def::SelfTy(Some(trait_did), Some(impl_id))) => {
                // For Def::SelfTy() values inlined from another crate, the
                // impl_id will be DUMMY_NODE_ID, which would cause problems
                // here. But we should never run into an impl from another crate
                // in this pass.
                assert!(impl_id != ast::DUMMY_NODE_ID);

                // `Self` in an impl of a trait - we have a concrete self type and a
                // trait reference.
                let trait_ref = tcx.impl_trait_ref(tcx.map.local_def_id(impl_id)).unwrap();
                let trait_ref = if let Some(free_substs) = self.get_free_substs() {
                    trait_ref.subst(tcx, free_substs)
                } else {
                    trait_ref
                };

                if self.ensure_super_predicates(span, trait_did).is_err() {
                    return (tcx.types.err, Def::Err);
                }

                let candidates: Vec<ty::PolyTraitRef> =
                    traits::supertraits(tcx, ty::Binder(trait_ref))
                    .filter(|r| self.trait_defines_associated_type_named(r.def_id(),
                                                                         assoc_name))
                    .collect();

                match self.one_bound_for_assoc_type(candidates,
                                                    "Self",
                                                    &assoc_name.as_str(),
                                                    span) {
                    Ok(bound) => bound,
                    Err(ErrorReported) => return (tcx.types.err, Def::Err),
                }
            }
            (&ty::TyParam(_), Def::SelfTy(Some(trait_did), None)) => {
                let trait_node_id = tcx.map.as_local_node_id(trait_did).unwrap();
                match self.find_bound_for_assoc_item(trait_node_id,
                                                     keywords::SelfType.name(),
                                                     assoc_name,
                                                     span) {
                    Ok(bound) => bound,
                    Err(ErrorReported) => return (tcx.types.err, Def::Err),
                }
            }
            (&ty::TyParam(_), Def::TyParam(_, _, param_did, param_name)) => {
                let param_node_id = tcx.map.as_local_node_id(param_did).unwrap();
                match self.find_bound_for_assoc_item(param_node_id,
                                                     param_name,
                                                     assoc_name,
                                                     span) {
                    Ok(bound) => bound,
                    Err(ErrorReported) => return (tcx.types.err, Def::Err),
                }
            }
            _ => {
                self.report_ambiguous_associated_type(span,
                                                      &ty.to_string(),
                                                      "Trait",
                                                      &assoc_name.as_str());
                return (tcx.types.err, Def::Err);
            }
        };

        let trait_did = bound.0.def_id;
        let ty = self.projected_ty_from_poly_trait_ref(span, bound, assoc_name);

        let item_did = if let Some(trait_id) = tcx.map.as_local_node_id(trait_did) {
            // `ty::trait_items` used below requires information generated
            // by type collection, which may be in progress at this point.
            match tcx.map.expect_item(trait_id).node {
                hir::ItemTrait(_, _, _, ref trait_items) => {
                    let item = trait_items.iter()
                                          .find(|i| i.name == assoc_name)
                                          .expect("missing associated type");
                    tcx.map.local_def_id(item.id)
                }
                _ => bug!()
            }
        } else {
            let trait_items = tcx.trait_items(trait_did);
            let item = trait_items.iter().find(|i| i.name() == assoc_name);
            item.expect("missing associated type").def_id()
        };

        (ty, Def::AssociatedTy(trait_did, item_did))
    }

    fn qpath_to_ty(&self,
                   rscope: &RegionScope,
                   span: Span,
                   param_mode: PathParamMode,
                   opt_self_ty: Option<Ty<'tcx>>,
                   trait_def_id: DefId,
                   trait_segment: &hir::PathSegment,
                   item_segment: &hir::PathSegment)
                   -> Ty<'tcx>
    {
        let tcx = self.tcx();

        tcx.prohibit_type_params(slice::ref_slice(item_segment));

        let self_ty = if let Some(ty) = opt_self_ty {
            ty
        } else {
            let path_str = tcx.item_path_str(trait_def_id);
            self.report_ambiguous_associated_type(span,
                                                  "Type",
                                                  &path_str,
                                                  &item_segment.name.as_str());
            return tcx.types.err;
        };

        debug!("qpath_to_ty: self_type={:?}", self_ty);

        let trait_ref = self.ast_path_to_mono_trait_ref(rscope,
                                                        span,
                                                        param_mode,
                                                        trait_def_id,
                                                        Some(self_ty),
                                                        trait_segment);

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

        self.projected_ty(span, trait_ref, item_segment.name)
    }

    /// Convert a type supplied as value for a type argument from AST into our
    /// our internal representation. This is the same as `ast_ty_to_ty` but that
    /// it applies the object lifetime default.
    ///
    /// # Parameters
    ///
    /// * `this`, `rscope`: the surrounding context
    /// * `decl_generics`: the generics of the struct/enum/trait declaration being
    ///   referenced
    /// * `index`: the index of the type parameter being instantiated from the list
    ///   (we assume it is in the `TypeSpace`)
    /// * `region_substs`: a partial substitution consisting of
    ///   only the region type parameters being supplied to this type.
    /// * `ast_ty`: the ast representation of the type being supplied
    pub fn ast_ty_arg_to_ty(&self,
                            rscope: &RegionScope,
                            decl_generics: &ty::Generics<'tcx>,
                            index: usize,
                            region_substs: &Substs<'tcx>,
                            ast_ty: &hir::Ty)
                            -> Ty<'tcx>
    {
        let tcx = self.tcx();

        if let Some(def) = decl_generics.types.opt_get(TypeSpace, index) {
            let object_lifetime_default = def.object_lifetime_default.subst(tcx, region_substs);
            let rscope1 = &ObjectLifetimeDefaultRscope::new(rscope, object_lifetime_default);
            self.ast_ty_to_ty(rscope1, ast_ty)
        } else {
            self.ast_ty_to_ty(rscope, ast_ty)
        }
    }

    // Check the base def in a PathResolution and convert it to a Ty. If there are
    // associated types in the PathResolution, these will need to be separately
    // resolved.
    fn base_def_to_ty(&self,
                      rscope: &RegionScope,
                      span: Span,
                      param_mode: PathParamMode,
                      def: Def,
                      opt_self_ty: Option<Ty<'tcx>>,
                      base_path_ref_id: ast::NodeId,
                      base_segments: &[hir::PathSegment])
                      -> Ty<'tcx> {
        let tcx = self.tcx();

        debug!("base_def_to_ty(def={:?}, opt_self_ty={:?}, base_segments={:?})",
               def, opt_self_ty, base_segments);

        match def {
            Def::Trait(trait_def_id) => {
                // N.B. this case overlaps somewhat with
                // TyObjectSum, see that fn for details
                let mut projection_bounds = Vec::new();

                let trait_ref =
                    self.object_path_to_poly_trait_ref(rscope,
                                                       span,
                                                       param_mode,
                                                       trait_def_id,
                                                       base_path_ref_id,
                                                       base_segments.last().unwrap(),
                                                       &mut projection_bounds);

                tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
                self.trait_ref_to_object_type(rscope,
                                              span,
                                              trait_ref,
                                              projection_bounds,
                                              &[])
            }
            Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => {
                tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
                self.ast_path_to_ty(rscope,
                                    span,
                                    param_mode,
                                    did,
                                    base_segments.last().unwrap())
            }
            Def::TyParam(space, index, _, name) => {
                tcx.prohibit_type_params(base_segments);
                tcx.mk_param(space, index, name)
            }
            Def::SelfTy(_, Some(impl_id)) => {
                // Self in impl (we know the concrete type).

                // For Def::SelfTy() values inlined from another crate, the
                // impl_id will be DUMMY_NODE_ID, which would cause problems
                // here. But we should never run into an impl from another crate
                // in this pass.
                assert!(impl_id != ast::DUMMY_NODE_ID);

                tcx.prohibit_type_params(base_segments);
                let ty = tcx.node_id_to_type(impl_id);
                if let Some(free_substs) = self.get_free_substs() {
                    ty.subst(tcx, free_substs)
                } else {
                    ty
                }
            }
            Def::SelfTy(Some(_), None) => {
                // Self in trait.
                tcx.prohibit_type_params(base_segments);
                tcx.mk_self_type()
            }
            Def::AssociatedTy(trait_did, _) => {
                tcx.prohibit_type_params(&base_segments[..base_segments.len()-2]);
                self.qpath_to_ty(rscope,
                                 span,
                                 param_mode,
                                 opt_self_ty,
                                 trait_did,
                                 &base_segments[base_segments.len()-2],
                                 base_segments.last().unwrap())
            }
            Def::Mod(..) => {
                // Used as sentinel by callers to indicate the `<T>::A::B::C` form.
                // FIXME(#22519) This part of the resolution logic should be
                // avoided entirely for that form, once we stop needed a Def
                // for `associated_path_def_to_ty`.
                // Fixing this will also let use resolve <Self>::Foo the same way we
                // resolve Self::Foo, at the moment we can't resolve the former because
                // we don't have the trait information around, which is just sad.

                assert!(base_segments.is_empty());

                opt_self_ty.expect("missing T in <T>::a::b::c")
            }
            Def::PrimTy(prim_ty) => {
                tcx.prim_ty_to_ty(base_segments, prim_ty)
            }
            Def::Err => {
                self.set_tainted_by_errors();
                return self.tcx().types.err;
            }
            _ => {
                span_err!(tcx.sess, span, E0248,
                          "found value `{}` used as a type",
                          tcx.item_path_str(def.def_id()));
                return self.tcx().types.err;
            }
        }
    }

    // Resolve possibly associated type path into a type and final definition.
    // Note that both base_segments and assoc_segments may be empty, although not at same time.
    pub fn finish_resolving_def_to_ty(&self,
                                      rscope: &RegionScope,
                                      span: Span,
                                      param_mode: PathParamMode,
                                      base_def: Def,
                                      opt_self_ty: Option<Ty<'tcx>>,
                                      base_path_ref_id: ast::NodeId,
                                      base_segments: &[hir::PathSegment],
                                      assoc_segments: &[hir::PathSegment])
                                      -> (Ty<'tcx>, Def) {
        // Convert the base type.
        debug!("finish_resolving_def_to_ty(base_def={:?}, \
                base_segments={:?}, \
                assoc_segments={:?})",
               base_def,
               base_segments,
               assoc_segments);
        let base_ty = self.base_def_to_ty(rscope,
                                          span,
                                          param_mode,
                                          base_def,
                                          opt_self_ty,
                                          base_path_ref_id,
                                          base_segments);
        debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", base_ty);

        // If any associated type segments remain, attempt to resolve them.
        let (mut ty, mut def) = (base_ty, base_def);
        for segment in assoc_segments {
            debug!("finish_resolving_def_to_ty: segment={:?}", segment);
            // This is pretty bad (it will fail except for T::A and Self::A).
            let (new_ty, new_def) = self.associated_path_def_to_ty(span, ty, def, segment);
            ty = new_ty;
            def = new_def;

            if def == Def::Err {
                break;
            }
        }
        (ty, def)
    }

    /// Parses the programmer's textual representation of a type into our
    /// internal notion of a type.
    pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
        debug!("ast_ty_to_ty(id={:?}, ast_ty={:?})",
               ast_ty.id, ast_ty);

        let tcx = self.tcx();

        let cache = self.ast_ty_to_ty_cache();
        match cache.borrow().get(&ast_ty.id) {
            Some(ty) => { return ty; }
            None => { }
        }

        let result_ty = match ast_ty.node {
            hir::TyVec(ref ty) => {
                tcx.mk_slice(self.ast_ty_to_ty(rscope, &ty))
            }
            hir::TyObjectSum(ref ty, ref bounds) => {
                match self.ast_ty_to_trait_ref(rscope, &ty, bounds) {
                    Ok((trait_ref, projection_bounds)) => {
                        self.trait_ref_to_object_type(rscope,
                                                      ast_ty.span,
                                                      trait_ref,
                                                      projection_bounds,
                                                      bounds)
                    }
                    Err(ErrorReported) => {
                        self.tcx().types.err
                    }
                }
            }
            hir::TyPtr(ref mt) => {
                tcx.mk_ptr(ty::TypeAndMut {
                    ty: self.ast_ty_to_ty(rscope, &mt.ty),
                    mutbl: mt.mutbl
                })
            }
            hir::TyRptr(ref region, ref mt) => {
                let r = self.opt_ast_region_to_region(rscope, ast_ty.span, region);
                debug!("TyRef r={:?}", r);
                let rscope1 =
                    &ObjectLifetimeDefaultRscope::new(
                        rscope,
                        ty::ObjectLifetimeDefault::Specific(r));
                let t = self.ast_ty_to_ty(rscope1, &mt.ty);
                tcx.mk_ref(tcx.mk_region(r), ty::TypeAndMut {ty: t, mutbl: mt.mutbl})
            }
            hir::TyTup(ref fields) => {
                let flds = fields.iter()
                                 .map(|t| self.ast_ty_to_ty(rscope, &t))
                                 .collect();
                tcx.mk_tup(flds)
            }
            hir::TyBareFn(ref bf) => {
                require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
                let bare_fn_ty = self.ty_of_bare_fn(bf.unsafety, bf.abi, &bf.decl);

                // Find any late-bound regions declared in return type that do
                // not appear in the arguments. These are not wellformed.
                //
                // Example:
                //
                //     for<'a> fn() -> &'a str <-- 'a is bad
                //     for<'a> fn(&'a String) -> &'a str <-- 'a is ok
                //
                // Note that we do this check **here** and not in
                // `ty_of_bare_fn` because the latter is also used to make
                // the types for fn items, and we do not want to issue a
                // warning then. (Once we fix #32330, the regions we are
                // checking for here would be considered early bound
                // anyway.)
                let inputs = bare_fn_ty.sig.inputs();
                let late_bound_in_args = tcx.collect_constrained_late_bound_regions(&inputs);
                let output = bare_fn_ty.sig.output();
                let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(&output);
                for br in late_bound_in_ret.difference(&late_bound_in_args) {
                    let br_name = match *br {
                        ty::BrNamed(_, name, _) => name,
                        _ => {
                            span_bug!(
                                bf.decl.output.span(),
                                "anonymous bound region {:?} in return but not args",
                                br);
                        }
                    };
                    tcx.sess.add_lint(
                        lint::builtin::HR_LIFETIME_IN_ASSOC_TYPE,
                        ast_ty.id,
                        ast_ty.span,
                        format!("return type references lifetime `{}`, \
                                 which does not appear in the trait input types",
                                br_name));
                }
                tcx.mk_fn_ptr(bare_fn_ty)
            }
            hir::TyPolyTraitRef(ref bounds) => {
                self.conv_ty_poly_trait_ref(rscope, ast_ty.span, bounds)
            }
            hir::TyPath(ref maybe_qself, ref path) => {
                debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
                let path_res = tcx.expect_resolution(ast_ty.id);
                let base_ty_end = path.segments.len() - path_res.depth;
                let opt_self_ty = maybe_qself.as_ref().map(|qself| {
                    self.ast_ty_to_ty(rscope, &qself.ty)
                });
                let (ty, def) = self.finish_resolving_def_to_ty(rscope,
                                                                ast_ty.span,
                                                                PathParamMode::Explicit,
                                                                path_res.base_def,
                                                                opt_self_ty,
                                                                ast_ty.id,
                                                                &path.segments[..base_ty_end],
                                                                &path.segments[base_ty_end..]);

                // Write back the new resolution.
                if path_res.depth != 0 {
                    tcx.def_map.borrow_mut().insert(ast_ty.id, PathResolution::new(def));
                }

                ty
            }
            hir::TyFixedLengthVec(ref ty, ref e) => {
                if let Ok(length) = eval_length(tcx.global_tcx(), &e, "array length") {
                    tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), length)
                } else {
                    self.tcx().types.err
                }
            }
            hir::TyTypeof(ref _e) => {
                span_err!(tcx.sess, ast_ty.span, E0516,
                      "`typeof` is a reserved keyword but unimplemented");
                tcx.types.err
            }
            hir::TyInfer => {
                // TyInfer also appears as the type of arguments or return
                // values in a ExprClosure, or as
                // the type of local variables. Both of these cases are
                // handled specially and will not descend into this routine.
                self.ty_infer(None, None, None, ast_ty.span)
            }
        };

        cache.borrow_mut().insert(ast_ty.id, result_ty);

        result_ty
    }

    pub fn ty_of_arg(&self,
                     rscope: &RegionScope,
                     a: &hir::Arg,
                     expected_ty: Option<Ty<'tcx>>)
                     -> Ty<'tcx>
    {
        match a.ty.node {
            hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
            hir::TyInfer => self.ty_infer(None, None, None, a.ty.span),
            _ => self.ast_ty_to_ty(rscope, &a.ty),
        }
    }

    pub fn ty_of_method(&self,
                        sig: &hir::MethodSig,
                        untransformed_self_ty: Ty<'tcx>)
                        -> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
        let (bare_fn_ty, optional_explicit_self_category) =
            self.ty_of_method_or_bare_fn(sig.unsafety,
                                         sig.abi,
                                         Some(untransformed_self_ty),
                                         &sig.decl);
        (bare_fn_ty, optional_explicit_self_category)
    }

    pub fn ty_of_bare_fn(&self,
                         unsafety: hir::Unsafety,
                         abi: abi::Abi,
                         decl: &hir::FnDecl)
                         -> &'tcx ty::BareFnTy<'tcx> {
        self.ty_of_method_or_bare_fn(unsafety, abi, None, decl).0
    }

    fn ty_of_method_or_bare_fn<'a>(&self,
                                   unsafety: hir::Unsafety,
                                   abi: abi::Abi,
                                   opt_untransformed_self_ty: Option<Ty<'tcx>>,
                                   decl: &hir::FnDecl)
                                   -> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory)
    {
        debug!("ty_of_method_or_bare_fn");

        // New region names that appear inside of the arguments of the function
        // declaration are bound to that function type.
        let rb = rscope::BindingRscope::new();

        // `implied_output_region` is the region that will be assumed for any
        // region parameters in the return type. In accordance with the rules for
        // lifetime elision, we can determine it in two ways. First (determined
        // here), if self is by-reference, then the implied output region is the
        // region of the self parameter.
        let (self_ty, explicit_self_category) = match (opt_untransformed_self_ty, decl.get_self()) {
            (Some(untransformed_self_ty), Some(explicit_self)) => {
                let self_type = self.determine_self_type(&rb, untransformed_self_ty,
                                                         &explicit_self);
                (Some(self_type.0), self_type.1)
            }
            _ => (None, ty::ExplicitSelfCategory::Static),
        };

        // HACK(eddyb) replace the fake self type in the AST with the actual type.
        let arg_params = if self_ty.is_some() {
            &decl.inputs[1..]
        } else {
            &decl.inputs[..]
        };
        let arg_tys: Vec<Ty> =
            arg_params.iter().map(|a| self.ty_of_arg(&rb, a, None)).collect();
        let arg_pats: Vec<String> =
            arg_params.iter().map(|a| pprust::pat_to_string(&a.pat)).collect();

        // Second, if there was exactly one lifetime (either a substitution or a
        // reference) in the arguments, then any anonymous regions in the output
        // have that lifetime.
        let implied_output_region = match explicit_self_category {
            ty::ExplicitSelfCategory::ByReference(region, _) => Ok(region),
            _ => self.find_implied_output_region(&arg_tys, arg_pats)
        };

        let output_ty = match decl.output {
            hir::Return(ref output) =>
                ty::FnConverging(self.convert_ty_with_lifetime_elision(implied_output_region,
                                                                       &output)),
            hir::DefaultReturn(..) => ty::FnConverging(self.tcx().mk_nil()),
            hir::NoReturn(..) => ty::FnDiverging
        };

        (self.tcx().mk_bare_fn(ty::BareFnTy {
            unsafety: unsafety,
            abi: abi,
            sig: ty::Binder(ty::FnSig {
                inputs: self_ty.into_iter().chain(arg_tys).collect(),
                output: output_ty,
                variadic: decl.variadic
            }),
        }), explicit_self_category)
    }

    fn determine_self_type<'a>(&self,
                               rscope: &RegionScope,
                               untransformed_self_ty: Ty<'tcx>,
                               explicit_self: &hir::ExplicitSelf)
                               -> (Ty<'tcx>, ty::ExplicitSelfCategory)
    {
        return match explicit_self.node {
            SelfKind::Value(..) => {
                (untransformed_self_ty, ty::ExplicitSelfCategory::ByValue)
            }
            SelfKind::Region(ref lifetime, mutability) => {
                let region =
                    self.opt_ast_region_to_region(
                                             rscope,
                                             explicit_self.span,
                                             lifetime);
                (self.tcx().mk_ref(
                    self.tcx().mk_region(region),
                    ty::TypeAndMut {
                        ty: untransformed_self_ty,
                        mutbl: mutability
                    }),
                 ty::ExplicitSelfCategory::ByReference(region, mutability))
            }
            SelfKind::Explicit(ref ast_type, _) => {
                let explicit_type = self.ast_ty_to_ty(rscope, &ast_type);

                // We wish to (for now) categorize an explicit self
                // declaration like `self: SomeType` into either `self`,
                // `&self`, `&mut self`, or `Box<self>`. We do this here
                // by some simple pattern matching. A more precise check
                // is done later in `check_method_self_type()`.
                //
                // Examples:
                //
                // ```
                // impl Foo for &T {
                //     // Legal declarations:
                //     fn method1(self: &&T); // ExplicitSelfCategory::ByReference
                //     fn method2(self: &T); // ExplicitSelfCategory::ByValue
                //     fn method3(self: Box<&T>); // ExplicitSelfCategory::ByBox
                //
                //     // Invalid cases will be caught later by `check_method_self_type`:
                //     fn method_err1(self: &mut T); // ExplicitSelfCategory::ByReference
                // }
                // ```
                //
                // To do the check we just count the number of "modifiers"
                // on each type and compare them. If they are the same or
                // the impl has more, we call it "by value". Otherwise, we
                // look at the outermost modifier on the method decl and
                // call it by-ref, by-box as appropriate. For method1, for
                // example, the impl type has one modifier, but the method
                // type has two, so we end up with
                // ExplicitSelfCategory::ByReference.

                let impl_modifiers = count_modifiers(untransformed_self_ty);
                let method_modifiers = count_modifiers(explicit_type);

                debug!("determine_explicit_self_category(self_info.untransformed_self_ty={:?} \
                       explicit_type={:?} \
                       modifiers=({},{})",
                       untransformed_self_ty,
                       explicit_type,
                       impl_modifiers,
                       method_modifiers);

                let category = if impl_modifiers >= method_modifiers {
                    ty::ExplicitSelfCategory::ByValue
                } else {
                    match explicit_type.sty {
                        ty::TyRef(r, mt) => ty::ExplicitSelfCategory::ByReference(*r, mt.mutbl),
                        ty::TyBox(_) => ty::ExplicitSelfCategory::ByBox,
                        _ => ty::ExplicitSelfCategory::ByValue,
                    }
                };

                (explicit_type, category)
            }
        };

        fn count_modifiers(ty: Ty) -> usize {
            match ty.sty {
                ty::TyRef(_, mt) => count_modifiers(mt.ty) + 1,
                ty::TyBox(t) => count_modifiers(t) + 1,
                _ => 0,
            }
        }
    }

    pub fn ty_of_closure(&self,
        unsafety: hir::Unsafety,
        decl: &hir::FnDecl,
        abi: abi::Abi,
        expected_sig: Option<ty::FnSig<'tcx>>)
        -> ty::ClosureTy<'tcx>
    {
        debug!("ty_of_closure(expected_sig={:?})",
               expected_sig);

        // new region names that appear inside of the fn decl are bound to
        // that function type
        let rb = rscope::BindingRscope::new();

        let input_tys: Vec<_> = decl.inputs.iter().enumerate().map(|(i, a)| {
            let expected_arg_ty = expected_sig.as_ref().and_then(|e| {
                // no guarantee that the correct number of expected args
                // were supplied
                if i < e.inputs.len() {
                    Some(e.inputs[i])
                } else {
                    None
                }
            });
            self.ty_of_arg(&rb, a, expected_arg_ty)
        }).collect();

        let expected_ret_ty = expected_sig.map(|e| e.output);

        let is_infer = match decl.output {
            hir::Return(ref output) if output.node == hir::TyInfer => true,
            hir::DefaultReturn(..) => true,
            _ => false
        };

        let output_ty = match decl.output {
            _ if is_infer && expected_ret_ty.is_some() =>
                expected_ret_ty.unwrap(),
            _ if is_infer =>
                ty::FnConverging(self.ty_infer(None, None, None, decl.output.span())),
            hir::Return(ref output) =>
                ty::FnConverging(self.ast_ty_to_ty(&rb, &output)),
            hir::DefaultReturn(..) => bug!(),
            hir::NoReturn(..) => ty::FnDiverging
        };

        debug!("ty_of_closure: input_tys={:?}", input_tys);
        debug!("ty_of_closure: output_ty={:?}", output_ty);

        ty::ClosureTy {
            unsafety: unsafety,
            abi: abi,
            sig: ty::Binder(ty::FnSig {inputs: input_tys,
                                       output: output_ty,
                                       variadic: decl.variadic}),
        }
    }

    /// Given an existential type like `Foo+'a+Bar`, this routine converts
    /// the `'a` and `Bar` intos an `ExistentialBounds` struct.
    /// The `main_trait_refs` argument specifies the `Foo` -- it is absent
    /// for closures. Eventually this should all be normalized, I think,
    /// so that there is no "main trait ref" and instead we just have a flat
    /// list of bounds as the existential type.
    fn conv_existential_bounds(&self,
        rscope: &RegionScope,
        span: Span,
        principal_trait_ref: ty::PolyTraitRef<'tcx>,
        projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
        ast_bounds: &[hir::TyParamBound])
        -> ty::ExistentialBounds<'tcx>
    {
        let partitioned_bounds =
            partition_bounds(self.tcx(), span, ast_bounds);

        self.conv_existential_bounds_from_partitioned_bounds(
            rscope, span, principal_trait_ref, projection_bounds, partitioned_bounds)
    }

    fn conv_ty_poly_trait_ref(&self,
        rscope: &RegionScope,
        span: Span,
        ast_bounds: &[hir::TyParamBound])
        -> Ty<'tcx>
    {
        let mut partitioned_bounds = partition_bounds(self.tcx(), span, &ast_bounds[..]);

        let mut projection_bounds = Vec::new();
        let main_trait_bound = if !partitioned_bounds.trait_bounds.is_empty() {
            let trait_bound = partitioned_bounds.trait_bounds.remove(0);
            self.instantiate_poly_trait_ref(rscope,
                                            trait_bound,
                                            None,
                                            &mut projection_bounds)
        } else {
            span_err!(self.tcx().sess, span, E0224,
                      "at least one non-builtin trait is required for an object type");
            return self.tcx().types.err;
        };

        let bounds =
            self.conv_existential_bounds_from_partitioned_bounds(rscope,
                                                                 span,
                                                                 main_trait_bound.clone(),
                                                                 projection_bounds,
                                                                 partitioned_bounds);

        self.make_object_type(span, main_trait_bound, bounds)
    }

    pub fn conv_existential_bounds_from_partitioned_bounds(&self,
        rscope: &RegionScope,
        span: Span,
        principal_trait_ref: ty::PolyTraitRef<'tcx>,
        projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>, // Empty for boxed closures
        partitioned_bounds: PartitionedBounds)
        -> ty::ExistentialBounds<'tcx>
    {
        let PartitionedBounds { builtin_bounds,
                                trait_bounds,
                                region_bounds } =
            partitioned_bounds;

        if !trait_bounds.is_empty() {
            let b = &trait_bounds[0];
            span_err!(self.tcx().sess, b.trait_ref.path.span, E0225,
                      "only the builtin traits can be used as closure or object bounds");
        }

        let region_bound =
            self.compute_object_lifetime_bound(span,
                                               &region_bounds,
                                               principal_trait_ref,
                                               builtin_bounds);

        let region_bound = match region_bound {
            Some(r) => r,
            None => {
                match rscope.object_lifetime_default(span) {
                    Some(r) => r,
                    None => {
                        span_err!(self.tcx().sess, span, E0228,
                                  "the lifetime bound for this object type cannot be deduced \
                                   from context; please supply an explicit bound");
                        ty::ReStatic
                    }
                }
            }
        };

        debug!("region_bound: {:?}", region_bound);

        ty::ExistentialBounds::new(region_bound, builtin_bounds, projection_bounds)
    }

    /// Given the bounds on an object, determines what single region bound (if any) we can
    /// use to summarize this type. The basic idea is that we will use the bound the user
    /// provided, if they provided one, and otherwise search the supertypes of trait bounds
    /// for region bounds. It may be that we can derive no bound at all, in which case
    /// we return `None`.
    fn compute_object_lifetime_bound(&self,
        span: Span,
        explicit_region_bounds: &[&hir::Lifetime],
        principal_trait_ref: ty::PolyTraitRef<'tcx>,
        builtin_bounds: ty::BuiltinBounds)
        -> Option<ty::Region> // if None, use the default
    {
        let tcx = self.tcx();

        debug!("compute_opt_region_bound(explicit_region_bounds={:?}, \
               principal_trait_ref={:?}, builtin_bounds={:?})",
               explicit_region_bounds,
               principal_trait_ref,
               builtin_bounds);

        if explicit_region_bounds.len() > 1 {
            span_err!(tcx.sess, explicit_region_bounds[1].span, E0226,
                "only a single explicit lifetime bound is permitted");
        }

        if !explicit_region_bounds.is_empty() {
            // Explicitly specified region bound. Use that.
            let r = explicit_region_bounds[0];
            return Some(ast_region_to_region(tcx, r));
        }

        if let Err(ErrorReported) =
                self.ensure_super_predicates(span, principal_trait_ref.def_id()) {
            return Some(ty::ReStatic);
        }

        // No explicit region bound specified. Therefore, examine trait
        // bounds and see if we can derive region bounds from those.
        let derived_region_bounds =
            object_region_bounds(tcx, &principal_trait_ref, builtin_bounds);

        // If there are no derived region bounds, then report back that we
        // can find no region bound. The caller will use the default.
        if derived_region_bounds.is_empty() {
            return None;
        }

        // If any of the derived region bounds are 'static, that is always
        // the best choice.
        if derived_region_bounds.iter().any(|r| ty::ReStatic == *r) {
            return Some(ty::ReStatic);
        }

        // Determine whether there is exactly one unique region in the set
        // of derived region bounds. If so, use that. Otherwise, report an
        // error.
        let r = derived_region_bounds[0];
        if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
            span_err!(tcx.sess, span, E0227,
                      "ambiguous lifetime bound, explicit lifetime bound required");
        }
        return Some(r);
    }
}

pub struct PartitionedBounds<'a> {
    pub builtin_bounds: ty::BuiltinBounds,
    pub trait_bounds: Vec<&'a hir::PolyTraitRef>,
    pub region_bounds: Vec<&'a hir::Lifetime>,
}

/// Divides a list of bounds from the AST into three groups: builtin bounds (Copy, Sized etc),
/// general trait bounds, and region bounds.
pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                            _span: Span,
                                            ast_bounds: &'b [hir::TyParamBound])
                                            -> PartitionedBounds<'b>
{
    let mut builtin_bounds = ty::BuiltinBounds::empty();
    let mut region_bounds = Vec::new();
    let mut trait_bounds = Vec::new();
    for ast_bound in ast_bounds {
        match *ast_bound {
            hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => {
                match tcx.expect_def(b.trait_ref.ref_id) {
                    Def::Trait(trait_did) => {
                        if tcx.try_add_builtin_trait(trait_did,
                                                     &mut builtin_bounds) {
                            let segments = &b.trait_ref.path.segments;
                            let parameters = &segments[segments.len() - 1].parameters;
                            if !parameters.types().is_empty() {
                                check_type_argument_count(tcx, b.trait_ref.path.span,
                                                          parameters.types().len(), 0, 0);
                            }
                            if !parameters.lifetimes().is_empty() {
                                report_lifetime_number_error(tcx, b.trait_ref.path.span,
                                                             parameters.lifetimes().len(), 0);
                            }
                            continue; // success
                        }
                    }
                    _ => {
                        // Not a trait? that's an error, but it'll get
                        // reported later.
                    }
                }
                trait_bounds.push(b);
            }
            hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => {}
            hir::RegionTyParamBound(ref l) => {
                region_bounds.push(l);
            }
        }
    }

    PartitionedBounds {
        builtin_bounds: builtin_bounds,
        trait_bounds: trait_bounds,
        region_bounds: region_bounds,
    }
}

fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize,
                             required: usize, accepted: usize) {
    if supplied < required {
        let expected = if required < accepted {
            "expected at least"
        } else {
            "expected"
        };
        span_err!(tcx.sess, span, E0243,
                  "wrong number of type arguments: {} {}, found {}",
                  expected, required, supplied);
    } else if supplied > accepted {
        let expected = if required < accepted {
            "expected at most"
        } else {
            "expected"
        };
        span_err!(tcx.sess, span, E0244,
                  "wrong number of type arguments: {} {}, found {}",
                  expected,
                  accepted,
                  supplied);
    }
}

fn report_lifetime_number_error(tcx: TyCtxt, span: Span, number: usize, expected: usize) {
    span_err!(tcx.sess, span, E0107,
              "wrong number of lifetime parameters: expected {}, found {}",
              expected, number);
}

// A helper struct for conveniently grouping a set of bounds which we pass to
// and return from functions in multiple places.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Bounds<'tcx> {
    pub region_bounds: Vec<ty::Region>,
    pub builtin_bounds: ty::BuiltinBounds,
    pub trait_bounds: Vec<ty::PolyTraitRef<'tcx>>,
    pub projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
}

impl<'a, 'gcx, 'tcx> Bounds<'tcx> {
    pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>)
                      -> Vec<ty::Predicate<'tcx>>
    {
        let mut vec = Vec::new();

        for builtin_bound in &self.builtin_bounds {
            match tcx.trait_ref_for_builtin_bound(builtin_bound, param_ty) {
                Ok(trait_ref) => { vec.push(trait_ref.to_predicate()); }
                Err(ErrorReported) => { }
            }
        }

        for &region_bound in &self.region_bounds {
            // account for the binder being introduced below; no need to shift `param_ty`
            // because, at present at least, it can only refer to early-bound regions
            let region_bound = ty::fold::shift_region(region_bound, 1);
            vec.push(ty::Binder(ty::OutlivesPredicate(param_ty, region_bound)).to_predicate());
        }

        for bound_trait_ref in &self.trait_bounds {
            vec.push(bound_trait_ref.to_predicate());
        }

        for projection in &self.projection_bounds {
            vec.push(projection.to_predicate());
        }

        vec
    }
}
