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::{Expectation, FnCtxt, Needs, TupleArgumentsFlag};
12 use super::autoderef::Autoderef;
13 use super::method::MethodCallee;
16 use hir::def_id::{DefId, LOCAL_CRATE};
17 use rustc::{infer, traits};
18 use rustc::ty::{self, TyCtxt, TypeFoldable, Ty};
19 use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
20 use rustc_target::spec::abi;
21 use syntax::ast::Ident;
23 use errors::Applicability;
27 /// Check that it is legal to call methods of the trait corresponding
28 /// to `trait_id` (this only cares about the trait, not the specific
29 /// method that is called)
30 pub fn check_legal_trait_for_method_call(tcx: TyCtxt, span: Span, trait_id: DefId) {
31 if tcx.lang_items().drop_trait() == Some(trait_id) {
32 struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method")
33 .span_label(span, "explicit destructor calls not allowed")
40 DeferredClosure(ty::FnSig<'tcx>),
41 /// e.g. enum variant constructors
42 Overloaded(MethodCallee<'tcx>),
45 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
46 pub fn check_call(&self,
47 call_expr: &'gcx hir::Expr,
48 callee_expr: &'gcx hir::Expr,
49 arg_exprs: &'gcx [hir::Expr],
50 expected: Expectation<'tcx>)
52 let original_callee_ty = self.check_expr(callee_expr);
53 let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty);
55 let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
56 let mut result = None;
57 while result.is_none() && autoderef.next().is_some() {
58 result = self.try_overloaded_call_step(call_expr, callee_expr, &autoderef);
62 let output = match result {
64 // this will report an error since original_callee_ty is not a fn
65 self.confirm_builtin_call(call_expr, original_callee_ty, arg_exprs, expected)
68 Some(CallStep::Builtin(callee_ty)) => {
69 self.confirm_builtin_call(call_expr, callee_ty, arg_exprs, expected)
72 Some(CallStep::DeferredClosure(fn_sig)) => {
73 self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, fn_sig)
76 Some(CallStep::Overloaded(method_callee)) => {
77 self.confirm_overloaded_call(call_expr, arg_exprs, expected, method_callee)
81 // we must check that return type of called functions is WF:
82 self.register_wf_obligation(output, call_expr.span, traits::MiscObligation);
87 fn try_overloaded_call_step(&self,
88 call_expr: &'gcx hir::Expr,
89 callee_expr: &'gcx hir::Expr,
90 autoderef: &Autoderef<'a, 'gcx, 'tcx>)
91 -> Option<CallStep<'tcx>> {
92 let adjusted_ty = autoderef.unambiguous_final_ty();
93 debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})",
97 // If the callee is a bare function or a closure, then we're all set.
98 match adjusted_ty.sty {
99 ty::FnDef(..) | ty::FnPtr(_) => {
100 let adjustments = autoderef.adjust_steps(Needs::None);
101 self.apply_adjustments(callee_expr, adjustments);
102 return Some(CallStep::Builtin(adjusted_ty));
105 ty::Closure(def_id, substs) => {
106 assert_eq!(def_id.krate, LOCAL_CRATE);
108 // Check whether this is a call to a closure where we
109 // haven't yet decided on whether the closure is fn vs
110 // fnmut vs fnonce. If so, we have to defer further processing.
111 if self.closure_kind(def_id, substs).is_none() {
112 let closure_ty = self.closure_sig(def_id, substs);
113 let fn_sig = self.replace_bound_vars_with_fresh_vars(
118 let adjustments = autoderef.adjust_steps(Needs::None);
119 self.record_deferred_call_resolution(def_id, DeferredCallResolution {
125 closure_def_id: def_id,
126 closure_substs: substs,
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::Ref(..) if autoderef.step_count() == 0 => {
147 self.try_overloaded_call_traits(call_expr, adjusted_ty).map(|(autoref, method)| {
148 let mut adjustments = autoderef.adjust_steps(Needs::None);
149 adjustments.extend(autoref);
150 self.apply_adjustments(callee_expr, adjustments);
151 CallStep::Overloaded(method)
155 fn try_overloaded_call_traits(&self,
156 call_expr: &hir::Expr,
157 adjusted_ty: Ty<'tcx>)
158 -> Option<(Option<Adjustment<'tcx>>,
159 MethodCallee<'tcx>)> {
160 // Try the options that are least restrictive on the caller first.
161 for &(opt_trait_def_id, method_name, borrow) in
162 &[(self.tcx.lang_items().fn_trait(), Ident::from_str("call"), true),
163 (self.tcx.lang_items().fn_mut_trait(), Ident::from_str("call_mut"), true),
164 (self.tcx.lang_items().fn_once_trait(), Ident::from_str("call_once"), false)] {
165 let trait_def_id = match opt_trait_def_id {
166 Some(def_id) => def_id,
170 if let Some(ok) = self.lookup_method_in_trait(call_expr.span,
175 let method = self.register_infer_ok_obligations(ok);
176 let mut autoref = None;
178 if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].sty {
179 let mutbl = match mutbl {
180 hir::MutImmutable => AutoBorrowMutability::Immutable,
181 hir::MutMutable => AutoBorrowMutability::Mutable {
182 // For initial two-phase borrow
183 // deployment, conservatively omit
184 // overloaded function call ops.
185 allow_two_phase_borrow: AllowTwoPhase::No,
188 autoref = Some(Adjustment {
189 kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
190 target: method.sig.inputs()[0]
194 return Some((autoref, method));
201 fn confirm_builtin_call(&self,
202 call_expr: &hir::Expr,
204 arg_exprs: &'gcx [hir::Expr],
205 expected: Expectation<'tcx>)
207 let (fn_sig, def_span) = match callee_ty.sty {
208 ty::FnDef(def_id, _) => {
209 (callee_ty.fn_sig(self.tcx), self.tcx.hir().span_if_local(def_id))
211 ty::FnPtr(sig) => (sig, None),
213 let mut unit_variant = None;
214 if let &ty::Adt(adt_def, ..) = t {
215 if adt_def.is_enum() {
216 if let hir::ExprKind::Call(ref expr, _) = call_expr.node {
217 unit_variant = Some(self.tcx.hir().node_to_pretty_string(expr.id))
222 if let hir::ExprKind::Call(ref callee, _) = call_expr.node {
223 let mut err = type_error_struct!(
228 "expected function, found {}",
230 Some(ref path) => format!("enum variant `{}`", path),
231 None => format!("`{}`", callee_ty),
234 if let Some(ref path) = unit_variant {
235 err.span_suggestion_with_applicability(
237 &format!("`{}` is a unit variant, you need to write it \
238 without the parenthesis", path),
240 Applicability::MachineApplicable
244 let mut inner_callee_path = None;
245 let def = match callee.node {
246 hir::ExprKind::Path(ref qpath) => {
247 self.tables.borrow().qpath_def(qpath, callee.hir_id)
249 hir::ExprKind::Call(ref inner_callee, _) => {
250 // If the call spans more than one line and the callee kind is
251 // itself another `ExprCall`, that's a clue that we might just be
252 // missing a semicolon (Issue #51055)
253 let call_is_multiline = self.tcx.sess.source_map()
254 .is_multiline(call_expr.span);
255 if call_is_multiline {
256 let span = self.tcx.sess.source_map().next_point(callee.span);
257 err.span_suggestion_with_applicability(
259 "try adding a semicolon",
261 Applicability::MaybeIncorrect
264 if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.node {
265 inner_callee_path = Some(inner_qpath);
266 self.tables.borrow().qpath_def(inner_qpath, inner_callee.hir_id)
276 err.span_label(call_expr.span, "call expression requires function");
278 let def_span = match def {
280 Def::Local(id) | Def::Upvar(id, ..) => {
281 Some(self.tcx.hir().span(id))
283 _ => self.tcx.hir().span_if_local(def.def_id())
285 if let Some(span) = def_span {
286 let label = match (unit_variant, inner_callee_path) {
287 (Some(path), _) => format!("`{}` defined here", path),
288 (_, Some(hir::QPath::Resolved(_, path))) => format!(
289 "`{}` defined here returns `{}`", path, callee_ty.to_string()
291 _ => format!("`{}` defined here", callee_ty.to_string()),
293 err.span_label(span, label);
297 bug!("call_expr.node should be an ExprKind::Call, got {:?}", call_expr.node);
300 // This is the "default" function signature, used in case of error.
301 // In that case, we check each argument against "error" in order to
302 // set up all the node type bindings.
303 (ty::Binder::bind(self.tcx.mk_fn_sig(
304 self.err_args(arg_exprs.len()).into_iter(),
307 hir::Unsafety::Normal,
313 // Replace any late-bound regions that appear in the function
314 // signature with region variables. We also have to
315 // renormalize the associated types at this point, since they
316 // previously appeared within a `Binder<>` and hence would not
317 // have been normalized before.
319 self.replace_bound_vars_with_fresh_vars(call_expr.span, infer::FnCall, &fn_sig)
321 let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig);
323 // Call the generic checker.
324 let expected_arg_tys =
325 self.expected_inputs_for_expected_output(call_expr.span,
329 self.check_argument_types(call_expr.span,
332 &expected_arg_tys[..],
335 TupleArgumentsFlag::DontTupleArguments,
341 fn confirm_deferred_closure_call(&self,
342 call_expr: &hir::Expr,
343 arg_exprs: &'gcx [hir::Expr],
344 expected: Expectation<'tcx>,
345 fn_sig: ty::FnSig<'tcx>)
347 // `fn_sig` is the *signature* of the cosure being called. We
348 // don't know the full details yet (`Fn` vs `FnMut` etc), but we
349 // do know the types expected for each argument and the return
352 let expected_arg_tys = self.expected_inputs_for_expected_output(call_expr.span,
354 fn_sig.output().clone(),
357 self.check_argument_types(call_expr.span,
363 TupleArgumentsFlag::TupleArguments,
369 fn confirm_overloaded_call(&self,
370 call_expr: &hir::Expr,
371 arg_exprs: &'gcx [hir::Expr],
372 expected: Expectation<'tcx>,
373 method_callee: MethodCallee<'tcx>)
375 let output_type = self.check_method_argument_types(call_expr.span,
379 TupleArgumentsFlag::TupleArguments,
382 self.write_method_call(call_expr.hir_id, method_callee);
388 pub struct DeferredCallResolution<'gcx: 'tcx, 'tcx> {
389 call_expr: &'gcx hir::Expr,
390 callee_expr: &'gcx hir::Expr,
391 adjusted_ty: Ty<'tcx>,
392 adjustments: Vec<Adjustment<'tcx>>,
393 fn_sig: ty::FnSig<'tcx>,
394 closure_def_id: DefId,
395 closure_substs: ty::ClosureSubsts<'tcx>,
398 impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> {
399 pub fn resolve(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
400 debug!("DeferredCallResolution::resolve() {:?}", self);
402 // we should not be invoked until the closure kind has been
403 // determined by upvar inference
404 assert!(fcx.closure_kind(self.closure_def_id, self.closure_substs).is_some());
406 // We may now know enough to figure out fn vs fnmut etc.
407 match fcx.try_overloaded_call_traits(self.call_expr,
409 Some((autoref, method_callee)) => {
410 // One problem is that when we get here, we are going
411 // to have a newly instantiated function signature
412 // from the call trait. This has to be reconciled with
413 // the older function signature we had before. In
414 // principle we *should* be able to fn_sigs(), but we
415 // can't because of the annoying need for a TypeTrace.
416 // (This always bites me, should find a way to
418 let method_sig = method_callee.sig;
420 debug!("attempt_resolution: method_callee={:?}", method_callee);
422 for (method_arg_ty, self_arg_ty) in
423 method_sig.inputs().iter().skip(1).zip(self.fn_sig.inputs()) {
424 fcx.demand_eqtype(self.call_expr.span, &self_arg_ty, &method_arg_ty);
427 fcx.demand_eqtype(self.call_expr.span, method_sig.output(), self.fn_sig.output());
429 let mut adjustments = self.adjustments;
430 adjustments.extend(autoref);
431 fcx.apply_adjustments(self.callee_expr, adjustments);
433 fcx.write_method_call(self.call_expr.hir_id,
437 span_bug!(self.call_expr.span,
438 "failed to find an overloaded call trait for closure call");