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