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, TupleArgumentsFlag};
14 use hir::def_id::{DefId, LOCAL_CRATE};
15 use rustc::{infer, traits};
16 use rustc::ty::{self, TyCtxt, LvaluePreference, Ty};
17 use rustc::ty::subst::Subst;
19 use syntax::symbol::Symbol;
24 /// Check that it is legal to call methods of the trait corresponding
25 /// to `trait_id` (this only cares about the trait, not the specific
26 /// method that is called)
27 pub fn check_legal_trait_for_method_call(tcx: TyCtxt, span: Span, trait_id: DefId) {
28 if tcx.lang_items.drop_trait() == Some(trait_id) {
29 struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method")
30 .span_label(span, &format!("explicit destructor calls not allowed"))
37 DeferredClosure(ty::FnSig<'tcx>),
38 Overloaded(ty::MethodCallee<'tcx>),
41 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
42 pub fn check_call(&self,
43 call_expr: &'gcx hir::Expr,
44 callee_expr: &'gcx hir::Expr,
45 arg_exprs: &'gcx [hir::Expr],
46 expected: Expectation<'tcx>)
48 let original_callee_ty = self.check_expr(callee_expr);
49 let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty);
51 let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
52 let result = autoderef.by_ref()
53 .flat_map(|(adj_ty, idx)| {
54 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, callee_expr);
60 let output = match result {
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,
83 // we must check that return type of called functions is WF:
84 self.register_wf_obligation(output, call_expr.span, traits::MiscObligation);
89 fn try_overloaded_call_step(&self,
90 call_expr: &'gcx hir::Expr,
91 callee_expr: &'gcx hir::Expr,
92 adjusted_ty: Ty<'tcx>,
94 -> Option<CallStep<'tcx>> {
95 debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?}, autoderefs={})",
100 // If the callee is a bare function or a closure, then we're all set.
101 match self.structurally_resolved_type(callee_expr.span, adjusted_ty).sty {
102 ty::TyFnDef(..) | ty::TyFnPtr(_) => {
103 self.apply_autoderef_adjustment(callee_expr.id, autoderefs, adjusted_ty);
104 return Some(CallStep::Builtin);
107 ty::TyClosure(def_id, substs) => {
108 assert_eq!(def_id.krate, LOCAL_CRATE);
110 // Check whether this is a call to a closure where we
111 // haven't yet decided on whether the closure is fn vs
112 // fnmut vs fnonce. If so, we have to defer further processing.
113 if self.closure_kind(def_id).is_none() {
114 let closure_ty = self.closure_type(def_id).subst(self.tcx, substs.substs);
115 let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
119 self.record_deferred_call_resolution(def_id,
120 Box::new(CallResolution {
121 call_expr: call_expr,
122 callee_expr: callee_expr,
123 adjusted_ty: adjusted_ty,
124 autoderefs: autoderefs,
125 fn_sig: fn_sig.clone(),
126 closure_def_id: def_id,
128 return Some(CallStep::DeferredClosure(fn_sig));
132 // Hack: we know that there are traits implementing Fn for &F
133 // where F:Fn and so forth. In the particular case of types
134 // like `x: &mut FnMut()`, if there is a call `x()`, we would
135 // normally translate to `FnMut::call_mut(&mut x, ())`, but
136 // that winds up requiring `mut x: &mut FnMut()`. A little
137 // over the top. The simplest fix by far is to just ignore
138 // this case and deref again, so we wind up with
139 // `FnMut::call_mut(&mut *x, ())`.
140 ty::TyRef(..) if autoderefs == 0 => {
147 self.try_overloaded_call_traits(call_expr, callee_expr, adjusted_ty, autoderefs)
148 .map(|method_callee| CallStep::Overloaded(method_callee))
151 fn try_overloaded_call_traits(&self,
152 call_expr: &hir::Expr,
153 callee_expr: &hir::Expr,
154 adjusted_ty: Ty<'tcx>,
156 -> Option<ty::MethodCallee<'tcx>> {
157 // Try the options that are least restrictive on the caller first.
158 for &(opt_trait_def_id, method_name) in
159 &[(self.tcx.lang_items.fn_trait(), Symbol::intern("call")),
160 (self.tcx.lang_items.fn_mut_trait(), Symbol::intern("call_mut")),
161 (self.tcx.lang_items.fn_once_trait(), Symbol::intern("call_once"))] {
162 let trait_def_id = match opt_trait_def_id {
163 Some(def_id) => def_id,
167 match self.lookup_method_in_trait_adjusted(call_expr.span,
168 Some(super::AdjustedRcvr {
169 rcvr_expr: callee_expr,
179 let method_callee = self.register_infer_ok_obligations(ok);
180 return Some(method_callee);
188 fn confirm_builtin_call(&self,
189 call_expr: &hir::Expr,
191 arg_exprs: &'gcx [hir::Expr],
192 expected: Expectation<'tcx>)
194 let (fn_sig, def_span) = match callee_ty.sty {
195 ty::TyFnDef(def_id, .., sig) => {
196 (sig, self.tcx.hir.span_if_local(def_id))
198 ty::TyFnPtr(sig) => (sig, None),
200 let mut unit_variant = None;
201 if let &ty::TyAdt(adt_def, ..) = t {
202 if adt_def.is_enum() {
203 if let hir::ExprCall(ref expr, _) = call_expr.node {
204 unit_variant = Some(self.tcx.hir.node_to_pretty_string(expr.id))
208 let mut err = if let Some(path) = unit_variant {
209 let mut err = self.type_error_struct(call_expr.span, |_| {
210 format!("`{}` is being called, but it is not a function", path)
212 err.help(&format!("did you mean to write `{}`?", path));
215 self.type_error_struct(call_expr.span, |actual| {
216 format!("expected function, found `{}`", actual)
220 if let hir::ExprCall(ref expr, _) = call_expr.node {
221 let def = if let hir::ExprPath(ref qpath) = expr.node {
222 self.tables.borrow().qpath_def(qpath, expr.id)
227 if let Some(span) = self.tcx.hir.span_if_local(def.def_id()) {
228 err.span_note(span, "defined here");
235 // This is the "default" function signature, used in case of error.
236 // In that case, we check each argument against "error" in order to
237 // set up all the node type bindings.
238 (ty::Binder(self.tcx.mk_fn_sig(
239 self.err_args(arg_exprs.len()).into_iter(),
242 hir::Unsafety::Normal,
248 // Replace any late-bound regions that appear in the function
249 // signature with region variables. We also have to
250 // renormalize the associated types at this point, since they
251 // previously appeared within a `Binder<>` and hence would not
252 // have been normalized before.
254 self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, &fn_sig)
256 let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig);
258 // Call the generic checker.
259 let expected_arg_tys =
260 self.expected_inputs_for_expected_output(call_expr.span,
264 self.check_argument_types(call_expr.span,
266 &expected_arg_tys[..],
269 TupleArgumentsFlag::DontTupleArguments,
275 fn confirm_deferred_closure_call(&self,
276 call_expr: &hir::Expr,
277 arg_exprs: &'gcx [hir::Expr],
278 expected: Expectation<'tcx>,
279 fn_sig: ty::FnSig<'tcx>)
281 // `fn_sig` is the *signature* of the cosure being called. We
282 // don't know the full details yet (`Fn` vs `FnMut` etc), but we
283 // do know the types expected for each argument and the return
286 let expected_arg_tys = self.expected_inputs_for_expected_output(call_expr.span,
288 fn_sig.output().clone(),
291 self.check_argument_types(call_expr.span,
296 TupleArgumentsFlag::TupleArguments,
302 fn confirm_overloaded_call(&self,
303 call_expr: &hir::Expr,
304 callee_expr: &'gcx hir::Expr,
305 arg_exprs: &'gcx [hir::Expr],
306 expected: Expectation<'tcx>,
307 method_callee: ty::MethodCallee<'tcx>)
309 let output_type = self.check_method_argument_types(call_expr.span,
313 TupleArgumentsFlag::TupleArguments,
316 self.write_overloaded_call_method_map(call_expr, method_callee);
320 fn write_overloaded_call_method_map(&self,
321 call_expr: &hir::Expr,
322 method_callee: ty::MethodCallee<'tcx>) {
323 let method_call = ty::MethodCall::expr(call_expr.id);
324 self.tables.borrow_mut().method_map.insert(method_call, method_callee);
329 struct CallResolution<'gcx: 'tcx, 'tcx> {
330 call_expr: &'gcx hir::Expr,
331 callee_expr: &'gcx hir::Expr,
332 adjusted_ty: Ty<'tcx>,
334 fn_sig: ty::FnSig<'tcx>,
335 closure_def_id: DefId,
338 impl<'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> for CallResolution<'gcx, 'tcx> {
339 fn resolve<'a>(&mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
340 debug!("DeferredCallResolution::resolve() {:?}", self);
342 // we should not be invoked until the closure kind has been
343 // determined by upvar inference
344 assert!(fcx.closure_kind(self.closure_def_id).is_some());
346 // We may now know enough to figure out fn vs fnmut etc.
347 match fcx.try_overloaded_call_traits(self.call_expr,
351 Some(method_callee) => {
352 // One problem is that when we get here, we are going
353 // to have a newly instantiated function signature
354 // from the call trait. This has to be reconciled with
355 // the older function signature we had before. In
356 // principle we *should* be able to fn_sigs(), but we
357 // can't because of the annoying need for a TypeTrace.
358 // (This always bites me, should find a way to
360 let method_sig = fcx.tcx
361 .no_late_bound_regions(&method_callee.ty.fn_sig())
364 debug!("attempt_resolution: method_callee={:?}", method_callee);
366 for (method_arg_ty, self_arg_ty) in
367 method_sig.inputs().iter().skip(1).zip(self.fn_sig.inputs()) {
368 fcx.demand_eqtype(self.call_expr.span, &self_arg_ty, &method_arg_ty);
371 fcx.demand_eqtype(self.call_expr.span, method_sig.output(), self.fn_sig.output());
373 fcx.write_overloaded_call_method_map(self.call_expr, method_callee);
376 span_bug!(self.call_expr.span,
377 "failed to find an overloaded call trait for closure call");