1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use super::{DeferredCallResolution, Expectation, FnCtxt,
15 use middle::cstore::LOCAL_CRATE;
17 use hir::def_id::DefId;
19 use rustc::ty::{self, LvaluePreference, Ty};
20 use syntax::parse::token;
26 /// Check that it is legal to call methods of the trait corresponding
27 /// to `trait_id` (this only cares about the trait, not the specific
28 /// method that is called)
29 pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: DefId) {
30 if ccx.tcx.lang_items.drop_trait() == Some(trait_id) {
31 struct_span_err!(ccx.tcx.sess, span, E0040, "explicit use of destructor method")
32 .span_label(span, &format!("call to destructor method"))
39 DeferredClosure(ty::FnSig<'tcx>),
40 Overloaded(ty::MethodCallee<'tcx>)
43 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
44 pub fn check_call(&self,
45 call_expr: &'gcx hir::Expr,
46 callee_expr: &'gcx hir::Expr,
47 arg_exprs: &'gcx [P<hir::Expr>],
48 expected: Expectation<'tcx>)
50 self.check_expr(callee_expr);
51 let original_callee_ty = self.expr_ty(callee_expr);
53 let mut autoderef = self.autoderef(callee_expr.span, original_callee_ty);
54 let result = autoderef.by_ref().flat_map(|(adj_ty, idx)| {
55 self.try_overloaded_call_step(call_expr, callee_expr, adj_ty, idx)
57 let callee_ty = autoderef.unambiguous_final_ty();
58 autoderef.finalize(LvaluePreference::NoPreference, Some(callee_expr));
62 // this will report an error since original_callee_ty is not a fn
63 self.confirm_builtin_call(call_expr, original_callee_ty, arg_exprs, expected);
66 Some(CallStep::Builtin) => {
67 self.confirm_builtin_call(call_expr, callee_ty, arg_exprs, expected);
70 Some(CallStep::DeferredClosure(fn_sig)) => {
71 self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, fn_sig);
74 Some(CallStep::Overloaded(method_callee)) => {
75 self.confirm_overloaded_call(call_expr, callee_expr,
76 arg_exprs, expected, method_callee);
81 fn try_overloaded_call_step(&self,
82 call_expr: &'gcx hir::Expr,
83 callee_expr: &'gcx hir::Expr,
84 adjusted_ty: Ty<'tcx>,
86 -> Option<CallStep<'tcx>>
88 debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?}, autoderefs={})",
93 // If the callee is a bare function or a closure, then we're all set.
94 match self.structurally_resolved_type(callee_expr.span, adjusted_ty).sty {
95 ty::TyFnDef(..) | ty::TyFnPtr(_) => {
96 self.write_autoderef_adjustment(callee_expr.id, autoderefs);
97 return Some(CallStep::Builtin);
100 ty::TyClosure(def_id, substs) => {
101 assert_eq!(def_id.krate, LOCAL_CRATE);
103 // Check whether this is a call to a closure where we
104 // haven't yet decided on whether the closure is fn vs
105 // fnmut vs fnonce. If so, we have to defer further processing.
106 if self.closure_kind(def_id).is_none() {
108 self.closure_type(def_id, substs);
110 self.replace_late_bound_regions_with_fresh_var(call_expr.span,
113 self.record_deferred_call_resolution(def_id, Box::new(CallResolution {
114 call_expr: call_expr,
115 callee_expr: callee_expr,
116 adjusted_ty: adjusted_ty,
117 autoderefs: autoderefs,
118 fn_sig: fn_sig.clone(),
119 closure_def_id: def_id
121 return Some(CallStep::DeferredClosure(fn_sig));
125 // Hack: we know that there are traits implementing Fn for &F
126 // where F:Fn and so forth. In the particular case of types
127 // like `x: &mut FnMut()`, if there is a call `x()`, we would
128 // normally translate to `FnMut::call_mut(&mut x, ())`, but
129 // that winds up requiring `mut x: &mut FnMut()`. A little
130 // over the top. The simplest fix by far is to just ignore
131 // this case and deref again, so we wind up with
132 // `FnMut::call_mut(&mut *x, ())`.
133 ty::TyRef(..) if autoderefs == 0 => {
140 self.try_overloaded_call_traits(call_expr, callee_expr, adjusted_ty, autoderefs)
141 .map(|method_callee| CallStep::Overloaded(method_callee))
144 fn try_overloaded_call_traits(&self,
145 call_expr: &hir::Expr,
146 callee_expr: &hir::Expr,
147 adjusted_ty: Ty<'tcx>,
149 -> Option<ty::MethodCallee<'tcx>>
151 // Try the options that are least restrictive on the caller first.
152 for &(opt_trait_def_id, method_name) in &[
153 (self.tcx.lang_items.fn_trait(), token::intern("call")),
154 (self.tcx.lang_items.fn_mut_trait(), token::intern("call_mut")),
155 (self.tcx.lang_items.fn_once_trait(), token::intern("call_once")),
157 let trait_def_id = match opt_trait_def_id {
158 Some(def_id) => def_id,
162 match self.lookup_method_in_trait_adjusted(call_expr.span,
171 Some(method_callee) => {
172 return Some(method_callee);
180 fn confirm_builtin_call(&self,
181 call_expr: &hir::Expr,
183 arg_exprs: &'gcx [P<hir::Expr>],
184 expected: Expectation<'tcx>)
188 let fn_sig = match callee_ty.sty {
189 ty::TyFnDef(_, _, &ty::BareFnTy {ref sig, ..}) |
190 ty::TyFnPtr(&ty::BareFnTy {ref sig, ..}) => {
194 let mut err = self.type_error_struct(call_expr.span, |actual| {
195 format!("expected function, found `{}`", actual)
198 if let hir::ExprCall(ref expr, _) = call_expr.node {
200 if let Some(pr) = tcx.def_map.borrow().get(&expr.id) {
201 if pr.depth == 0 && pr.base_def != Def::Err {
202 if let Some(span) = tcx.map.span_if_local(pr.base_def.def_id()) {
203 err.span_note(span, "defined here");
211 // This is the "default" function signature, used in case of error.
212 // In that case, we check each argument against "error" in order to
213 // set up all the node type bindings.
214 error_fn_sig = ty::Binder(ty::FnSig {
215 inputs: self.err_args(arg_exprs.len()),
216 output: ty::FnConverging(self.tcx.types.err),
224 // Replace any late-bound regions that appear in the function
225 // signature with region variables. We also have to
226 // renormalize the associated types at this point, since they
227 // previously appeared within a `Binder<>` and hence would not
228 // have been normalized before.
230 self.replace_late_bound_regions_with_fresh_var(call_expr.span,
234 self.normalize_associated_types_in(call_expr.span, &fn_sig);
236 // Call the generic checker.
237 let expected_arg_tys = self.expected_types_for_fn_args(call_expr.span,
241 self.check_argument_types(call_expr.span,
243 &expected_arg_tys[..],
246 TupleArgumentsFlag::DontTupleArguments);
248 self.write_call(call_expr, fn_sig.output);
251 fn confirm_deferred_closure_call(&self,
252 call_expr: &hir::Expr,
253 arg_exprs: &'gcx [P<hir::Expr>],
254 expected: Expectation<'tcx>,
255 fn_sig: ty::FnSig<'tcx>)
257 // `fn_sig` is the *signature* of the cosure being called. We
258 // don't know the full details yet (`Fn` vs `FnMut` etc), but we
259 // do know the types expected for each argument and the return
262 let expected_arg_tys =
263 self.expected_types_for_fn_args(call_expr.span,
265 fn_sig.output.clone(),
268 self.check_argument_types(call_expr.span,
273 TupleArgumentsFlag::TupleArguments);
275 self.write_call(call_expr, fn_sig.output);
278 fn confirm_overloaded_call(&self,
279 call_expr: &hir::Expr,
280 callee_expr: &'gcx hir::Expr,
281 arg_exprs: &'gcx [P<hir::Expr>],
282 expected: Expectation<'tcx>,
283 method_callee: ty::MethodCallee<'tcx>)
286 self.check_method_argument_types(call_expr.span,
290 TupleArgumentsFlag::TupleArguments,
292 self.write_call(call_expr, output_type);
294 self.write_overloaded_call_method_map(call_expr, method_callee);
297 fn write_overloaded_call_method_map(&self,
298 call_expr: &hir::Expr,
299 method_callee: ty::MethodCallee<'tcx>) {
300 let method_call = ty::MethodCall::expr(call_expr.id);
301 self.tables.borrow_mut().method_map.insert(method_call, method_callee);
306 struct CallResolution<'gcx: 'tcx, 'tcx> {
307 call_expr: &'gcx hir::Expr,
308 callee_expr: &'gcx hir::Expr,
309 adjusted_ty: Ty<'tcx>,
311 fn_sig: ty::FnSig<'tcx>,
312 closure_def_id: DefId,
315 impl<'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> for CallResolution<'gcx, 'tcx> {
316 fn resolve<'a>(&mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
317 debug!("DeferredCallResolution::resolve() {:?}",
320 // we should not be invoked until the closure kind has been
321 // determined by upvar inference
322 assert!(fcx.closure_kind(self.closure_def_id).is_some());
324 // We may now know enough to figure out fn vs fnmut etc.
325 match fcx.try_overloaded_call_traits(self.call_expr, self.callee_expr,
326 self.adjusted_ty, self.autoderefs) {
327 Some(method_callee) => {
328 // One problem is that when we get here, we are going
329 // to have a newly instantiated function signature
330 // from the call trait. This has to be reconciled with
331 // the older function signature we had before. In
332 // principle we *should* be able to fn_sigs(), but we
333 // can't because of the annoying need for a TypeTrace.
334 // (This always bites me, should find a way to
336 let method_sig = fcx.tcx.no_late_bound_regions(method_callee.ty.fn_sig())
339 debug!("attempt_resolution: method_callee={:?}",
342 for (&method_arg_ty, &self_arg_ty) in
343 method_sig.inputs[1..].iter().zip(&self.fn_sig.inputs)
345 fcx.demand_eqtype(self.call_expr.span, self_arg_ty, method_arg_ty);
348 let nilty = fcx.tcx.mk_nil();
349 fcx.demand_eqtype(self.call_expr.span,
350 method_sig.output.unwrap_or(nilty),
351 self.fn_sig.output.unwrap_or(nilty));
353 fcx.write_overloaded_call_method_map(self.call_expr, method_callee);
358 "failed to find an overloaded call trait for closure call");