]>
Commit | Line | Data |
---|---|---|
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 | 11 | use super::{DeferredCallResolution, Expectation, FnCtxt, TupleArgumentsFlag}; |
1a4d82fc | 12 | |
85aaf69f | 13 | use CrateCtxt; |
54a0048b | 14 | use hir::def::Def; |
9e0c209e SL |
15 | use hir::def_id::{DefId, LOCAL_CRATE}; |
16 | use rustc::{infer, traits}; | |
54a0048b | 17 | use rustc::ty::{self, LvaluePreference, Ty}; |
1a4d82fc JJ |
18 | use syntax::parse::token; |
19 | use syntax::ptr::P; | |
3157f602 | 20 | use syntax_pos::Span; |
1a4d82fc | 21 | |
54a0048b | 22 | use 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 | 27 | pub 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 |
38 | enum CallStep<'tcx> { |
39 | Builtin, | |
85aaf69f | 40 | DeferredClosure(ty::FnSig<'tcx>), |
c30ab7b3 | 41 | Overloaded(ty::MethodCallee<'tcx>), |
1a4d82fc JJ |
42 | } |
43 | ||
a7813a04 XL |
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 [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 |
312 | struct 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 |
321 | impl<'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 | } |