// Type resolution: the phase that finds all the types in the AST with
// unresolved type variables and replaces "ty_var" types with their
// substitutions.

use crate::check::FnCtxt;
use errors::DiagnosticBuilder;
use rustc::hir;
use rustc::hir::def_id::{DefId, DefIndex};
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc::infer::InferCtxt;
use rustc::ty::adjustment::{Adjust, Adjustment, PointerCast};
use rustc::ty::fold::{TypeFoldable, TypeFolder};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::util::nodemap::DefIdSet;
use rustc_data_structures::sync::Lrc;
use std::mem;
use syntax::symbol::sym;
use syntax_pos::Span;

///////////////////////////////////////////////////////////////////////////
// Entry point

// During type inference, partially inferred types are
// represented using Type variables (ty::Infer). These don't appear in
// the final TypeckTables since all of the types should have been
// inferred once typeck_tables_of is done.
// When type inference is running however, having to update the typeck
// tables every time a new type is inferred would be unreasonably slow,
// so instead all of the replacement happens at the end in
// resolve_type_vars_in_body, which creates a new TypeTables which
// doesn't contain any inference types.
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
    pub fn resolve_type_vars_in_body(&self, body: &'tcx hir::Body) -> &'tcx ty::TypeckTables<'tcx> {
        let item_id = self.tcx.hir().body_owner(body.id());
        let item_def_id = self.tcx.hir().local_def_id(item_id);

        // This attribute causes us to dump some writeback information
        // in the form of errors, which is uSymbolfor unit tests.
        let rustc_dump_user_substs = self.tcx.has_attr(item_def_id, sym::rustc_dump_user_substs);

        let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_substs);
        for arg in &body.arguments {
            wbcx.visit_node_id(arg.pat.span, arg.hir_id);
        }
        // Type only exists for constants and statics, not functions.
        match self.tcx.hir().body_owner_kind(item_id) {
            hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => {
                wbcx.visit_node_id(body.value.span, item_id);
            }
            hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (),
        }
        wbcx.visit_body(body);
        wbcx.visit_upvar_capture_map();
        wbcx.visit_closures();
        wbcx.visit_liberated_fn_sigs();
        wbcx.visit_fru_field_types();
        wbcx.visit_opaque_types(body.value.span);
        wbcx.visit_coercion_casts();
        wbcx.visit_free_region_map();
        wbcx.visit_user_provided_tys();
        wbcx.visit_user_provided_sigs();

        let used_trait_imports = mem::replace(
            &mut self.tables.borrow_mut().used_trait_imports,
            Lrc::new(DefIdSet::default()),
        );
        debug!(
            "used_trait_imports({:?}) = {:?}",
            item_def_id, used_trait_imports
        );
        wbcx.tables.used_trait_imports = used_trait_imports;

        wbcx.tables.upvar_list = mem::replace(
            &mut self.tables.borrow_mut().upvar_list,
            Default::default(),
        );

        wbcx.tables.tainted_by_errors = self.is_tainted_by_errors();

        debug!(
            "writeback: tables for {:?} are {:#?}",
            item_def_id, wbcx.tables
        );

        self.tcx.arena.alloc(wbcx.tables)
    }
}

///////////////////////////////////////////////////////////////////////////
// The Writeback context. This visitor walks the AST, checking the
// fn-specific tables to find references to types or regions. It
// resolves those regions to remove inference variables and writes the
// final result back into the master tables in the tcx. Here and
// there, it applies a few ad-hoc checks that were not convenient to
// do elsewhere.

struct WritebackCx<'cx, 'tcx> {
    fcx: &'cx FnCtxt<'cx, 'tcx>,

    tables: ty::TypeckTables<'tcx>,

    body: &'tcx hir::Body,

    rustc_dump_user_substs: bool,
}

impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
    fn new(
        fcx: &'cx FnCtxt<'cx, 'tcx>,
        body: &'tcx hir::Body,
        rustc_dump_user_substs: bool,
    ) -> WritebackCx<'cx, 'tcx> {
        let owner = body.id().hir_id;

        WritebackCx {
            fcx,
            tables: ty::TypeckTables::empty(Some(DefId::local(owner.owner))),
            body,
            rustc_dump_user_substs,
        }
    }

    fn tcx(&self) -> TyCtxt<'tcx> {
        self.fcx.tcx
    }

    fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) {
        debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty);
        assert!(!ty.needs_infer() && !ty.has_placeholders());
        self.tables.node_types_mut().insert(hir_id, ty);
    }

    // Hacky hack: During type-checking, we treat *all* operators
    // as potentially overloaded. But then, during writeback, if
    // we observe that something like `a+b` is (known to be)
    // operating on scalars, we clear the overload.
    fn fix_scalar_builtin_expr(&mut self, e: &hir::Expr) {
        match e.node {
            hir::ExprKind::Unary(hir::UnNeg, ref inner)
            | hir::ExprKind::Unary(hir::UnNot, ref inner) => {
                let inner_ty = self.fcx.node_ty(inner.hir_id);
                let inner_ty = self.fcx.resolve_vars_if_possible(&inner_ty);

                if inner_ty.is_scalar() {
                    let mut tables = self.fcx.tables.borrow_mut();
                    tables.type_dependent_defs_mut().remove(e.hir_id);
                    tables.node_substs_mut().remove(e.hir_id);
                }
            }
            hir::ExprKind::Binary(ref op, ref lhs, ref rhs)
            | hir::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => {
                let lhs_ty = self.fcx.node_ty(lhs.hir_id);
                let lhs_ty = self.fcx.resolve_vars_if_possible(&lhs_ty);

                let rhs_ty = self.fcx.node_ty(rhs.hir_id);
                let rhs_ty = self.fcx.resolve_vars_if_possible(&rhs_ty);

                if lhs_ty.is_scalar() && rhs_ty.is_scalar() {
                    let mut tables = self.fcx.tables.borrow_mut();
                    tables.type_dependent_defs_mut().remove(e.hir_id);
                    tables.node_substs_mut().remove(e.hir_id);

                    match e.node {
                        hir::ExprKind::Binary(..) => {
                            if !op.node.is_by_value() {
                                let mut adjustments = tables.adjustments_mut();
                                adjustments.get_mut(lhs.hir_id).map(|a| a.pop());
                                adjustments.get_mut(rhs.hir_id).map(|a| a.pop());
                            }
                        }
                        hir::ExprKind::AssignOp(..) => {
                            tables
                                .adjustments_mut()
                                .get_mut(lhs.hir_id)
                                .map(|a| a.pop());
                        }
                        _ => {}
                    }
                }
            }
            _ => {}
        }
    }

    // Similar to operators, indexing is always assumed to be overloaded
    // Here, correct cases where an indexing expression can be simplified
    // to use builtin indexing because the index type is known to be
    // usize-ish
    fn fix_index_builtin_expr(&mut self, e: &hir::Expr) {
        if let hir::ExprKind::Index(ref base, ref index) = e.node {
            let mut tables = self.fcx.tables.borrow_mut();

            // All valid indexing looks like this; might encounter non-valid indexes at this point
            if let ty::Ref(_, base_ty, _) = tables.expr_ty_adjusted(&base).sty {
                let index_ty = tables.expr_ty_adjusted(&index);
                let index_ty = self.fcx.resolve_vars_if_possible(&index_ty);

                if base_ty.builtin_index().is_some() && index_ty == self.fcx.tcx.types.usize {
                    // Remove the method call record
                    tables.type_dependent_defs_mut().remove(e.hir_id);
                    tables.node_substs_mut().remove(e.hir_id);

                    tables.adjustments_mut().get_mut(base.hir_id).map(|a| {
                        // Discard the need for a mutable borrow
                        match a.pop() {
                            // Extra adjustment made when indexing causes a drop
                            // of size information - we need to get rid of it
                            // Since this is "after" the other adjustment to be
                            // discarded, we do an extra `pop()`
                            Some(Adjustment {
                                kind: Adjust::Pointer(PointerCast::Unsize),
                                ..
                            }) => {
                                // So the borrow discard actually happens here
                                a.pop();
                            }
                            _ => {}
                        }
                    });
                }
            }
        }
    }
}

