]>
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 | 15 | use hir::def_id::{DefId, LOCAL_CRATE}; |
476ff2be | 16 | use hir::print; |
9e0c209e | 17 | use rustc::{infer, traits}; |
54a0048b | 18 | use rustc::ty::{self, LvaluePreference, Ty}; |
476ff2be | 19 | use syntax::symbol::Symbol; |
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, | |
476ff2be | 48 | arg_exprs: &'gcx [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 | 161 | for &(opt_trait_def_id, method_name) in |
476ff2be SL |
162 | &[(self.tcx.lang_items.fn_trait(), Symbol::intern("call")), |
163 | (self.tcx.lang_items.fn_mut_trait(), Symbol::intern("call_mut")), | |
164 | (self.tcx.lang_items.fn_once_trait(), Symbol::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>, | |
476ff2be | 191 | arg_exprs: &'gcx [hir::Expr], |
c30ab7b3 SL |
192 | expected: Expectation<'tcx>) |
193 | -> Ty<'tcx> { | |
a7813a04 XL |
194 | let error_fn_sig; |
195 | ||
476ff2be SL |
196 | let (fn_sig, def_span) = match callee_ty.sty { |
197 | ty::TyFnDef(def_id, .., &ty::BareFnTy {ref sig, ..}) => { | |
198 | (sig, self.tcx.map.span_if_local(def_id)) | |
199 | } | |
200 | ty::TyFnPtr(&ty::BareFnTy {ref sig, ..}) => (sig, None), | |
201 | ref t => { | |
202 | let mut unit_variant = None; | |
203 | if let &ty::TyAdt(adt_def, ..) = t { | |
204 | if adt_def.is_enum() { | |
205 | if let hir::ExprCall(ref expr, _) = call_expr.node { | |
206 | unit_variant = Some(print::expr_to_string(expr)) | |
207 | } | |
208 | } | |
209 | } | |
210 | let mut err = if let Some(path) = unit_variant { | |
211 | let mut err = self.type_error_struct(call_expr.span, |_| { | |
212 | format!("`{}` is being called, but it is not a function", path) | |
213 | }, callee_ty); | |
214 | err.help(&format!("did you mean to write `{}`?", path)); | |
215 | err | |
216 | } else { | |
217 | self.type_error_struct(call_expr.span, |actual| { | |
218 | format!("expected function, found `{}`", actual) | |
219 | }, callee_ty) | |
220 | }; | |
a7813a04 XL |
221 | |
222 | if let hir::ExprCall(ref expr, _) = call_expr.node { | |
476ff2be SL |
223 | let def = if let hir::ExprPath(ref qpath) = expr.node { |
224 | self.tables.borrow().qpath_def(qpath, expr.id) | |
225 | } else { | |
226 | Def::Err | |
227 | }; | |
228 | if def != Def::Err { | |
229 | if let Some(span) = self.tcx.map.span_if_local(def.def_id()) { | |
230 | err.span_note(span, "defined here"); | |
92a42be0 SL |
231 | } |
232 | } | |
233 | } | |
92a42be0 | 234 | |
a7813a04 | 235 | err.emit(); |
9cc50fc6 | 236 | |
a7813a04 XL |
237 | // This is the "default" function signature, used in case of error. |
238 | // In that case, we check each argument against "error" in order to | |
239 | // set up all the node type bindings. | |
476ff2be SL |
240 | error_fn_sig = ty::Binder(self.tcx.mk_fn_sig( |
241 | self.err_args(arg_exprs.len()).into_iter(), | |
242 | self.tcx.types.err, | |
243 | false, | |
244 | )); | |
1a4d82fc | 245 | |
476ff2be | 246 | (&error_fn_sig, None) |
a7813a04 XL |
247 | } |
248 | }; | |
1a4d82fc | 249 | |
a7813a04 XL |
250 | // Replace any late-bound regions that appear in the function |
251 | // signature with region variables. We also have to | |
252 | // renormalize the associated types at this point, since they | |
253 | // previously appeared within a `Binder<>` and hence would not | |
254 | // have been normalized before. | |
255 | let fn_sig = | |
c30ab7b3 SL |
256 | self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, fn_sig) |
257 | .0; | |
258 | let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig); | |
a7813a04 XL |
259 | |
260 | // Call the generic checker. | |
c30ab7b3 SL |
261 | let expected_arg_tys = |
262 | self.expected_types_for_fn_args(call_expr.span, | |
263 | expected, | |
476ff2be SL |
264 | fn_sig.output(), |
265 | fn_sig.inputs()); | |
a7813a04 | 266 | self.check_argument_types(call_expr.span, |
476ff2be | 267 | fn_sig.inputs(), |
a7813a04 XL |
268 | &expected_arg_tys[..], |
269 | arg_exprs, | |
270 | fn_sig.variadic, | |
476ff2be SL |
271 | TupleArgumentsFlag::DontTupleArguments, |
272 | def_span); | |
a7813a04 | 273 | |
476ff2be | 274 | fn_sig.output() |
a7813a04 | 275 | } |
85aaf69f | 276 | |
a7813a04 XL |
277 | fn confirm_deferred_closure_call(&self, |
278 | call_expr: &hir::Expr, | |
476ff2be | 279 | arg_exprs: &'gcx [hir::Expr], |
a7813a04 | 280 | expected: Expectation<'tcx>, |
c30ab7b3 SL |
281 | fn_sig: ty::FnSig<'tcx>) |
282 | -> Ty<'tcx> { | |
a7813a04 XL |
283 | // `fn_sig` is the *signature* of the cosure being called. We |
284 | // don't know the full details yet (`Fn` vs `FnMut` etc), but we | |
285 | // do know the types expected for each argument and the return | |
286 | // type. | |
287 | ||
c30ab7b3 SL |
288 | let expected_arg_tys = self.expected_types_for_fn_args(call_expr.span, |
289 | expected, | |
476ff2be SL |
290 | fn_sig.output().clone(), |
291 | fn_sig.inputs()); | |
a7813a04 XL |
292 | |
293 | self.check_argument_types(call_expr.span, | |
476ff2be | 294 | fn_sig.inputs(), |
a7813a04 XL |
295 | &expected_arg_tys, |
296 | arg_exprs, | |
297 | fn_sig.variadic, | |
476ff2be SL |
298 | TupleArgumentsFlag::TupleArguments, |
299 | None); | |
a7813a04 | 300 | |
476ff2be | 301 | fn_sig.output() |
a7813a04 | 302 | } |
85aaf69f | 303 | |
a7813a04 XL |
304 | fn confirm_overloaded_call(&self, |
305 | call_expr: &hir::Expr, | |
306 | callee_expr: &'gcx hir::Expr, | |
476ff2be | 307 | arg_exprs: &'gcx [hir::Expr], |
a7813a04 | 308 | expected: Expectation<'tcx>, |
c30ab7b3 SL |
309 | method_callee: ty::MethodCallee<'tcx>) |
310 | -> Ty<'tcx> { | |
311 | let output_type = self.check_method_argument_types(call_expr.span, | |
312 | method_callee.ty, | |
313 | callee_expr, | |
314 | arg_exprs, | |
315 | TupleArgumentsFlag::TupleArguments, | |
316 | expected); | |
a7813a04 XL |
317 | |
318 | self.write_overloaded_call_method_map(call_expr, method_callee); | |
9e0c209e | 319 | output_type |
a7813a04 XL |
320 | } |
321 | ||
322 | fn write_overloaded_call_method_map(&self, | |
323 | call_expr: &hir::Expr, | |
324 | method_callee: ty::MethodCallee<'tcx>) { | |
325 | let method_call = ty::MethodCall::expr(call_expr.id); | |
326 | self.tables.borrow_mut().method_map.insert(method_call, method_callee); | |
327 | } | |
1a4d82fc JJ |
328 | } |
329 | ||
62682a34 | 330 | #[derive(Debug)] |
a7813a04 XL |
331 | struct CallResolution<'gcx: 'tcx, 'tcx> { |
332 | call_expr: &'gcx hir::Expr, | |
333 | callee_expr: &'gcx hir::Expr, | |
85aaf69f | 334 | adjusted_ty: Ty<'tcx>, |
9346a6ac | 335 | autoderefs: usize, |
85aaf69f | 336 | fn_sig: ty::FnSig<'tcx>, |
e9174d1e | 337 | closure_def_id: DefId, |
85aaf69f SL |
338 | } |
339 | ||
a7813a04 XL |
340 | impl<'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> for CallResolution<'gcx, 'tcx> { |
341 | fn resolve<'a>(&mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) { | |
c30ab7b3 | 342 | debug!("DeferredCallResolution::resolve() {:?}", self); |
85aaf69f SL |
343 | |
344 | // we should not be invoked until the closure kind has been | |
345 | // determined by upvar inference | |
a7813a04 | 346 | assert!(fcx.closure_kind(self.closure_def_id).is_some()); |
85aaf69f SL |
347 | |
348 | // We may now know enough to figure out fn vs fnmut etc. | |
c30ab7b3 SL |
349 | match fcx.try_overloaded_call_traits(self.call_expr, |
350 | self.callee_expr, | |
351 | self.adjusted_ty, | |
352 | self.autoderefs) { | |
85aaf69f SL |
353 | Some(method_callee) => { |
354 | // One problem is that when we get here, we are going | |
355 | // to have a newly instantiated function signature | |
356 | // from the call trait. This has to be reconciled with | |
357 | // the older function signature we had before. In | |
358 | // principle we *should* be able to fn_sigs(), but we | |
359 | // can't because of the annoying need for a TypeTrace. | |
360 | // (This always bites me, should find a way to | |
361 | // refactor it.) | |
c30ab7b3 SL |
362 | let method_sig = fcx.tcx |
363 | .no_late_bound_regions(method_callee.ty.fn_sig()) | |
364 | .unwrap(); | |
85aaf69f | 365 | |
c30ab7b3 | 366 | debug!("attempt_resolution: method_callee={:?}", method_callee); |
85aaf69f | 367 | |
476ff2be SL |
368 | for (method_arg_ty, self_arg_ty) in |
369 | method_sig.inputs().iter().skip(1).zip(self.fn_sig.inputs()) { | |
370 | fcx.demand_eqtype(self.call_expr.span, &self_arg_ty, &method_arg_ty); | |
85aaf69f SL |
371 | } |
372 | ||
476ff2be | 373 | fcx.demand_eqtype(self.call_expr.span, method_sig.output(), self.fn_sig.output()); |
85aaf69f | 374 | |
a7813a04 | 375 | fcx.write_overloaded_call_method_map(self.call_expr, method_callee); |
85aaf69f SL |
376 | } |
377 | None => { | |
c30ab7b3 SL |
378 | span_bug!(self.call_expr.span, |
379 | "failed to find an overloaded call trait for closure call"); | |
85aaf69f SL |
380 | } |
381 | } | |
382 | } | |
383 | } |