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