///////////////////////////////////////////////////////////////////////////
// Impl of Visitor for Resolver
//
// This is the master code which walks the AST. It delegates most of
// the heavy lifting to the generic visit and resolve functions
// below. In general, a function is made into a `visitor` if it must
// traffic in node-ids or update tables in the type context etc.

impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::None
    }

    fn visit_expr(&mut self, e: &'tcx hir::Expr) {
        self.fix_scalar_builtin_expr(e);
        self.fix_index_builtin_expr(e);

        self.visit_node_id(e.span, e.hir_id);

        match e.node {
            hir::ExprKind::Closure(_, _, body, _, _) => {
                let body = self.fcx.tcx.hir().body(body);
                for arg in &body.arguments {
                    self.visit_node_id(e.span, arg.hir_id);
                }

                self.visit_body(body);
            }
            hir::ExprKind::Struct(_, ref fields, _) => {
                for field in fields {
                    self.visit_field_id(field.hir_id);
                }
            }
            hir::ExprKind::Field(..) => {
                self.visit_field_id(e.hir_id);
            }
            _ => {}
        }

        intravisit::walk_expr(self, e);
    }

    fn visit_block(&mut self, b: &'tcx hir::Block) {
        self.visit_node_id(b.span, b.hir_id);
        intravisit::walk_block(self, b);
    }

    fn visit_pat(&mut self, p: &'tcx hir::Pat) {
        match p.node {
            hir::PatKind::Binding(..) => {
                if let Some(&bm) = self.fcx.tables.borrow().pat_binding_modes().get(p.hir_id) {
                    self.tables.pat_binding_modes_mut().insert(p.hir_id, bm);
                } else {
                    self.tcx()
                        .sess
                        .delay_span_bug(p.span, "missing binding mode");
                }
            }
            hir::PatKind::Struct(_, ref fields, _) => {
                for field in fields {
                    self.visit_field_id(field.hir_id);
                }
            }
            _ => {}
        };

        self.visit_pat_adjustments(p.span, p.hir_id);

        self.visit_node_id(p.span, p.hir_id);
        intravisit::walk_pat(self, p);
    }

    fn visit_local(&mut self, l: &'tcx hir::Local) {
        intravisit::walk_local(self, l);
        let var_ty = self.fcx.local_ty(l.span, l.hir_id).decl_ty;
        let var_ty = self.resolve(&var_ty, &l.span);
        self.write_ty_to_tables(l.hir_id, var_ty);
    }

    fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty) {
        intravisit::walk_ty(self, hir_ty);
        let ty = self.fcx.node_ty(hir_ty.hir_id);
        let ty = self.resolve(&ty, &hir_ty.span);
        self.write_ty_to_tables(hir_ty.hir_id, ty);
    }
}

impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
    fn visit_upvar_capture_map(&mut self) {
        for (upvar_id, upvar_capture) in self.fcx.tables.borrow().upvar_capture_map.iter() {
            let new_upvar_capture = match *upvar_capture {
                ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue,
                ty::UpvarCapture::ByRef(ref upvar_borrow) => {
                    let r = upvar_borrow.region;
                    let r = self.resolve(&r, &upvar_id.var_path.hir_id);
                    ty::UpvarCapture::ByRef(ty::UpvarBorrow {
                        kind: upvar_borrow.kind,
                        region: r,
                    })
                }
            };
            debug!(
                "Upvar capture for {:?} resolved to {:?}",
                upvar_id, new_upvar_capture
            );
            self.tables
                .upvar_capture_map
                .insert(*upvar_id, new_upvar_capture);
        }
    }

    fn visit_closures(&mut self) {
        let fcx_tables = self.fcx.tables.borrow();
        debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
        let common_local_id_root = fcx_tables.local_id_root.unwrap();

        for (&id, &origin) in fcx_tables.closure_kind_origins().iter() {
            let hir_id = hir::HirId {
                owner: common_local_id_root.index,
                local_id: id,
            };
            self.tables
                .closure_kind_origins_mut()
                .insert(hir_id, origin);
        }
    }

    fn visit_coercion_casts(&mut self) {
        let fcx_tables = self.fcx.tables.borrow();
        let fcx_coercion_casts = fcx_tables.coercion_casts();
        debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);

        for local_id in fcx_coercion_casts {
            self.tables.set_coercion_cast(*local_id);
        }
    }

    fn visit_free_region_map(&mut self) {
        self.tables.free_region_map = self.fcx.tables.borrow().free_region_map.clone();
        debug_assert!(!self.tables.free_region_map.elements().any(|r| r.has_local_value()));
    }

    fn visit_user_provided_tys(&mut self) {
        let fcx_tables = self.fcx.tables.borrow();
        debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
        let common_local_id_root = fcx_tables.local_id_root.unwrap();

        let mut errors_buffer = Vec::new();
        for (&local_id, c_ty) in fcx_tables.user_provided_types().iter() {
            let hir_id = hir::HirId {
                owner: common_local_id_root.index,
                local_id,
            };

            if cfg!(debug_assertions) && c_ty.has_local_value() {
                span_bug!(
                    hir_id.to_span(self.fcx.tcx),
                    "writeback: `{:?}` is a local value",
                    c_ty
                );
            };

            self.tables
                .user_provided_types_mut()
                .insert(hir_id, c_ty.clone());

            if let ty::UserType::TypeOf(_, user_substs) = c_ty.value {
                if self.rustc_dump_user_substs {
                    // This is a unit-testing mechanism.
                    let span = self.tcx().hir().span(hir_id);
                    // We need to buffer the errors in order to guarantee a consistent
                    // order when emitting them.
                    let err = self.tcx().sess.struct_span_err(
                        span,
                        &format!("user substs: {:?}", user_substs)
                    );
                    err.buffer(&mut errors_buffer);
                }
            }
        }

        if !errors_buffer.is_empty() {
            errors_buffer.sort_by_key(|diag| diag.span.primary_span());
            for diag in errors_buffer.drain(..) {
                DiagnosticBuilder::new_diagnostic(self.tcx().sess.diagnostic(), diag).emit();
            }
        }
    }

    fn visit_user_provided_sigs(&mut self) {
        let fcx_tables = self.fcx.tables.borrow();
        debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);

        for (&def_id, c_sig) in fcx_tables.user_provided_sigs.iter() {
            if cfg!(debug_assertions) && c_sig.has_local_value() {
                span_bug!(
                    self.fcx.tcx.hir().span_if_local(def_id).unwrap(),
                    "writeback: `{:?}` is a local value",
                    c_sig
                );
            };

            self.tables
                .user_provided_sigs
                .insert(def_id, c_sig.clone());
        }
    }

    fn visit_opaque_types(&mut self, span: Span) {
        for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() {
            let hir_id = self.tcx().hir().as_local_hir_id(def_id).unwrap();
            let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &hir_id);

            debug_assert!(!instantiated_ty.has_escaping_bound_vars());

            // Prevent:
            // * `fn foo<T>() -> Foo<T>`
            // * `fn foo<T: Bound + Other>() -> Foo<T>`
            // from being defining.

            // Also replace all generic params with the ones from the opaque type
            // definition so that
            // ```rust
            // type Foo<T> = impl Baz + 'static;
            // fn foo<U>() -> Foo<U> { .. }
            // ```
            // figures out the concrete type with `U`, but the stored type is with `T`.
            let definition_ty = self.fcx.infer_opaque_definition_from_instantiation(
                def_id, opaque_defn, instantiated_ty, span);

            let mut skip_add = false;

            if let ty::Opaque(defin_ty_def_id, _substs) = definition_ty.sty {
                if def_id == defin_ty_def_id {
                    debug!("Skipping adding concrete definition for opaque type {:?} {:?}",
                           opaque_defn, defin_ty_def_id);
                    skip_add = true;
                }
            }

            if !opaque_defn.substs.has_local_value() {
                // We only want to add an entry into `concrete_opaque_types`
                // if we actually found a defining usage of this opaque type.
                // Otherwise, we do nothing - we'll either find a defining usage
                // in some other location, or we'll end up emitting an error due
                // to the lack of defining usage
                if !skip_add {
                    let new = ty::ResolvedOpaqueTy {
                        concrete_type: definition_ty,
                        substs: opaque_defn.substs,
                    };

                    let old = self.tables
                        .concrete_opaque_types
                        .insert(def_id, new);
                    if let Some(old) = old {
                        if old.concrete_type != definition_ty || old.substs != opaque_defn.substs {
                            span_bug!(
                                span,
                                "visit_opaque_types tried to write different types for the same \
                                opaque type: {:?}, {:?}, {:?}, {:?}",
                                def_id,
                                definition_ty,
                                opaque_defn,
                                old,
                            );
                        }
                    }
                }
            } else {
                self.tcx().sess.delay_span_bug(
                    span,
                    "`opaque_defn` is a local value",
                );
            }
        }
    }

    fn visit_field_id(&mut self, hir_id: hir::HirId) {
        if let Some(index) = self.fcx
            .tables
            .borrow_mut()
            .field_indices_mut()
            .remove(hir_id)
        {
            self.tables.field_indices_mut().insert(hir_id, index);
        }
    }

    fn visit_node_id(&mut self, span: Span, hir_id: hir::HirId) {
        // Export associated path extensions and method resolutions.
        if let Some(def) = self.fcx
            .tables
            .borrow_mut()
            .type_dependent_defs_mut()
            .remove(hir_id)
        {
            self.tables.type_dependent_defs_mut().insert(hir_id, def);
        }

        // Resolve any borrowings for the node with id `node_id`
        self.visit_adjustments(span, hir_id);

        // Resolve the type of the node with id `node_id`
        let n_ty = self.fcx.node_ty(hir_id);
        let n_ty = self.resolve(&n_ty, &span);
        self.write_ty_to_tables(hir_id, n_ty);
        debug!("node {:?} has type {:?}", hir_id, n_ty);

        // Resolve any substitutions
        if let Some(substs) = self.fcx.tables.borrow().node_substs_opt(hir_id) {
            let substs = self.resolve(&substs, &span);
            debug!("write_substs_to_tcx({:?}, {:?})", hir_id, substs);
            assert!(!substs.needs_infer() && !substs.has_placeholders());
            self.tables.node_substs_mut().insert(hir_id, substs);
        }
    }

    fn visit_adjustments(&mut self, span: Span, hir_id: hir::HirId) {
        let adjustment = self.fcx
            .tables
            .borrow_mut()
            .adjustments_mut()
            .remove(hir_id);
        match adjustment {
            None => {
                debug!("no adjustments for node {:?}", hir_id);
            }

            Some(adjustment) => {
                let resolved_adjustment = self.resolve(&adjustment, &span);
                debug!(
                    "adjustments for node {:?}: {:?}",
                    hir_id, resolved_adjustment
                );
                self.tables
                    .adjustments_mut()
                    .insert(hir_id, resolved_adjustment);
            }
        }
    }

    fn visit_pat_adjustments(&mut self, span: Span, hir_id: hir::HirId) {
        let adjustment = self.fcx
            .tables
            .borrow_mut()
            .pat_adjustments_mut()
            .remove(hir_id);
        match adjustment {
            None => {
                debug!("no pat_adjustments for node {:?}", hir_id);
            }

            Some(adjustment) => {
                let resolved_adjustment = self.resolve(&adjustment, &span);
                debug!(
                    "pat_adjustments for node {:?}: {:?}",
                    hir_id, resolved_adjustment
                );
                self.tables
                    .pat_adjustments_mut()
                    .insert(hir_id, resolved_adjustment);
            }
        }
    }

    fn visit_liberated_fn_sigs(&mut self) {
        let fcx_tables = self.fcx.tables.borrow();
        debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
        let common_local_id_root = fcx_tables.local_id_root.unwrap();

        for (&local_id, fn_sig) in fcx_tables.liberated_fn_sigs().iter() {
            let hir_id = hir::HirId {
                owner: common_local_id_root.index,
                local_id,
            };
            let fn_sig = self.resolve(fn_sig, &hir_id);
            self.tables
                .liberated_fn_sigs_mut()
                .insert(hir_id, fn_sig.clone());
        }
    }

    fn visit_fru_field_types(&mut self) {
        let fcx_tables = self.fcx.tables.borrow();
        debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
        let common_local_id_root = fcx_tables.local_id_root.unwrap();

        for (&local_id, ftys) in fcx_tables.fru_field_types().iter() {
            let hir_id = hir::HirId {
                owner: common_local_id_root.index,
                local_id,
            };
            let ftys = self.resolve(ftys, &hir_id);
            self.tables.fru_field_types_mut().insert(hir_id, ftys);
        }
    }

    fn resolve<T>(&self, x: &T, span: &dyn Locatable) -> T
    where
        T: TypeFoldable<'tcx>,
    {
        let x = x.fold_with(&mut Resolver::new(self.fcx, span, self.body));
        if cfg!(debug_assertions) && x.has_local_value() {
            span_bug!(
                span.to_span(self.fcx.tcx),
                "writeback: `{:?}` is a local value",
                x
            );
        }
        x
    }
}

