]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc_typeck/check/callee.rs
New upstream version 1.21.0+dfsg1
[rustc.git] / src / librustc_typeck / check / callee.rs
index 4cca3b7582bfb0897a3d0ee13b380ec841bf424c..460e2858b22ec091ea4272467e4bdc2cef4c1235 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::autoderef;
-use super::check_argument_types;
-use super::check_expr;
-use super::check_method_argument_types;
-use super::demand;
-use super::DeferredCallResolution;
-use super::err_args;
-use super::Expectation;
-use super::expected_types_for_fn_args;
-use super::FnCtxt;
-use super::LvaluePreference;
-use super::method;
-use super::structurally_resolved_type;
-use super::TupleArgumentsFlag;
-use super::UnresolvedTypeAction;
-use super::write_call;
-
-use CrateCtxt;
-use middle::infer;
-use middle::ty::{self, Ty};
-use syntax::ast;
-use syntax::codemap::Span;
-use syntax::parse::token;
-use syntax::ptr::P;
+use super::{Expectation, FnCtxt, TupleArgumentsFlag};
+use super::autoderef::Autoderef;
+use super::method::MethodCallee;
+
+use hir::def::Def;
+use hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::{infer, traits};
+use rustc::ty::{self, TyCtxt, TypeFoldable, LvaluePreference, Ty};
+use rustc::ty::subst::Subst;
+use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
+use syntax::abi;
+use syntax::symbol::Symbol;
+use syntax_pos::Span;
+
+use rustc::hir;
 
 /// Check that it is legal to call methods of the trait corresponding
 /// to `trait_id` (this only cares about the trait, not the specific
 /// method that is called)
-pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: ast::DefId) {
-    let tcx = ccx.tcx;
-    let did = Some(trait_id);
-    let li = &tcx.lang_items;
-
-    if did == li.drop_trait() {
-        span_err!(tcx.sess, span, E0040, "explicit use of destructor method");
-    } else if !tcx.sess.features.borrow().unboxed_closures {
-        // the #[feature(unboxed_closures)] feature isn't
-        // activated so we need to enforce the closure
-        // restrictions.
-
-        let method = if did == li.fn_trait() {
-            "call"
-        } else if did == li.fn_mut_trait() {
-            "call_mut"
-        } else if did == li.fn_once_trait() {
-            "call_once"
-        } else {
-            return // not a closure method, everything is OK.
-        };
-
-        span_err!(tcx.sess, span, E0174,
-                  "explicit use of unboxed closure method `{}` is experimental",
-                  method);
-        fileline_help!(tcx.sess, span,
-                   "add `#![feature(unboxed_closures)]` to the crate attributes to enable");
+pub fn check_legal_trait_for_method_call(tcx: TyCtxt, span: Span, trait_id: DefId) {
+    if tcx.lang_items.drop_trait() == Some(trait_id) {
+        struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method")
+            .span_label(span, "explicit destructor calls not allowed")
+            .emit();
     }
 }
 
-pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                            call_expr: &'tcx ast::Expr,
-                            callee_expr: &'tcx ast::Expr,
-                            arg_exprs: &'tcx [P<ast::Expr>],
-                            expected: Expectation<'tcx>)
-{
-    check_expr(fcx, callee_expr);
-    let original_callee_ty = fcx.expr_ty(callee_expr);
-    let (callee_ty, _, result) =
-        autoderef(fcx,
-                  callee_expr.span,
-                  original_callee_ty,
-                  Some(callee_expr),
-                  UnresolvedTypeAction::Error,
-                  LvaluePreference::NoPreference,
-                  |adj_ty, idx| {
-                      try_overloaded_call_step(fcx, call_expr, callee_expr, adj_ty, idx)
-                  });
-
-    match result {
-        None => {
-            // this will report an error since original_callee_ty is not a fn
-            confirm_builtin_call(fcx, call_expr, original_callee_ty, arg_exprs, expected);
-        }
+enum CallStep<'tcx> {
+    Builtin(Ty<'tcx>),
+    DeferredClosure(ty::FnSig<'tcx>),
+    Overloaded(MethodCallee<'tcx>),
+}
 
-        Some(CallStep::Builtin) => {
-            confirm_builtin_call(fcx, call_expr, callee_ty, arg_exprs, expected);
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
+    pub fn check_call(&self,
+                      call_expr: &'gcx hir::Expr,
+                      callee_expr: &'gcx hir::Expr,
+                      arg_exprs: &'gcx [hir::Expr],
+                      expected: Expectation<'tcx>)
+                      -> Ty<'tcx> {
+        let original_callee_ty = self.check_expr(callee_expr);
+        let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty);
+
+        let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
+        let mut result = None;
+        while result.is_none() && autoderef.next().is_some() {
+            result = self.try_overloaded_call_step(call_expr, callee_expr, &autoderef);
         }
+        autoderef.finalize();
 
-        Some(CallStep::DeferredClosure(fn_sig)) => {
-            confirm_deferred_closure_call(fcx, call_expr, arg_exprs, expected, fn_sig);
-        }
+        let output = match result {
+            None => {
+                // this will report an error since original_callee_ty is not a fn
+                self.confirm_builtin_call(call_expr, original_callee_ty, arg_exprs, expected)
+            }
 
-        Some(CallStep::Overloaded(method_callee)) => {
-            confirm_overloaded_call(fcx, call_expr, callee_expr,
-                                    arg_exprs, expected, method_callee);
-        }
+            Some(CallStep::Builtin(callee_ty)) => {
+                self.confirm_builtin_call(call_expr, callee_ty, arg_exprs, expected)
+            }
+
+            Some(CallStep::DeferredClosure(fn_sig)) => {
+                self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, fn_sig)
+            }
+
+            Some(CallStep::Overloaded(method_callee)) => {
+                self.confirm_overloaded_call(call_expr, arg_exprs, expected, method_callee)
+            }
+        };
+
+        // we must check that return type of called functions is WF:
+        self.register_wf_obligation(output, call_expr.span, traits::MiscObligation);
+
+        output
     }
-}
 
-enum CallStep<'tcx> {
-    Builtin,
-    DeferredClosure(ty::FnSig<'tcx>),
-    Overloaded(ty::MethodCallee<'tcx>)
-}
+    fn try_overloaded_call_step(&self,
+                                call_expr: &'gcx hir::Expr,
+                                callee_expr: &'gcx hir::Expr,
+                                autoderef: &Autoderef<'a, 'gcx, 'tcx>)
+                                -> Option<CallStep<'tcx>> {
+        let adjusted_ty = autoderef.unambiguous_final_ty();
+        debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})",
+               call_expr,
+               adjusted_ty);
+
+        // If the callee is a bare function or a closure, then we're all set.
+        match adjusted_ty.sty {
+            ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+                let adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference);
+                self.apply_adjustments(callee_expr, adjustments);
+                return Some(CallStep::Builtin(adjusted_ty));
+            }
 
-fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                      call_expr: &'tcx ast::Expr,
-                                      callee_expr: &'tcx ast::Expr,
-                                      adjusted_ty: Ty<'tcx>,
-                                      autoderefs: usize)
-                                      -> Option<CallStep<'tcx>>
-{
-    debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?}, autoderefs={})",
-           call_expr,
-           adjusted_ty,
-           autoderefs);
-
-    // If the callee is a bare function or a closure, then we're all set.
-    match structurally_resolved_type(fcx, callee_expr.span, adjusted_ty).sty {
-        ty::TyBareFn(..) => {
-            fcx.write_autoderef_adjustment(callee_expr.id, autoderefs);
-            return Some(CallStep::Builtin);
-        }
+            ty::TyClosure(def_id, substs) => {
+                assert_eq!(def_id.krate, LOCAL_CRATE);
+
+                // Check whether this is a call to a closure where we
+                // haven't yet decided on whether the closure is fn vs
+                // fnmut vs fnonce. If so, we have to defer further processing.
+                if self.closure_kind(def_id).is_none() {
+                    let closure_ty = self.fn_sig(def_id).subst(self.tcx, substs.substs);
+                    let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
+                                                                   infer::FnCall,
+                                                                   &closure_ty)
+                        .0;
+                    let adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference);
+                    self.record_deferred_call_resolution(def_id, DeferredCallResolution {
+                        call_expr,
+                        callee_expr,
+                        adjusted_ty,
+                        adjustments,
+                        fn_sig,
+                        closure_def_id: def_id,
+                    });
+                    return Some(CallStep::DeferredClosure(fn_sig));
+                }
+            }
 
