// 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
// 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");
}
}
}