]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/callee.rs
Auto merge of #49313 - sgrif:sg-revert-stuff, r=nikomatsakis
[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::{Expectation, FnCtxt, Needs, TupleArgumentsFlag};
12 use super::autoderef::Autoderef;
13 use super::method::MethodCallee;
14
15 use hir::def::Def;
16 use hir::def_id::{DefId, LOCAL_CRATE};
17 use rustc::{infer, traits};
18 use rustc::ty::{self, TyCtxt, TypeFoldable, Ty};
19 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
20 use syntax::abi;
21 use syntax::symbol::Symbol;
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(tcx: TyCtxt, span: Span, trait_id: DefId) {
30     if tcx.lang_items().drop_trait() == Some(trait_id) {
31         struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method")
32             .span_label(span, "explicit destructor calls not allowed")
33             .emit();
34     }
35 }
36
37 enum CallStep<'tcx> {
38     Builtin(Ty<'tcx>),
39     DeferredClosure(ty::FnSig<'tcx>),
40     /// e.g. enum variant constructors
41     Overloaded(MethodCallee<'tcx>),
42 }
43
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 [hir::Expr],
49                       expected: Expectation<'tcx>)
50                       -> Ty<'tcx> {
51         let original_callee_ty = self.check_expr(callee_expr);
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 mut result = None;
56         while result.is_none() && autoderef.next().is_some() {
57             result = self.try_overloaded_call_step(call_expr, callee_expr, &autoderef);
58         }
59         autoderef.finalize();
60
61         let output = match result {
62             None => {
63                 // this will report an error since original_callee_ty is not a fn
64                 self.confirm_builtin_call(call_expr, original_callee_ty, arg_exprs, expected)
65             }
66
67             Some(CallStep::Builtin(callee_ty)) => {
68                 self.confirm_builtin_call(call_expr, callee_ty, arg_exprs, expected)
69             }
70
71             Some(CallStep::DeferredClosure(fn_sig)) => {
72                 self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, fn_sig)
73             }
74
75             Some(CallStep::Overloaded(method_callee)) => {
76                 self.confirm_overloaded_call(call_expr, arg_exprs, expected, method_callee)
77             }
78         };
79
80         // we must check that return type of called functions is WF:
81         self.register_wf_obligation(output, call_expr.span, traits::MiscObligation);
82
83         output
84     }
85
86     fn try_overloaded_call_step(&self,
87                                 call_expr: &'gcx hir::Expr,
88                                 callee_expr: &'gcx hir::Expr,
89                                 autoderef: &Autoderef<'a, 'gcx, 'tcx>)
90                                 -> Option<CallStep<'tcx>> {
91         let adjusted_ty = autoderef.unambiguous_final_ty();
92         debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})",
93                call_expr,
94                adjusted_ty);
95
96         // If the callee is a bare function or a closure, then we're all set.
97         match adjusted_ty.sty {
98             ty::TyFnDef(..) | ty::TyFnPtr(_) => {
99                 let adjustments = autoderef.adjust_steps(Needs::None);
100                 self.apply_adjustments(callee_expr, adjustments);
101                 return Some(CallStep::Builtin(adjusted_ty));
102             }
103
104             ty::TyClosure(def_id, substs) => {
105                 assert_eq!(def_id.krate, LOCAL_CRATE);
106
107                 // Check whether this is a call to a closure where we
108                 // haven't yet decided on whether the closure is fn vs
109                 // fnmut vs fnonce. If so, we have to defer further processing.
110                 if self.closure_kind(def_id, substs).is_none() {
111                     let closure_ty = self.closure_sig(def_id, substs);
112                     let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
113                                                                    infer::FnCall,
114                                                                    &closure_ty)
115                         .0;
116                     let adjustments = autoderef.adjust_steps(Needs::None);
117                     self.record_deferred_call_resolution(def_id, DeferredCallResolution {
118                         call_expr,
119                         callee_expr,
120                         adjusted_ty,
121                         adjustments,
122                         fn_sig,
123                         closure_def_id: def_id,
124                         closure_substs: substs,
125                     });
126                     return Some(CallStep::DeferredClosure(fn_sig));
127                 }
128             }
129
130             // Hack: we know that there are traits implementing Fn for &F
131             // where F:Fn and so forth. In the particular case of types
132             // like `x: &mut FnMut()`, if there is a call `x()`, we would
133             // normally translate to `FnMut::call_mut(&mut x, ())`, but
134             // that winds up requiring `mut x: &mut FnMut()`. A little
135             // over the top. The simplest fix by far is to just ignore
136             // this case and deref again, so we wind up with
137             // `FnMut::call_mut(&mut *x, ())`.
138             ty::TyRef(..) if autoderef.step_count() == 0 => {
139                 return None;
140             }
141
142             _ => {}
143         }
144
145         self.try_overloaded_call_traits(call_expr, adjusted_ty).map(|(autoref, method)| {
146             let mut adjustments = autoderef.adjust_steps(Needs::None);
147             adjustments.extend(autoref);
148             self.apply_adjustments(callee_expr, adjustments);
149             CallStep::Overloaded(method)
150         })
151     }
152
153     fn try_overloaded_call_traits(&self,
154                                   call_expr: &hir::Expr,
155                                   adjusted_ty: Ty<'tcx>)
156                                   -> Option<(Option<Adjustment<'tcx>>,
157                                              MethodCallee<'tcx>)> {
158         // Try the options that are least restrictive on the caller first.
159         for &(opt_trait_def_id, method_name, borrow) in
160             &[(self.tcx.lang_items().fn_trait(), Symbol::intern("call"), true),
161               (self.tcx.lang_items().fn_mut_trait(), Symbol::intern("call_mut"), true),
162               (self.tcx.lang_items().fn_once_trait(), Symbol::intern("call_once"), false)] {
163             let trait_def_id = match opt_trait_def_id {
164                 Some(def_id) => def_id,
165                 None => continue,
166             };
167
168             match self.lookup_method_in_trait(call_expr.span,
169                                               method_name,
170                                               trait_def_id,
171                                               adjusted_ty,
172                                               None) {
173                 None => continue,
174                 Some(ok) => {
175                     let method = self.register_infer_ok_obligations(ok);
176                     let mut autoref = None;
177                     if borrow {
178                         if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty {
179                             let mutbl = match mt.mutbl {
180                                 hir::MutImmutable => AutoBorrowMutability::Immutable,
181                                 hir::MutMutable => AutoBorrowMutability::Mutable {
182                                     // For initial two-phase borrow
183                                     // deployment, conservatively omit
184                                     // overloaded function call ops.
185                                     allow_two_phase_borrow: false,
186                                 }
187                             };
188                             autoref = Some(Adjustment {
189                                 kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
190                                 target: method.sig.inputs()[0]
191                             });
192                         }
193                     }
194                     return Some((autoref, method));
195                 }
196             }
197         }
198
199         None
200     }
201
202     fn confirm_builtin_call(&self,
203                             call_expr: &hir::Expr,
204                             callee_ty: Ty<'tcx>,
205                             arg_exprs: &'gcx [hir::Expr],
206                             expected: Expectation<'tcx>)
207                             -> Ty<'tcx> {
208         let (fn_sig, def_span) = match callee_ty.sty {
209             ty::TyFnDef(def_id, _) => {
210                 (callee_ty.fn_sig(self.tcx), self.tcx.hir.span_if_local(def_id))
211             }
212             ty::TyFnPtr(sig) => (sig, None),
213             ref t => {
214                 let mut unit_variant = None;
215                 if let &ty::TyAdt(adt_def, ..) = t {
216                     if adt_def.is_enum() {
217                         if let hir::ExprCall(ref expr, _) = call_expr.node {
218                             unit_variant = Some(self.tcx.hir.node_to_pretty_string(expr.id))
219                         }
220                     }
221                 }
222
223                 let mut err = type_error_struct!(
224                     self.tcx.sess,
225                     call_expr.span,
226                     callee_ty,
227                     E0618,
228                     "expected function, found {}",
229                     match unit_variant {
230                         Some(ref path) => format!("enum variant `{}`", path),
231                         None => format!("`{}`", callee_ty),
232                     });
233
234                 err.span_label(call_expr.span, "not a function");
235
236                 if let Some(ref path) = unit_variant {
237                     err.span_suggestion(call_expr.span,
238                                         &format!("`{}` is a unit variant, you need to write it \
239                                                   without the parenthesis", path),
240                                         path.to_string());
241                 }
242
243                 if let hir::ExprCall(ref expr, _) = call_expr.node {
244                     let def = if let hir::ExprPath(ref qpath) = expr.node {
245                         self.tables.borrow().qpath_def(qpath, expr.hir_id)
246                     } else {
247                         Def::Err
248                     };
249                     let def_span = match def {
250                         Def::Err => None,
251                         Def::Local(id) | Def::Upvar(id, ..) => {
252                             Some(self.tcx.hir.span(id))
253                         }
254                         _ => self.tcx.hir.span_if_local(def.def_id())
255                     };
256                     if let Some(span) = def_span {
257                         let name = match unit_variant {
258                             Some(path) => path,
259                             None => callee_ty.to_string(),
260                         };
261                         err.span_label(span, format!("`{}` defined here", name));
262                     }
263                 }
264
265                 err.emit();
266
267                 // This is the "default" function signature, used in case of error.
268                 // In that case, we check each argument against "error" in order to
269                 // set up all the node type bindings.
270                 (ty::Binder(self.tcx.mk_fn_sig(
271                     self.err_args(arg_exprs.len()).into_iter(),
272                     self.tcx.types.err,
273                     false,
274                     hir::Unsafety::Normal,
275                     abi::Abi::Rust
276                 )), None)
277             }
278         };
279
280         // Replace any late-bound regions that appear in the function
281         // signature with region variables. We also have to
282         // renormalize the associated types at this point, since they
283         // previously appeared within a `Binder<>` and hence would not
284         // have been normalized before.
285         let fn_sig =
286             self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, &fn_sig)
287                 .0;
288         let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig);
289
290         // Call the generic checker.
291         let expected_arg_tys =
292             self.expected_inputs_for_expected_output(call_expr.span,
293                                             expected,
294                                             fn_sig.output(),
295                                             fn_sig.inputs());
296         self.check_argument_types(call_expr.span,
297                                   call_expr.span,
298                                   fn_sig.inputs(),
299                                   &expected_arg_tys[..],
300                                   arg_exprs,
301                                   fn_sig.variadic,
302                                   TupleArgumentsFlag::DontTupleArguments,
303                                   def_span);
304
305         fn_sig.output()
306     }
307
308     fn confirm_deferred_closure_call(&self,
309                                      call_expr: &hir::Expr,
310                                      arg_exprs: &'gcx [hir::Expr],
311                                      expected: Expectation<'tcx>,
312                                      fn_sig: ty::FnSig<'tcx>)
313                                      -> Ty<'tcx> {
314         // `fn_sig` is the *signature* of the cosure being called. We
315         // don't know the full details yet (`Fn` vs `FnMut` etc), but we
316         // do know the types expected for each argument and the return
317         // type.
318
319         let expected_arg_tys = self.expected_inputs_for_expected_output(call_expr.span,
320                                                                expected,
321                                                                fn_sig.output().clone(),
322                                                                fn_sig.inputs());
323
324         self.check_argument_types(call_expr.span,
325                                   call_expr.span,
326                                   fn_sig.inputs(),
327                                   &expected_arg_tys,
328                                   arg_exprs,
329                                   fn_sig.variadic,
330                                   TupleArgumentsFlag::TupleArguments,
331                                   None);
332
333         fn_sig.output()
334     }
335
336     fn confirm_overloaded_call(&self,
337                                call_expr: &hir::Expr,
338                                arg_exprs: &'gcx [hir::Expr],
339                                expected: Expectation<'tcx>,
340                                method_callee: MethodCallee<'tcx>)
341                                -> Ty<'tcx> {
342         let output_type = self.check_method_argument_types(call_expr.span,
343                                                            call_expr.span,
344                                                            Ok(method_callee),
345                                                            arg_exprs,
346                                                            TupleArgumentsFlag::TupleArguments,
347                                                            expected);
348
349         self.write_method_call(call_expr.hir_id, method_callee);
350         output_type
351     }
352 }
353
354 #[derive(Debug)]
355 pub struct DeferredCallResolution<'gcx: 'tcx, 'tcx> {
356     call_expr: &'gcx hir::Expr,
357     callee_expr: &'gcx hir::Expr,
358     adjusted_ty: Ty<'tcx>,
359     adjustments: Vec<Adjustment<'tcx>>,
360     fn_sig: ty::FnSig<'tcx>,
361     closure_def_id: DefId,
362     closure_substs: ty::ClosureSubsts<'tcx>,
363 }
364
365 impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> {
366     pub fn resolve(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
367         debug!("DeferredCallResolution::resolve() {:?}", self);
368
369         // we should not be invoked until the closure kind has been
370         // determined by upvar inference
371         assert!(fcx.closure_kind(self.closure_def_id, self.closure_substs).is_some());
372
373         // We may now know enough to figure out fn vs fnmut etc.
374         match fcx.try_overloaded_call_traits(self.call_expr,
375                                              self.adjusted_ty) {
376             Some((autoref, method_callee)) => {
377                 // One problem is that when we get here, we are going
378                 // to have a newly instantiated function signature
379                 // from the call trait. This has to be reconciled with
380                 // the older function signature we had before. In
381                 // principle we *should* be able to fn_sigs(), but we
382                 // can't because of the annoying need for a TypeTrace.
383                 // (This always bites me, should find a way to
384                 // refactor it.)
385                 let method_sig = method_callee.sig;
386
387                 debug!("attempt_resolution: method_callee={:?}", method_callee);
388
389                 for (method_arg_ty, self_arg_ty) in
390                     method_sig.inputs().iter().skip(1).zip(self.fn_sig.inputs()) {
391                     fcx.demand_eqtype(self.call_expr.span, &self_arg_ty, &method_arg_ty);
392                 }
393
394                 fcx.demand_eqtype(self.call_expr.span, method_sig.output(), self.fn_sig.output());
395
396                 let mut adjustments = self.adjustments;
397                 adjustments.extend(autoref);
398                 fcx.apply_adjustments(self.callee_expr, adjustments);
399
400                 fcx.write_method_call(self.call_expr.hir_id,
401                                       method_callee);
402             }
403             None => {
404                 span_bug!(self.call_expr.span,
405                           "failed to find an overloaded call trait for closure call");
406             }
407         }
408     }
409 }