-        ty::TyClosure(def_id, ref substs) => {
-            assert_eq!(def_id.krate, ast::LOCAL_CRATE);
-
-            // Check whether this is a call to a closure where we
-            // haven't yet decided on whether the closure is fn vs
-            // fnmut vs fnonce. If so, we have to defer further processing.
-            if fcx.infcx().closure_kind(def_id).is_none() {
-                let closure_ty =
-                    fcx.infcx().closure_type(def_id, substs);
-                let fn_sig =
-                    fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
-                                                                          infer::FnCall,
-                                                                          &closure_ty.sig).0;
-                fcx.record_deferred_call_resolution(def_id, Box::new(CallResolution {
-                    call_expr: call_expr,
-                    callee_expr: callee_expr,
-                    adjusted_ty: adjusted_ty,
-                    autoderefs: autoderefs,
-                    fn_sig: fn_sig.clone(),
-                    closure_def_id: def_id
-                }));
-                return Some(CallStep::DeferredClosure(fn_sig));
+            // Hack: we know that there are traits implementing Fn for &F
+            // where F:Fn and so forth. In the particular case of types
+            // like `x: &mut FnMut()`, if there is a call `x()`, we would
+            // normally translate to `FnMut::call_mut(&mut x, ())`, but
+            // that winds up requiring `mut x: &mut FnMut()`. A little
+            // over the top. The simplest fix by far is to just ignore
+            // this case and deref again, so we wind up with
+            // `FnMut::call_mut(&mut *x, ())`.
+            ty::TyRef(..) if autoderef.step_count() == 0 => {
+                return None;
             }
-        }
 
-        // Hack: we know that there are traits implementing Fn for &F
-        // where F:Fn and so forth. In the particular case of types
-        // like `x: &mut FnMut()`, if there is a call `x()`, we would
-        // normally translate to `FnMut::call_mut(&mut x, ())`, but
-        // that winds up requiring `mut x: &mut FnMut()`. A little
-        // over the top. The simplest fix by far is to just ignore
-        // this case and deref again, so we wind up with
-        // `FnMut::call_mut(&mut *x, ())`.
-        ty::TyRef(..) if autoderefs == 0 => {
-            return None;
+            _ => {}
         }
 
-        _ => {}
+        self.try_overloaded_call_traits(call_expr, adjusted_ty).map(|(autoref, method)| {
+            let mut adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference);
+            adjustments.extend(autoref);
+            self.apply_adjustments(callee_expr, adjustments);
+            CallStep::Overloaded(method)
+        })
     }
 