trait Locatable {
    fn to_span(&self, tcx: TyCtxt<'_>) -> Span;
}

impl Locatable for Span {
    fn to_span(&self, _: TyCtxt<'_>) -> Span {
        *self
    }
}

impl Locatable for DefIndex {
    fn to_span(&self, tcx: TyCtxt<'_>) -> Span {
        let hir_id = tcx.hir().def_index_to_hir_id(*self);
        tcx.hir().span(hir_id)
    }
}

impl Locatable for hir::HirId {
    fn to_span(&self, tcx: TyCtxt<'_>) -> Span {
        tcx.hir().span(*self)
    }
}

///////////////////////////////////////////////////////////////////////////
// The Resolver. This is the type folding engine that detects
// unresolved types and so forth.

struct Resolver<'cx, 'tcx> {
    tcx: TyCtxt<'tcx>,
    infcx: &'cx InferCtxt<'cx, 'tcx>,
    span: &'cx dyn Locatable,
    body: &'tcx hir::Body,
}

impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
    fn new(
        fcx: &'cx FnCtxt<'cx, 'tcx>,
        span: &'cx dyn Locatable,
        body: &'tcx hir::Body,
    ) -> Resolver<'cx, 'tcx> {
        Resolver {
            tcx: fcx.tcx,
            infcx: fcx,
            span,
            body,
        }
    }

