]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/closure.rs
Auto merge of #43710 - zackmdavis:field_init_shorthand_power_slam, r=Mark-Simulacrum
[rust.git] / src / librustc_typeck / check / closure.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 //! Code for type-checking closure expressions.
12
13 use super::{check_fn, Expectation, FnCtxt};
14
15 use astconv::AstConv;
16 use rustc::infer::type_variable::TypeVariableOrigin;
17 use rustc::ty::{self, ToPolyTraitRef, Ty};
18 use rustc::ty::subst::Substs;
19 use std::cmp;
20 use std::iter;
21 use syntax::abi::Abi;
22 use rustc::hir;
23
24 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
25     pub fn check_expr_closure(&self,
26                               expr: &hir::Expr,
27                               _capture: hir::CaptureClause,
28                               decl: &'gcx hir::FnDecl,
29                               body_id: hir::BodyId,
30                               expected: Expectation<'tcx>)
31                               -> Ty<'tcx> {
32         debug!("check_expr_closure(expr={:?},expected={:?})",
33                expr,
34                expected);
35
36         // It's always helpful for inference if we know the kind of
37         // closure sooner rather than later, so first examine the expected
38         // type, and see if can glean a closure kind from there.
39         let (expected_sig, expected_kind) = match expected.to_option(self) {
40             Some(ty) => self.deduce_expectations_from_expected_type(ty),
41             None => (None, None),
42         };
43         let body = self.tcx.hir.body(body_id);
44         self.check_closure(expr, expected_kind, decl, body, expected_sig)
45     }
46
47     fn check_closure(&self,
48                      expr: &hir::Expr,
49                      opt_kind: Option<ty::ClosureKind>,
50                      decl: &'gcx hir::FnDecl,
51                      body: &'gcx hir::Body,
52                      expected_sig: Option<ty::FnSig<'tcx>>)
53                      -> Ty<'tcx> {
54         debug!("check_closure opt_kind={:?} expected_sig={:?}",
55                opt_kind,
56                expected_sig);
57
58         let expr_def_id = self.tcx.hir.local_def_id(expr.id);
59         let sig = AstConv::ty_of_closure(self,
60                                          hir::Unsafety::Normal,
61                                          decl,
62                                          Abi::RustCall,
63                                          expected_sig);
64         // `deduce_expectations_from_expected_type` introduces late-bound
65         // lifetimes defined elsewhere, which we need to anonymize away.
66         let sig = self.tcx.anonymize_late_bound_regions(&sig);
67
68         // Create type variables (for now) to represent the transformed
69         // types of upvars. These will be unified during the upvar
70         // inference phase (`upvar.rs`).
71         let base_substs = Substs::identity_for_item(self.tcx,
72             self.tcx.closure_base_def_id(expr_def_id));
73         let closure_type = self.tcx.mk_closure(expr_def_id,
74             base_substs.extend_to(self.tcx, expr_def_id,
75                 |_, _| span_bug!(expr.span, "closure has region param"),
76                 |_, _| self.infcx.next_ty_var(TypeVariableOrigin::TransformedUpvar(expr.span))
77             )
78         );
79
80         debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type);
81
82         let fn_sig = self.liberate_late_bound_regions(expr_def_id, &sig);
83         let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
84                                                             body.value.id,
85                                                             self.param_env,
86                                                             &fn_sig);
87
88         check_fn(self, self.param_env, fn_sig, decl, expr.id, body);
89
90         // Tuple up the arguments and insert the resulting function type into
91         // the `closures` table.
92         let sig = sig.map_bound(|sig| self.tcx.mk_fn_sig(
93             iter::once(self.tcx.intern_tup(sig.inputs(), false)),
94             sig.output(),
95             sig.variadic,
96             sig.unsafety,
97             sig.abi
98         ));
99
100         debug!("closure for {:?} --> sig={:?} opt_kind={:?}",
101                expr_def_id,
102                sig,
103                opt_kind);
104
105         {
106             let mut tables = self.tables.borrow_mut();
107             tables.closure_tys_mut().insert(expr.hir_id, sig);
108             match opt_kind {
109                 Some(kind) => {
110                     tables.closure_kinds_mut().insert(expr.hir_id, (kind, None));
111                 }
112                 None => {}
113             }
114         }
115
116         closure_type
117     }
118
119     fn deduce_expectations_from_expected_type
120         (&self,
121          expected_ty: Ty<'tcx>)
122          -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
123         debug!("deduce_expectations_from_expected_type(expected_ty={:?})",
124                expected_ty);
125
126         match expected_ty.sty {
127             ty::TyDynamic(ref object_type, ..) => {
128                 let sig = object_type.projection_bounds()
129                     .filter_map(|pb| {
130                         let pb = pb.with_self_ty(self.tcx, self.tcx.types.err);
131                         self.deduce_sig_from_projection(&pb)
132                     })
133                     .next();
134                 let kind = object_type.principal()
135                     .and_then(|p| self.tcx.lang_items.fn_trait_kind(p.def_id()));
136                 (sig, kind)
137             }
138             ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
139             ty::TyFnPtr(sig) => (Some(sig.skip_binder().clone()), Some(ty::ClosureKind::Fn)),
140             _ => (None, None),
141         }
142     }
143
144     fn deduce_expectations_from_obligations
145         (&self,
146          expected_vid: ty::TyVid)
147          -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
148         let fulfillment_cx = self.fulfillment_cx.borrow();
149         // Here `expected_ty` is known to be a type inference variable.
150
151         let expected_sig = fulfillment_cx.pending_obligations()
152             .iter()
153             .map(|obligation| &obligation.obligation)
154             .filter_map(|obligation| {
155                 debug!("deduce_expectations_from_obligations: obligation.predicate={:?}",
156                        obligation.predicate);
157
158                 match obligation.predicate {
159                     // Given a Projection predicate, we can potentially infer
160                     // the complete signature.
161                     ty::Predicate::Projection(ref proj_predicate) => {
162                         let trait_ref = proj_predicate.to_poly_trait_ref(self.tcx);
163                         self.self_type_matches_expected_vid(trait_ref, expected_vid)
164                             .and_then(|_| self.deduce_sig_from_projection(proj_predicate))
165                     }
166                     _ => None,
167                 }
168             })
169             .next();
170
171         // Even if we can't infer the full signature, we may be able to
172         // infer the kind. This can occur if there is a trait-reference
173         // like `F : Fn<A>`. Note that due to subtyping we could encounter
174         // many viable options, so pick the most restrictive.
175         let expected_kind = fulfillment_cx.pending_obligations()
176             .iter()
177             .map(|obligation| &obligation.obligation)
178             .filter_map(|obligation| {
179                 let opt_trait_ref = match obligation.predicate {
180                     ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref(self.tcx)),
181                     ty::Predicate::Trait(ref data) => Some(data.to_poly_trait_ref()),
182                     ty::Predicate::Equate(..) => None,
183                     ty::Predicate::Subtype(..) => None,
184                     ty::Predicate::RegionOutlives(..) => None,
185                     ty::Predicate::TypeOutlives(..) => None,
186                     ty::Predicate::WellFormed(..) => None,
187                     ty::Predicate::ObjectSafe(..) => None,
188
189                     // NB: This predicate is created by breaking down a
190                     // `ClosureType: FnFoo()` predicate, where
191                     // `ClosureType` represents some `TyClosure`. It can't
192                     // possibly be referring to the current closure,
193                     // because we haven't produced the `TyClosure` for
194                     // this closure yet; this is exactly why the other
195                     // code is looking for a self type of a unresolved
196                     // inference variable.
197                     ty::Predicate::ClosureKind(..) => None,
198                 };
199                 opt_trait_ref.and_then(|tr| self.self_type_matches_expected_vid(tr, expected_vid))
200                     .and_then(|tr| self.tcx.lang_items.fn_trait_kind(tr.def_id()))
201             })
202             .fold(None,
203                   |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur))));
204
205         (expected_sig, expected_kind)
206     }
207
208     /// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
209     /// everything we need to know about a closure.
210     fn deduce_sig_from_projection(&self,
211                                   projection: &ty::PolyProjectionPredicate<'tcx>)
212                                   -> Option<ty::FnSig<'tcx>> {
213         let tcx = self.tcx;
214
215         debug!("deduce_sig_from_projection({:?})", projection);
216
217         let trait_ref = projection.to_poly_trait_ref(tcx);
218
219         if tcx.lang_items.fn_trait_kind(trait_ref.def_id()).is_none() {
220             return None;
221         }
222
223         let arg_param_ty = trait_ref.substs().type_at(1);
224         let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty);
225         debug!("deduce_sig_from_projection: arg_param_ty {:?}",
226                arg_param_ty);
227
228         let input_tys = match arg_param_ty.sty {
229             ty::TyTuple(tys, _) => tys.into_iter(),
230             _ => {
231                 return None;
232             }
233         };
234
235         let ret_param_ty = projection.0.ty;
236         let ret_param_ty = self.resolve_type_vars_if_possible(&ret_param_ty);
237         debug!("deduce_sig_from_projection: ret_param_ty {:?}", ret_param_ty);
238
239         let fn_sig = self.tcx.mk_fn_sig(
240             input_tys.cloned(),
241             ret_param_ty,
242             false,
243             hir::Unsafety::Normal,
244             Abi::Rust
245         );
246         debug!("deduce_sig_from_projection: fn_sig {:?}", fn_sig);
247
248         Some(fn_sig)
249     }
250
251     fn self_type_matches_expected_vid(&self,
252                                       trait_ref: ty::PolyTraitRef<'tcx>,
253                                       expected_vid: ty::TyVid)
254                                       -> Option<ty::PolyTraitRef<'tcx>> {
255         let self_ty = self.shallow_resolve(trait_ref.self_ty());
256         debug!("self_type_matches_expected_vid(trait_ref={:?}, self_ty={:?})",
257                trait_ref,
258                self_ty);
259         match self_ty.sty {
260             ty::TyInfer(ty::TyVar(v)) if expected_vid == v => Some(trait_ref),
261             _ => None,
262         }
263     }
264 }