-    try_overloaded_call_traits(fcx, call_expr, callee_expr, adjusted_ty, autoderefs)
-        .map(|method_callee| CallStep::Overloaded(method_callee))
-}
-
-fn try_overloaded_call_traits<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                       call_expr: &ast::Expr,
-                                       callee_expr: &ast::Expr,
-                                       adjusted_ty: Ty<'tcx>,
-                                       autoderefs: usize)
-                                       -> Option<ty::MethodCallee<'tcx>>
-{
-    // Try the options that are least restrictive on the caller first.
-    for &(opt_trait_def_id, method_name) in &[
-        (fcx.tcx().lang_items.fn_trait(), token::intern("call")),
-        (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
-        (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
-    ] {
-        let trait_def_id = match opt_trait_def_id {
-            Some(def_id) => def_id,
-            None => continue,
-        };
-
-        match method::lookup_in_trait_adjusted(fcx,
-                                               call_expr.span,
-                                               Some(&*callee_expr),
-                                               method_name,
-                                               trait_def_id,
-                                               autoderefs,
-                                               false,
-                                               adjusted_ty,
-                                               None) {
-            None => continue,
-            Some(method_callee) => {
-                return Some(method_callee);
+    fn try_overloaded_call_traits(&self,
+                                  call_expr: &hir::Expr,
+                                  adjusted_ty: Ty<'tcx>)
+                                  -> Option<(Option<Adjustment<'tcx>>,
+                                             MethodCallee<'tcx>)> {
+        // Try the options that are least restrictive on the caller first.
+        for &(opt_trait_def_id, method_name, borrow) in
+            &[(self.tcx.lang_items.fn_trait(), Symbol::intern("call"), true),
+              (self.tcx.lang_items.fn_mut_trait(), Symbol::intern("call_mut"), true),
+              (self.tcx.lang_items.fn_once_trait(), Symbol::intern("call_once"), false)] {
+            let trait_def_id = match opt_trait_def_id {
+                Some(def_id) => def_id,
+                None => continue,
+            };
+
+            match self.lookup_method_in_trait(call_expr.span,
+                                              method_name,
+                                              trait_def_id,
+                                              adjusted_ty,
+                                              None) {
+                None => continue,
+                Some(ok) => {
+                    let method = self.register_infer_ok_obligations(ok);
+                    let mut autoref = None;
+                    if borrow {
+                        if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty {
+                            autoref = Some(Adjustment {
+                                kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)),
+                                target: method.sig.inputs()[0]
+                            });
+                        }
+                    }
+                    return Some((autoref, method));
+                }
             }
         }
+
+        None
     }
 
-    None
-}
+    fn confirm_builtin_call(&self,
+                            call_expr: &hir::Expr,
+                            callee_ty: Ty<'tcx>,
+                            arg_exprs: &'gcx [hir::Expr],
+                            expected: Expectation<'tcx>)
+                            -> Ty<'tcx> {
+        let (fn_sig, def_span) = match callee_ty.sty {
+            ty::TyFnDef(def_id, _) => {
+                (callee_ty.fn_sig(self.tcx), self.tcx.hir.span_if_local(def_id))
+            }
+            ty::TyFnPtr(sig) => (sig, None),
+            ref t => {
+                let mut unit_variant = None;
+                if let &ty::TyAdt(adt_def, ..) = t {
+                    if adt_def.is_enum() {
+                        if let hir::ExprCall(ref expr, _) = call_expr.node {
+                            unit_variant = Some(self.tcx.hir.node_to_pretty_string(expr.id))
+                        }
+                    }
+                }
+                let mut err = type_error_struct!(self.tcx.sess, call_expr.span, callee_ty, E0618,
+                                                 "expected function, found `{}`",
+                                                 if let Some(ref path) = unit_variant {
+                                                     path.to_string()
+                                                 } else {
+                                                     callee_ty.to_string()
+                                                 });
+                if let Some(path) = unit_variant {
+                    err.help(&format!("did you mean to write `{}`?", path));
+                }
 
-fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
-                                 call_expr: &ast::Expr,
-                                 callee_ty: Ty<'tcx>,
-                                 arg_exprs: &'tcx [P<ast::Expr>],
-                                 expected: Expectation<'tcx>)
-{
-    let error_fn_sig;
-
-    let fn_sig = match callee_ty.sty {
-        ty::TyBareFn(_, &ty::BareFnTy {ref sig, ..}) => {
-            sig
-        }
-        _ => {
-            fcx.type_error_message(call_expr.span, |actual| {
-                format!("expected function, found `{}`", actual)
-            }, callee_ty, None);
-
-            // This is the "default" function signature, used in case of error.
-            // In that case, we check each argument against "error" in order to
-            // set up all the node type bindings.
-            error_fn_sig = ty::Binder(ty::FnSig {
-                inputs: err_args(fcx.tcx(), arg_exprs.len()),
-                output: ty::FnConverging(fcx.tcx().types.err),
-                variadic: false
-            });
-
-            &error_fn_sig
-        }
-    };
-
-    // Replace any late-bound regions that appear in the function
-    // signature with region variables. We also have to
-    // renormalize the associated types at this point, since they
-    // previously appeared within a `Binder<>` and hence would not
-    // have been normalized before.
-    let fn_sig =
-        fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
-                                                              infer::FnCall,
-                                                              fn_sig).0;
-    let fn_sig =
-        fcx.normalize_associated_types_in(call_expr.span, &fn_sig);
-
-    // Call the generic checker.
-    let expected_arg_tys = expected_types_for_fn_args(fcx,
-                                                      call_expr.span,
-                                                      expected,
-                                                      fn_sig.output,
-                                                      &fn_sig.inputs);
-    check_argument_types(fcx,
-                         call_expr.span,
-                         &fn_sig.inputs,
-                         &expected_arg_tys[..],
-                         arg_exprs,
-                         fn_sig.variadic,
-                         TupleArgumentsFlag::DontTupleArguments);
-
-    write_call(fcx, call_expr, fn_sig.output);
-}
+                if let hir::ExprCall(ref expr, _) = call_expr.node {
+                    let def = if let hir::ExprPath(ref qpath) = expr.node {
+                        self.tables.borrow().qpath_def(qpath, expr.hir_id)
+                    } else {
+                        Def::Err
+                    };
+                    if def != Def::Err {
+                        if let Some(span) = self.tcx.hir.span_if_local(def.def_id()) {
+                            err.span_note(span, "defined here");
+                        }
+                    }
+                }
 
-fn confirm_deferred_closure_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
-                                          call_expr: &ast::Expr,
-                                          arg_exprs: &'tcx [P<ast::Expr>],
-                                          expected: Expectation<'tcx>,
-                                          fn_sig: ty::FnSig<'tcx>)
-{
-    // `fn_sig` is the *signature* of the cosure being called. We
-    // don't know the full details yet (`Fn` vs `FnMut` etc), but we
-    // do know the types expected for each argument and the return
-    // type.
-
-    let expected_arg_tys =
-        expected_types_for_fn_args(fcx,
-                                   call_expr.span,
-                                   expected,
-                                   fn_sig.output.clone(),
-                                   &*fn_sig.inputs);
-
-    check_argument_types(fcx,
-                         call_expr.span,
-                         &*fn_sig.inputs,
-                         &*expected_arg_tys,
-                         arg_exprs,
-                         fn_sig.variadic,
-                         TupleArgumentsFlag::TupleArguments);
-
-    write_call(fcx, call_expr, fn_sig.output);
-}
+                err.emit();
+
+                // This is the "default" function signature, used in case of error.
+                // In that case, we check each argument against "error" in order to
+                // set up all the node type bindings.
+                (ty::Binder(self.tcx.mk_fn_sig(
+                    self.err_args(arg_exprs.len()).into_iter(),
+                    self.tcx.types.err,
+                    false,
+                    hir::Unsafety::Normal,
+                    abi::Abi::Rust
+                )), None)
+            }
+        };
 
-fn confirm_overloaded_call<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                    call_expr: &ast::Expr,
-                                    callee_expr: &'tcx ast::Expr,
-                                    arg_exprs: &'tcx [P<ast::Expr>],
-                                    expected: Expectation<'tcx>,
-                                    method_callee: ty::MethodCallee<'tcx>)
-{
-    let output_type =
-        check_method_argument_types(fcx,
-                                    call_expr.span,
-                                    method_callee.ty,
-                                    callee_expr,
-                                    arg_exprs,
-                                    TupleArgumentsFlag::TupleArguments,
-                                    expected);
-    write_call(fcx, call_expr, output_type);
-
-    write_overloaded_call_method_map(fcx, call_expr, method_callee);
-}
+        // Replace any late-bound regions that appear in the function
+        // signature with region variables. We also have to
+        // renormalize the associated types at this point, since they
+        // previously appeared within a `Binder<>` and hence would not
+        // have been normalized before.
+        let fn_sig =
+            self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, &fn_sig)
+                .0;
+        let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig);
+
+        // Call the generic checker.
+        let expected_arg_tys =
+            self.expected_inputs_for_expected_output(call_expr.span,
+                                            expected,
+                                            fn_sig.output(),
+                                            fn_sig.inputs());
+        self.check_argument_types(call_expr.span,
+                                  fn_sig.inputs(),
+                                  &expected_arg_tys[..],
+                                  arg_exprs,
+                                  fn_sig.variadic,
+                                  TupleArgumentsFlag::DontTupleArguments,
+                                  def_span);
+
+        fn_sig.output()
+    }
+
+    fn confirm_deferred_closure_call(&self,
+                                     call_expr: &hir::Expr,
+                                     arg_exprs: &'gcx [hir::Expr],
+                                     expected: Expectation<'tcx>,
+                                     fn_sig: ty::FnSig<'tcx>)
+                                     -> Ty<'tcx> {
+        // `fn_sig` is the *signature* of the cosure being called. We
+        // don't know the full details yet (`Fn` vs `FnMut` etc), but we
+        // do know the types expected for each argument and the return
+        // type.
+
+        let expected_arg_tys = self.expected_inputs_for_expected_output(call_expr.span,
+                                                               expected,
+                                                               fn_sig.output().clone(),
+                                                               fn_sig.inputs());
+
+        self.check_argument_types(call_expr.span,
+                                  fn_sig.inputs(),
+                                  &expected_arg_tys,
+                                  arg_exprs,
+                                  fn_sig.variadic,
+                                  TupleArgumentsFlag::TupleArguments,
+                                  None);
+
+        fn_sig.output()
+    }
 
-fn write_overloaded_call_method_map<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                             call_expr: &ast::Expr,
-                                             method_callee: ty::MethodCallee<'tcx>) {
-    let method_call = ty::MethodCall::expr(call_expr.id);
-    fcx.inh.tables.borrow_mut().method_map.insert(method_call, method_callee);
+    fn confirm_overloaded_call(&self,
+                               call_expr: &hir::Expr,
+                               arg_exprs: &'gcx [hir::Expr],
+                               expected: Expectation<'tcx>,
+                               method_callee: MethodCallee<'tcx>)
+                               -> Ty<'tcx> {
+        let output_type = self.check_method_argument_types(call_expr.span,
+                                                           Ok(method_callee),
+                                                           arg_exprs,
+                                                           TupleArgumentsFlag::TupleArguments,
+                                                           expected);
+
+        self.write_method_call(call_expr.hir_id, method_callee);
+        output_type
+    }
 }
 
 #[derive(Debug)]