    fn report_error(&self, t: Ty<'tcx>) {
        if !self.tcx.sess.has_errors() {
            self.infcx
                .need_type_info_err(Some(self.body.id()), self.span.to_span(self.tcx), t)
                .emit();
        }
    }
}

impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
    fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
        match self.infcx.fully_resolve(&t) {
            Ok(t) => t,
            Err(_) => {
                debug!(
                    "Resolver::fold_ty: input type `{:?}` not fully resolvable",
                    t
                );
                self.report_error(t);
                self.tcx().types.err
            }
        }
    }

    // FIXME This should be carefully checked
    // We could use `self.report_error` but it doesn't accept a ty::Region, right now.
    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
        self.infcx.fully_resolve(&r).unwrap_or(self.tcx.lifetimes.re_static)
    }

    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
        match self.infcx.fully_resolve(&ct) {
            Ok(ct) => ct,
            Err(_) => {
                debug!(
                    "Resolver::fold_const: input const `{:?}` not fully resolvable",
                    ct
                );
                // FIXME: we'd like to use `self.report_error`, but it doesn't yet
                // accept a &'tcx ty::Const.
                self.tcx().consts.err
            }
        }
    }
}

///////////////////////////////////////////////////////////////////////////
// During type check, we store promises with the result of trait
// lookup rather than the actual results (because the results are not
// necessarily available immediately). These routines unwind the
// promises. It is expected that we will have already reported any
// errors that may be encountered, so if the promises store an error,
// a dummy result is returned.
