]> git.proxmox.com Git - rustc.git/blame - src/librustc_typeck/check/callee.rs
New upstream version 1.14.0+dfsg1
[rustc.git] / src / librustc_typeck / check / callee.rs
CommitLineData
1a4d82fc
JJ
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.
4//
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.
10
c30ab7b3 11use super::{DeferredCallResolution, Expectation, FnCtxt, TupleArgumentsFlag};
1a4d82fc 12
85aaf69f 13use CrateCtxt;
54a0048b 14use hir::def::Def;
9e0c209e
SL
15use hir::def_id::{DefId, LOCAL_CRATE};
16use rustc::{infer, traits};
54a0048b 17use rustc::ty::{self, LvaluePreference, Ty};
1a4d82fc
JJ
18use syntax::parse::token;
19use syntax::ptr::P;
3157f602 20use syntax_pos::Span;
1a4d82fc 21
54a0048b 22use rustc::hir;
e9174d1e 23
1a4d82fc
JJ
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)
e9174d1e 27pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: DefId) {
5bcae85e 28 if ccx.tcx.lang_items.drop_trait() == Some(trait_id) {
c30ab7b3
SL
29 struct_span_err!(ccx.tcx.sess,
30 span,
31 E0040,
32 "explicit use of destructor method")
9e0c209e 33 .span_label(span, &format!("explicit destructor calls not allowed"))
9cc50fc6 34 .emit();
1a4d82fc
JJ
35 }
36}
37
1a4d82fc
JJ
38enum CallStep<'tcx> {
39 Builtin,
85aaf69f 40 DeferredClosure(ty::FnSig<'tcx>),
c30ab7b3 41 Overloaded(ty::MethodCallee<'tcx>),
1a4d82fc
JJ
42}
43
a7813a04
XL
44impl<'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 [P<hir::Expr>],
c30ab7b3
SL
49 expected: Expectation<'tcx>)
50 -> Ty<'tcx> {
9e0c209e 51 let original_callee_ty = self.check_expr(callee_expr);
c30ab7b3
SL
52 let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty);
53
54 let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
55 let result = autoderef.by_ref()
56 .flat_map(|(adj_ty, idx)| {
57 self.try_overloaded_call_step(call_expr, callee_expr, adj_ty, idx)
58 })
59 .next();
3157f602
XL
60 let callee_ty = autoderef.unambiguous_final_ty();
61 autoderef.finalize(LvaluePreference::NoPreference, Some(callee_expr));
a7813a04 62
9e0c209e 63 let output = match result {
a7813a04
XL
64 None => {
65 // this will report an error since original_callee_ty is not a fn
9e0c209e 66 self.confirm_builtin_call(call_expr, original_callee_ty, arg_exprs, expected)
a7813a04 67 }
1a4d82fc 68
a7813a04 69 Some(CallStep::Builtin) => {
9e0c209e 70 self.confirm_builtin_call(call_expr, callee_ty, arg_exprs, expected)
85aaf69f 71 }
85aaf69f 72
a7813a04 73 Some(CallStep::DeferredClosure(fn_sig)) => {
9e0c209e 74 self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, fn_sig)
a7813a04 75 }
c34b1796 76
a7813a04 77 Some(CallStep::Overloaded(method_callee)) => {
c30ab7b3
SL
78 self.confirm_overloaded_call(call_expr,
79 callee_expr,
80 arg_exprs,
81 expected,
82 method_callee)
a7813a04 83 }
9e0c209e
SL
84 };
85
86 // we must check that return type of called functions is WF:
87 self.register_wf_obligation(output, call_expr.span, traits::MiscObligation);
88
89 output
1a4d82fc
JJ
90 }
91
a7813a04
XL
92 fn try_overloaded_call_step(&self,
93 call_expr: &'gcx hir::Expr,
94 callee_expr: &'gcx hir::Expr,
95 adjusted_ty: Ty<'tcx>,
96 autoderefs: usize)
c30ab7b3 97 -> Option<CallStep<'tcx>> {
a7813a04
XL
98 debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?}, autoderefs={})",
99 call_expr,
100 adjusted_ty,
101 autoderefs);
102
103 // If the callee is a bare function or a closure, then we're all set.
104 match self.structurally_resolved_type(callee_expr.span, adjusted_ty).sty {
105 ty::TyFnDef(..) | ty::TyFnPtr(_) => {
c30ab7b3 106 self.write_autoderef_adjustment(callee_expr.id, autoderefs, adjusted_ty);
a7813a04
XL
107 return Some(CallStep::Builtin);
108 }
85aaf69f 109
a7813a04
XL
110 ty::TyClosure(def_id, substs) => {
111 assert_eq!(def_id.krate, LOCAL_CRATE);
112
113 // Check whether this is a call to a closure where we
114 // haven't yet decided on whether the closure is fn vs
115 // fnmut vs fnonce. If so, we have to defer further processing.
116 if self.closure_kind(def_id).is_none() {
c30ab7b3
SL
117 let closure_ty = self.closure_type(def_id, substs);
118 let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
119 infer::FnCall,
120 &closure_ty.sig)
121 .0;
122 self.record_deferred_call_resolution(def_id,
123 Box::new(CallResolution {
124 call_expr: call_expr,
125 callee_expr: callee_expr,
126 adjusted_ty: adjusted_ty,
127 autoderefs: autoderefs,
128 fn_sig: fn_sig.clone(),
129 closure_def_id: def_id,
130 }));
a7813a04
XL
131 return Some(CallStep::DeferredClosure(fn_sig));
132 }
133 }
1a4d82fc 134
a7813a04
XL
135 // Hack: we know that there are traits implementing Fn for &F
136 // where F:Fn and so forth. In the particular case of types
137 // like `x: &mut FnMut()`, if there is a call `x()`, we would
138 // normally translate to `FnMut::call_mut(&mut x, ())`, but
139 // that winds up requiring `mut x: &mut FnMut()`. A little
140 // over the top. The simplest fix by far is to just ignore
141 // this case and deref again, so we wind up with
142 // `FnMut::call_mut(&mut *x, ())`.
143 ty::TyRef(..) if autoderefs == 0 => {
144 return None;
1a4d82fc 145 }
a7813a04
XL
146
147 _ => {}
1a4d82fc 148 }
1a4d82fc 149
a7813a04
XL
150 self.try_overloaded_call_traits(call_expr, callee_expr, adjusted_ty, autoderefs)
151 .map(|method_callee| CallStep::Overloaded(method_callee))
152 }
1a4d82fc 153
a7813a04
XL
154 fn try_overloaded_call_traits(&self,
155 call_expr: &hir::Expr,
156 callee_expr: &hir::Expr,
157 adjusted_ty: Ty<'tcx>,
158 autoderefs: usize)
c30ab7b3 159 -> Option<ty::MethodCallee<'tcx>> {
a7813a04 160 // Try the options that are least restrictive on the caller first.
c30ab7b3
SL
161 for &(opt_trait_def_id, method_name) in
162 &[(self.tcx.lang_items.fn_trait(), token::intern("call")),
163 (self.tcx.lang_items.fn_mut_trait(), token::intern("call_mut")),
164 (self.tcx.lang_items.fn_once_trait(), token::intern("call_once"))] {
a7813a04
XL
165 let trait_def_id = match opt_trait_def_id {
166 Some(def_id) => def_id,
167 None => continue,
168 };
169
170 match self.lookup_method_in_trait_adjusted(call_expr.span,
171 Some(&callee_expr),
172 method_name,
173 trait_def_id,
174 autoderefs,
175 false,
176 adjusted_ty,
177 None) {
178 None => continue,
179 Some(method_callee) => {
180 return Some(method_callee);
181 }
182 }
1a4d82fc 183 }
a7813a04
XL
184
185 None
186 }
187
188 fn confirm_builtin_call(&self,
189 call_expr: &hir::Expr,
190 callee_ty: Ty<'tcx>,
191 arg_exprs: &'gcx [P<hir::Expr>],
c30ab7b3
SL
192 expected: Expectation<'tcx>)
193 -> Ty<'tcx> {
a7813a04
XL
194 let error_fn_sig;
195
196 let fn_sig = match callee_ty.sty {
c30ab7b3
SL
197 ty::TyFnDef(.., &ty::BareFnTy { ref sig, .. }) |
198 ty::TyFnPtr(&ty::BareFnTy { ref sig, .. }) => sig,
a7813a04 199 _ => {
c30ab7b3
SL
200 let mut err = self.type_error_struct(call_expr.span,
201 |actual| {
202 format!("expected function, found `{}`",
203 actual)
204 },
205 callee_ty);
a7813a04
XL
206
207 if let hir::ExprCall(ref expr, _) = call_expr.node {
208 let tcx = self.tcx;
209 if let Some(pr) = tcx.def_map.borrow().get(&expr.id) {
210 if pr.depth == 0 && pr.base_def != Def::Err {
3157f602 211 if let Some(span) = tcx.map.span_if_local(pr.base_def.def_id()) {
a7813a04
XL
212 err.span_note(span, "defined here");
213 }
92a42be0
SL
214 }
215 }
216 }
92a42be0 217
a7813a04 218 err.emit();
9cc50fc6 219
a7813a04
XL
220 // This is the "default" function signature, used in case of error.
221 // In that case, we check each argument against "error" in order to
222 // set up all the node type bindings.
223 error_fn_sig = ty::Binder(ty::FnSig {
224 inputs: self.err_args(arg_exprs.len()),
5bcae85e 225 output: self.tcx.types.err,
c30ab7b3 226 variadic: false,
a7813a04 227 });
1a4d82fc 228
a7813a04
XL
229 &error_fn_sig
230 }
231 };
1a4d82fc 232
a7813a04
XL
233 // Replace any late-bound regions that appear in the function
234 // signature with region variables. We also have to
235 // renormalize the associated types at this point, since they
236 // previously appeared within a `Binder<>` and hence would not
237 // have been normalized before.
238 let fn_sig =
c30ab7b3
SL
239 self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, fn_sig)
240 .0;
241 let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig);
a7813a04
XL
242
243 // Call the generic checker.
c30ab7b3
SL
244 let expected_arg_tys =
245 self.expected_types_for_fn_args(call_expr.span,
246 expected,
247 fn_sig.output,
248 &fn_sig.inputs);
a7813a04
XL
249 self.check_argument_types(call_expr.span,
250 &fn_sig.inputs,
251 &expected_arg_tys[..],
252 arg_exprs,
253 fn_sig.variadic,
254 TupleArgumentsFlag::DontTupleArguments);
255
9e0c209e 256 fn_sig.output
a7813a04 257 }
85aaf69f 258
a7813a04
XL
259 fn confirm_deferred_closure_call(&self,
260 call_expr: &hir::Expr,
261 arg_exprs: &'gcx [P<hir::Expr>],
262 expected: Expectation<'tcx>,
c30ab7b3
SL
263 fn_sig: ty::FnSig<'tcx>)
264 -> Ty<'tcx> {
a7813a04
XL
265 // `fn_sig` is the *signature* of the cosure being called. We
266 // don't know the full details yet (`Fn` vs `FnMut` etc), but we
267 // do know the types expected for each argument and the return
268 // type.
269
c30ab7b3
SL
270 let expected_arg_tys = self.expected_types_for_fn_args(call_expr.span,
271 expected,
272 fn_sig.output.clone(),
273 &fn_sig.inputs);
a7813a04
XL
274
275 self.check_argument_types(call_expr.span,
276 &fn_sig.inputs,
277 &expected_arg_tys,
278 arg_exprs,
279 fn_sig.variadic,
280 TupleArgumentsFlag::TupleArguments);
281
9e0c209e 282 fn_sig.output
a7813a04 283 }
85aaf69f 284
a7813a04
XL
285 fn confirm_overloaded_call(&self,
286 call_expr: &hir::Expr,
287 callee_expr: &'gcx hir::Expr,
288 arg_exprs: &'gcx [P<hir::Expr>],
289 expected: Expectation<'tcx>,
c30ab7b3
SL
290 method_callee: ty::MethodCallee<'tcx>)
291 -> Ty<'tcx> {
292 let output_type = self.check_method_argument_types(call_expr.span,
293 method_callee.ty,
294 callee_expr,
295 arg_exprs,
296 TupleArgumentsFlag::TupleArguments,
297 expected);
a7813a04
XL
298
299 self.write_overloaded_call_method_map(call_expr, method_callee);
9e0c209e 300 output_type
a7813a04
XL
301 }
302
303 fn write_overloaded_call_method_map(&self,
304 call_expr: &hir::Expr,
305 method_callee: ty::MethodCallee<'tcx>) {
306 let method_call = ty::MethodCall::expr(call_expr.id);
307 self.tables.borrow_mut().method_map.insert(method_call, method_callee);
308 }
1a4d82fc
JJ
309}
310
62682a34 311#[derive(Debug)]
a7813a04
XL
312struct CallResolution<'gcx: 'tcx, 'tcx> {
313 call_expr: &'gcx hir::Expr,
314 callee_expr: &'gcx hir::Expr,
85aaf69f 315 adjusted_ty: Ty<'tcx>,
9346a6ac 316 autoderefs: usize,
85aaf69f 317 fn_sig: ty::FnSig<'tcx>,
e9174d1e 318 closure_def_id: DefId,
85aaf69f
SL
319}
320
a7813a04
XL
321impl<'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> for CallResolution<'gcx, 'tcx> {
322 fn resolve<'a>(&mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
c30ab7b3 323 debug!("DeferredCallResolution::resolve() {:?}", self);
85aaf69f
SL
324
325 // we should not be invoked until the closure kind has been
326 // determined by upvar inference
a7813a04 327 assert!(fcx.closure_kind(self.closure_def_id).is_some());
85aaf69f
SL
328
329 // We may now know enough to figure out fn vs fnmut etc.
c30ab7b3
SL
330 match fcx.try_overloaded_call_traits(self.call_expr,
331 self.callee_expr,
332 self.adjusted_ty,
333 self.autoderefs) {
85aaf69f
SL
334 Some(method_callee) => {
335 // One problem is that when we get here, we are going
336 // to have a newly instantiated function signature
337 // from the call trait. This has to be reconciled with
338 // the older function signature we had before. In
339 // principle we *should* be able to fn_sigs(), but we
340 // can't because of the annoying need for a TypeTrace.
341 // (This always bites me, should find a way to
342 // refactor it.)
c30ab7b3
SL
343 let method_sig = fcx.tcx
344 .no_late_bound_regions(method_callee.ty.fn_sig())
345 .unwrap();
85aaf69f 346
c30ab7b3 347 debug!("attempt_resolution: method_callee={:?}", method_callee);
85aaf69f
SL
348
349 for (&method_arg_ty, &self_arg_ty) in
c30ab7b3 350 method_sig.inputs[1..].iter().zip(&self.fn_sig.inputs) {
a7813a04 351 fcx.demand_eqtype(self.call_expr.span, self_arg_ty, method_arg_ty);
85aaf69f
SL
352 }
353
c30ab7b3 354 fcx.demand_eqtype(self.call_expr.span, method_sig.output, self.fn_sig.output);
85aaf69f 355
a7813a04 356 fcx.write_overloaded_call_method_map(self.call_expr, method_callee);
85aaf69f
SL
357 }
358 None => {
c30ab7b3
SL
359 span_bug!(self.call_expr.span,
360 "failed to find an overloaded call trait for closure call");
85aaf69f
SL
361 }
362 }
363 }
364}