]> git.proxmox.com Git - rustc.git/blame - src/librustc_typeck/check/closure.rs
New upstream version 1.20.0+dfsg1
[rustc.git] / src / librustc_typeck / check / closure.rs
CommitLineData
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
11//! Code for type-checking closure expressions.
12
13use super::{check_fn, Expectation, FnCtxt};
14
a7813a04 15use astconv::AstConv;
476ff2be 16use rustc::infer::type_variable::TypeVariableOrigin;
54a0048b 17use rustc::ty::{self, ToPolyTraitRef, Ty};
7cac9316 18use rustc::ty::subst::Substs;
c34b1796 19use std::cmp;
476ff2be 20use std::iter;
7453a54e 21use syntax::abi::Abi;
54a0048b 22use rustc::hir;
1a4d82fc 23
a7813a04
XL
24impl<'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,
32a655c1 29 body_id: hir::BodyId,
c30ab7b3
SL
30 expected: Expectation<'tcx>)
31 -> Ty<'tcx> {
a7813a04
XL
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.
c30ab7b3 39 let (expected_sig, expected_kind) = match expected.to_option(self) {
a7813a04 40 Some(ty) => self.deduce_expectations_from_expected_type(ty),
c30ab7b3 41 None => (None, None),
a7813a04 42 };
32a655c1 43 let body = self.tcx.hir.body(body_id);
a7813a04
XL
44 self.check_closure(expr, expected_kind, decl, body, expected_sig)
45 }
1a4d82fc 46
a7813a04
XL
47 fn check_closure(&self,
48 expr: &hir::Expr,
49 opt_kind: Option<ty::ClosureKind>,
50 decl: &'gcx hir::FnDecl,
32a655c1 51 body: &'gcx hir::Body,
c30ab7b3
SL
52 expected_sig: Option<ty::FnSig<'tcx>>)
53 -> Ty<'tcx> {
a7813a04
XL
54 debug!("check_closure opt_kind={:?} expected_sig={:?}",
55 opt_kind,
56 expected_sig);
57
32a655c1 58 let expr_def_id = self.tcx.hir.local_def_id(expr.id);
8bb4bdeb
XL
59 let sig = AstConv::ty_of_closure(self,
60 hir::Unsafety::Normal,
61 decl,
62 Abi::RustCall,
63 expected_sig);
7cac9316
XL
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);
a7813a04
XL
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`).
7cac9316
XL
71 let base_substs = Substs::identity_for_item(self.tcx,
72 self.tcx.closure_base_def_id(expr_def_id));
a7813a04 73 let closure_type = self.tcx.mk_closure(expr_def_id,
7cac9316 74 base_substs.extend_to(self.tcx, expr_def_id,
476ff2be
SL
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);
c30ab7b3 81
7cac9316 82 let fn_sig = self.liberate_late_bound_regions(expr_def_id, &sig);
32a655c1 83 let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
7cac9316
XL
84 body.value.id,
85 self.param_env,
86 &fn_sig);
c30ab7b3 87
7cac9316 88 check_fn(self, self.param_env, fn_sig, decl, expr.id, body);
a7813a04
XL
89
90 // Tuple up the arguments and insert the resulting function type into
91 // the `closures` table.
8bb4bdeb
XL
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 ));
a7813a04
XL
99
100 debug!("closure for {:?} --> sig={:?} opt_kind={:?}",
101 expr_def_id,
8bb4bdeb 102 sig,
a7813a04
XL
103 opt_kind);
104
8bb4bdeb 105 self.tables.borrow_mut().closure_tys.insert(expr.id, sig);
a7813a04 106 match opt_kind {
c30ab7b3 107 Some(kind) => {
7cac9316 108 self.tables.borrow_mut().closure_kinds.insert(expr.id, (kind, None));
c30ab7b3
SL
109 }
110 None => {}
1a4d82fc 111 }
9e0c209e
SL
112
113 closure_type
1a4d82fc 114 }
1a4d82fc 115
c30ab7b3
SL
116 fn deduce_expectations_from_expected_type
117 (&self,
118 expected_ty: Ty<'tcx>)
119 -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
a7813a04
XL
120 debug!("deduce_expectations_from_expected_type(expected_ty={:?})",
121 expected_ty);
122
123 match expected_ty.sty {
476ff2be
SL
124 ty::TyDynamic(ref object_type, ..) => {
125 let sig = object_type.projection_bounds()
c30ab7b3
SL
126 .filter_map(|pb| {
127 let pb = pb.with_self_ty(self.tcx, self.tcx.types.err);
128 self.deduce_sig_from_projection(&pb)
129 })
130 .next();
476ff2be
SL
131 let kind = object_type.principal()
132 .and_then(|p| self.tcx.lang_items.fn_trait_kind(p.def_id()));
a7813a04 133 (sig, kind)
85aaf69f 134 }
c30ab7b3 135 ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
7cac9316 136 ty::TyFnPtr(sig) => (Some(sig.skip_binder().clone()), Some(ty::ClosureKind::Fn)),
c30ab7b3 137 _ => (None, None),
a7813a04
XL
138 }
139 }
c34b1796 140
c30ab7b3
SL
141 fn deduce_expectations_from_obligations
142 (&self,
143 expected_vid: ty::TyVid)
144 -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
a7813a04
XL
145 let fulfillment_cx = self.fulfillment_cx.borrow();
146 // Here `expected_ty` is known to be a type inference variable.
147
c30ab7b3 148 let expected_sig = fulfillment_cx.pending_obligations()
a7813a04
XL
149 .iter()
150 .map(|obligation| &obligation.obligation)
151 .filter_map(|obligation| {
152 debug!("deduce_expectations_from_obligations: obligation.predicate={:?}",
153 obligation.predicate);
154
155 match obligation.predicate {
156 // Given a Projection predicate, we can potentially infer
157 // the complete signature.
158 ty::Predicate::Projection(ref proj_predicate) => {
041b39d2 159 let trait_ref = proj_predicate.to_poly_trait_ref(self.tcx);
a7813a04
XL
160 self.self_type_matches_expected_vid(trait_ref, expected_vid)
161 .and_then(|_| self.deduce_sig_from_projection(proj_predicate))
162 }
c30ab7b3 163 _ => None,
a7813a04
XL
164 }
165 })
166 .next();
167
168 // Even if we can't infer the full signature, we may be able to
169 // infer the kind. This can occur if there is a trait-reference
170 // like `F : Fn<A>`. Note that due to subtyping we could encounter
171 // many viable options, so pick the most restrictive.
c30ab7b3 172 let expected_kind = fulfillment_cx.pending_obligations()
a7813a04
XL
173 .iter()
174 .map(|obligation| &obligation.obligation)
175 .filter_map(|obligation| {
176 let opt_trait_ref = match obligation.predicate {
041b39d2 177 ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref(self.tcx)),
a7813a04
XL
178 ty::Predicate::Trait(ref data) => Some(data.to_poly_trait_ref()),
179 ty::Predicate::Equate(..) => None,
cc61c64b 180 ty::Predicate::Subtype(..) => None,
a7813a04
XL
181 ty::Predicate::RegionOutlives(..) => None,
182 ty::Predicate::TypeOutlives(..) => None,
183 ty::Predicate::WellFormed(..) => None,
184 ty::Predicate::ObjectSafe(..) => None,
a7813a04
XL
185
186 // NB: This predicate is created by breaking down a
187 // `ClosureType: FnFoo()` predicate, where
188 // `ClosureType` represents some `TyClosure`. It can't
189 // possibly be referring to the current closure,
190 // because we haven't produced the `TyClosure` for
191 // this closure yet; this is exactly why the other
192 // code is looking for a self type of a unresolved
193 // inference variable.
194 ty::Predicate::ClosureKind(..) => None,
195 };
c30ab7b3 196 opt_trait_ref.and_then(|tr| self.self_type_matches_expected_vid(tr, expected_vid))
a7813a04
XL
197 .and_then(|tr| self.tcx.lang_items.fn_trait_kind(tr.def_id()))
198 })
c30ab7b3
SL
199 .fold(None,
200 |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur))));
a7813a04
XL
201
202 (expected_sig, expected_kind)
c34b1796 203 }
85aaf69f 204
a7813a04
XL
205 /// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
206 /// everything we need to know about a closure.
207 fn deduce_sig_from_projection(&self,
c30ab7b3
SL
208 projection: &ty::PolyProjectionPredicate<'tcx>)
209 -> Option<ty::FnSig<'tcx>> {
a7813a04 210 let tcx = self.tcx;
1a4d82fc 211
c30ab7b3 212 debug!("deduce_sig_from_projection({:?})", projection);
85aaf69f 213
041b39d2 214 let trait_ref = projection.to_poly_trait_ref(tcx);
1a4d82fc 215
a7813a04
XL
216 if tcx.lang_items.fn_trait_kind(trait_ref.def_id()).is_none() {
217 return None;
218 }
1a4d82fc 219
9e0c209e 220 let arg_param_ty = trait_ref.substs().type_at(1);
a7813a04 221 let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty);
c30ab7b3
SL
222 debug!("deduce_sig_from_projection: arg_param_ty {:?}",
223 arg_param_ty);
1a4d82fc 224
a7813a04 225 let input_tys = match arg_param_ty.sty {
8bb4bdeb 226 ty::TyTuple(tys, _) => tys.into_iter(),
c30ab7b3
SL
227 _ => {
228 return None;
229 }
a7813a04 230 };
1a4d82fc 231
a7813a04
XL
232 let ret_param_ty = projection.0.ty;
233 let ret_param_ty = self.resolve_type_vars_if_possible(&ret_param_ty);
476ff2be 234 debug!("deduce_sig_from_projection: ret_param_ty {:?}", ret_param_ty);
1a4d82fc 235
8bb4bdeb
XL
236 let fn_sig = self.tcx.mk_fn_sig(
237 input_tys.cloned(),
238 ret_param_ty,
239 false,
240 hir::Unsafety::Normal,
241 Abi::Rust
242 );
a7813a04 243 debug!("deduce_sig_from_projection: fn_sig {:?}", fn_sig);
1a4d82fc 244
a7813a04
XL
245 Some(fn_sig)
246 }
1a4d82fc 247
a7813a04 248 fn self_type_matches_expected_vid(&self,
c30ab7b3
SL
249 trait_ref: ty::PolyTraitRef<'tcx>,
250 expected_vid: ty::TyVid)
251 -> Option<ty::PolyTraitRef<'tcx>> {
a7813a04
XL
252 let self_ty = self.shallow_resolve(trait_ref.self_ty());
253 debug!("self_type_matches_expected_vid(trait_ref={:?}, self_ty={:?})",
254 trait_ref,
255 self_ty);
256 match self_ty.sty {
257 ty::TyInfer(ty::TyVar(v)) if expected_vid == v => Some(trait_ref),
258 _ => None,
259 }
1a4d82fc 260 }
1a4d82fc 261}