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, 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, LvaluePreference, Ty};
19 use rustc::ty::subst::Subst;
20 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
22 use syntax::symbol::Symbol;
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 Overloaded(MethodCallee<'tcx>),
44 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
45 pub fn check_call(&self,
46 call_expr: &'gcx hir::Expr,
47 callee_expr: &'gcx hir::Expr,
48 arg_exprs: &'gcx [hir::Expr],
49 expected: Expectation<'tcx>)
51 let original_callee_ty = self.check_expr(callee_expr);
52 let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty);
54 let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
55 let mut result = None;
56 while result.is_none() && autoderef.next().is_some() {
57 result = self.try_overloaded_call_step(call_expr, callee_expr, &autoderef);
61 let output = match result {
63 // this will report an error since original_callee_ty is not a fn
64 self.confirm_builtin_call(call_expr, original_callee_ty, arg_exprs, expected)
67 Some(CallStep::Builtin(callee_ty)) => {
68 self.confirm_builtin_call(call_expr, callee_ty, arg_exprs, expected)
71 Some(CallStep::DeferredClosure(fn_sig)) => {
72 self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, fn_sig)
75 Some(CallStep::Overloaded(method_callee)) => {
76 self.confirm_overloaded_call(call_expr, arg_exprs, expected, method_callee)
80 // we must check that return type of called functions is WF:
81 self.register_wf_obligation(output, call_expr.span, traits::MiscObligation);
86 fn try_overloaded_call_step(&self,
87 call_expr: &'gcx hir::Expr,
88 callee_expr: &'gcx hir::Expr,
89 autoderef: &Autoderef<'a, 'gcx, 'tcx>)
90 -> Option<CallStep<'tcx>> {
91 let adjusted_ty = autoderef.unambiguous_final_ty();
92 debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})",
96 // If the callee is a bare function or a closure, then we're all set.
97 match adjusted_ty.sty {
98 ty::TyFnDef(..) | ty::TyFnPtr(_) => {
99 let adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference);
100 self.apply_adjustments(callee_expr, adjustments);
101 return Some(CallStep::Builtin(adjusted_ty));
104 ty::TyClosure(def_id, substs) => {
105 assert_eq!(def_id.krate, LOCAL_CRATE);
107 // Check whether this is a call to a closure where we
108 // haven't yet decided on whether the closure is fn vs
109 // fnmut vs fnonce. If so, we have to defer further processing.
110 if self.closure_kind(def_id).is_none() {
111 let closure_ty = self.fn_sig(def_id).subst(self.tcx, substs.substs);
112 let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
116 let adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference);
117 self.record_deferred_call_resolution(def_id, DeferredCallResolution {
123 closure_def_id: def_id,
125 return Some(CallStep::DeferredClosure(fn_sig));
129 // Hack: we know that there are traits implementing Fn for &F
130 // where F:Fn and so forth. In the particular case of types
131 // like `x: &mut FnMut()`, if there is a call `x()`, we would
132 // normally translate to `FnMut::call_mut(&mut x, ())`, but
133 // that winds up requiring `mut x: &mut FnMut()`. A little
134 // over the top. The simplest fix by far is to just ignore
135 // this case and deref again, so we wind up with
136 // `FnMut::call_mut(&mut *x, ())`.
137 ty::TyRef(..) if autoderef.step_count() == 0 => {
144 self.try_overloaded_call_traits(call_expr, adjusted_ty).map(|(autoref, method)| {
145 let mut adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference);
146 adjustments.extend(autoref);
147 self.apply_adjustments(callee_expr, adjustments);
148 CallStep::Overloaded(method)
152 fn try_overloaded_call_traits(&self,
153 call_expr: &hir::Expr,
154 adjusted_ty: Ty<'tcx>)
155 -> Option<(Option<Adjustment<'tcx>>,
156 MethodCallee<'tcx>)> {
157 // Try the options that are least restrictive on the caller first.
158 for &(opt_trait_def_id, method_name, borrow) in
159 &[(self.tcx.lang_items.fn_trait(), Symbol::intern("call"), true),
160 (self.tcx.lang_items.fn_mut_trait(), Symbol::intern("call_mut"), true),
161 (self.tcx.lang_items.fn_once_trait(), Symbol::intern("call_once"), false)] {
162 let trait_def_id = match opt_trait_def_id {
163 Some(def_id) => def_id,
167 match self.lookup_method_in_trait(call_expr.span,
174 let method = self.register_infer_ok_obligations(ok);
175 let mut autoref = None;
177 if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty {
178 autoref = Some(Adjustment {
179 kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)),
180 target: method.sig.inputs()[0]
184 return Some((autoref, method));
192 fn confirm_builtin_call(&self,
193 call_expr: &hir::Expr,
195 arg_exprs: &'gcx [hir::Expr],
196 expected: Expectation<'tcx>)
198 let (fn_sig, def_span) = match callee_ty.sty {
199 ty::TyFnDef(def_id, _) => {
200 (callee_ty.fn_sig(self.tcx), self.tcx.hir.span_if_local(def_id))
202 ty::TyFnPtr(sig) => (sig, None),
204 let mut unit_variant = None;
205 if let &ty::TyAdt(adt_def, ..) = t {
206 if adt_def.is_enum() {
207 if let hir::ExprCall(ref expr, _) = call_expr.node {
208 unit_variant = Some(self.tcx.hir.node_to_pretty_string(expr.id))
212 let mut err = type_error_struct!(self.tcx.sess, call_expr.span, callee_ty, E0618,
213 "expected function, found `{}`",
214 if let Some(ref path) = unit_variant {
217 callee_ty.to_string()
219 if let Some(path) = unit_variant {
220 err.help(&format!("did you mean to write `{}`?", path));
223 if let hir::ExprCall(ref expr, _) = call_expr.node {
224 let def = if let hir::ExprPath(ref qpath) = expr.node {
225 self.tables.borrow().qpath_def(qpath, expr.hir_id)
230 if let Some(span) = self.tcx.hir.span_if_local(def.def_id()) {
231 err.span_note(span, "defined here");
238 // This is the "default" function signature, used in case of error.
239 // In that case, we check each argument against "error" in order to
240 // set up all the node type bindings.
241 (ty::Binder(self.tcx.mk_fn_sig(
242 self.err_args(arg_exprs.len()).into_iter(),
245 hir::Unsafety::Normal,
251 // Replace any late-bound regions that appear in the function
252 // signature with region variables. We also have to
253 // renormalize the associated types at this point, since they
254 // previously appeared within a `Binder<>` and hence would not
255 // have been normalized before.
257 self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, &fn_sig)
259 let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig);
261 // Call the generic checker.
262 let expected_arg_tys =
263 self.expected_inputs_for_expected_output(call_expr.span,
267 self.check_argument_types(call_expr.span,
269 &expected_arg_tys[..],
272 TupleArgumentsFlag::DontTupleArguments,
278 fn confirm_deferred_closure_call(&self,
279 call_expr: &hir::Expr,
280 arg_exprs: &'gcx [hir::Expr],
281 expected: Expectation<'tcx>,
282 fn_sig: ty::FnSig<'tcx>)
284 // `fn_sig` is the *signature* of the cosure being called. We
285 // don't know the full details yet (`Fn` vs `FnMut` etc), but we
286 // do know the types expected for each argument and the return
289 let expected_arg_tys = self.expected_inputs_for_expected_output(call_expr.span,
291 fn_sig.output().clone(),
294 self.check_argument_types(call_expr.span,
299 TupleArgumentsFlag::TupleArguments,
305 fn confirm_overloaded_call(&self,
306 call_expr: &hir::Expr,
307 arg_exprs: &'gcx [hir::Expr],
308 expected: Expectation<'tcx>,
309 method_callee: MethodCallee<'tcx>)
311 let output_type = self.check_method_argument_types(call_expr.span,
314 TupleArgumentsFlag::TupleArguments,
317 self.write_method_call(call_expr.hir_id, method_callee);
323 pub struct DeferredCallResolution<'gcx: 'tcx, 'tcx> {
324 call_expr: &'gcx hir::Expr,
325 callee_expr: &'gcx hir::Expr,
326 adjusted_ty: Ty<'tcx>,
327 adjustments: Vec<Adjustment<'tcx>>,
328 fn_sig: ty::FnSig<'tcx>,
329 closure_def_id: DefId,
332 impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> {
333 pub fn resolve(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
334 debug!("DeferredCallResolution::resolve() {:?}", self);
336 // we should not be invoked until the closure kind has been
337 // determined by upvar inference
338 assert!(fcx.closure_kind(self.closure_def_id).is_some());
340 // We may now know enough to figure out fn vs fnmut etc.
341 match fcx.try_overloaded_call_traits(self.call_expr,
343 Some((autoref, method_callee)) => {
344 // One problem is that when we get here, we are going
345 // to have a newly instantiated function signature
346 // from the call trait. This has to be reconciled with
347 // the older function signature we had before. In
348 // principle we *should* be able to fn_sigs(), but we
349 // can't because of the annoying need for a TypeTrace.
350 // (This always bites me, should find a way to
352 let method_sig = method_callee.sig;
354 debug!("attempt_resolution: method_callee={:?}", method_callee);
356 for (method_arg_ty, self_arg_ty) in
357 method_sig.inputs().iter().skip(1).zip(self.fn_sig.inputs()) {
358 fcx.demand_eqtype(self.call_expr.span, &self_arg_ty, &method_arg_ty);
361 fcx.demand_eqtype(self.call_expr.span, method_sig.output(), self.fn_sig.output());
363 let mut adjustments = self.adjustments;
364 adjustments.extend(autoref);
365 fcx.apply_adjustments(self.callee_expr, adjustments);
367 fcx.write_method_call(self.call_expr.hir_id,
371 span_bug!(self.call_expr.span,
372 "failed to find an overloaded call trait for closure call");