-struct CallResolution<'tcx> {
-    call_expr: &'tcx ast::Expr,
-    callee_expr: &'tcx ast::Expr,
+pub struct DeferredCallResolution<'gcx: 'tcx, 'tcx> {
+    call_expr: &'gcx hir::Expr,
+    callee_expr: &'gcx hir::Expr,
     adjusted_ty: Ty<'tcx>,
-    autoderefs: usize,
+    adjustments: Vec<Adjustment<'tcx>>,
     fn_sig: ty::FnSig<'tcx>,
-    closure_def_id: ast::DefId,
+    closure_def_id: DefId,
 }
 
-impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> {
-    fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>) {
-        debug!("DeferredCallResolution::resolve() {:?}",
-               self);
+impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> {
+    pub fn resolve(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
+        debug!("DeferredCallResolution::resolve() {:?}", self);
 
         // we should not be invoked until the closure kind has been
         // determined by upvar inference
-        assert!(fcx.infcx().closure_kind(self.closure_def_id).is_some());
+        assert!(fcx.closure_kind(self.closure_def_id).is_some());
 
         // We may now know enough to figure out fn vs fnmut etc.
-        match try_overloaded_call_traits(fcx, self.call_expr, self.callee_expr,
-                                         self.adjusted_ty, self.autoderefs) {
-            Some(method_callee) => {
+        match fcx.try_overloaded_call_traits(self.call_expr,
+                                             self.adjusted_ty) {
+            Some((autoref, method_callee)) => {
                 // One problem is that when we get here, we are going
                 // to have a newly instantiated function signature
                 // from the call trait. This has to be reconciled with
@@ -358,30 +349,27 @@ impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> {
                 // can't because of the annoying need for a TypeTrace.
                 // (This always bites me, should find a way to
                 // refactor it.)
-                let method_sig = fcx.tcx().no_late_bound_regions(method_callee.ty.fn_sig())
-                                          .unwrap();
+                let method_sig = method_callee.sig;
 
-                debug!("attempt_resolution: method_callee={:?}",
-                       method_callee);
+                debug!("attempt_resolution: method_callee={:?}", method_callee);
 
-                for (&method_arg_ty, &self_arg_ty) in
-                    method_sig.inputs[1..].iter().zip(&self.fn_sig.inputs)
-                {
-                    demand::eqtype(fcx, self.call_expr.span, self_arg_ty, method_arg_ty);
+                for (method_arg_ty, self_arg_ty) in
+                    method_sig.inputs().iter().skip(1).zip(self.fn_sig.inputs()) {
+                    fcx.demand_eqtype(self.call_expr.span, &self_arg_ty, &method_arg_ty);
                 }
 
-                let nilty = fcx.tcx().mk_nil();
-                demand::eqtype(fcx,
-                               self.call_expr.span,
-                               method_sig.output.unwrap_or(nilty),
-                               self.fn_sig.output.unwrap_or(nilty));
+                fcx.demand_eqtype(self.call_expr.span, method_sig.output(), self.fn_sig.output());
+
+                let mut adjustments = self.adjustments;
+                adjustments.extend(autoref);
+                fcx.apply_adjustments(self.callee_expr, adjustments);
 
-                write_overloaded_call_method_map(fcx, self.call_expr, method_callee);
+                fcx.write_method_call(self.call_expr.hir_id,
+                                      method_callee);
             }
             None => {
-                fcx.tcx().sess.span_bug(
-                    self.call_expr.span,
-                    "failed to find an overloaded call trait for closure call");
+                span_bug!(self.call_expr.span,
+                          "failed to find an overloaded call trait for closure call");
             }
         }
     }