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.
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.
11 //! Code for type-checking closure expressions.
13 use super::{check_fn, Expectation, FnCtxt};
16 use rustc::infer::type_variable::TypeVariableOrigin;
17 use rustc::ty::{self, ToPolyTraitRef, Ty};
23 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
24 pub fn check_expr_closure(&self,
26 _capture: hir::CaptureClause,
27 decl: &'gcx hir::FnDecl,
29 expected: Expectation<'tcx>)
31 debug!("check_expr_closure(expr={:?},expected={:?})",
35 // It's always helpful for inference if we know the kind of
36 // closure sooner rather than later, so first examine the expected
37 // type, and see if can glean a closure kind from there.
38 let (expected_sig, expected_kind) = match expected.to_option(self) {
39 Some(ty) => self.deduce_expectations_from_expected_type(ty),
42 let body = self.tcx.hir.body(body_id);
43 self.check_closure(expr, expected_kind, decl, body, expected_sig)
46 fn check_closure(&self,
48 opt_kind: Option<ty::ClosureKind>,
49 decl: &'gcx hir::FnDecl,
50 body: &'gcx hir::Body,
51 expected_sig: Option<ty::FnSig<'tcx>>)
53 debug!("check_closure opt_kind={:?} expected_sig={:?}",
57 let expr_def_id = self.tcx.hir.local_def_id(expr.id);
58 let sig = AstConv::ty_of_closure(self,
59 hir::Unsafety::Normal,
63 // `deduce_expectations_from_expected_type` introduces late-bound
64 // lifetimes defined elsewhere, which we need to anonymize away.
65 let sig = self.tcx.anonymize_late_bound_regions(&sig);
67 // Create type variables (for now) to represent the transformed
68 // types of upvars. These will be unified during the upvar
69 // inference phase (`upvar.rs`).
70 let closure_type = self.tcx.mk_closure(expr_def_id,
71 self.parameter_environment.free_substs.extend_to(self.tcx, expr_def_id,
72 |_, _| span_bug!(expr.span, "closure has region param"),
73 |_, _| self.infcx.next_ty_var(TypeVariableOrigin::TransformedUpvar(expr.span))
77 debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type);
79 let fn_sig = self.liberate_late_bound_regions(expr_def_id, &sig);
80 let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
81 body.value.id, &fn_sig);
83 check_fn(self, fn_sig, decl, expr.id, body);
85 // Tuple up the arguments and insert the resulting function type into
86 // the `closures` table.
87 let sig = sig.map_bound(|sig| self.tcx.mk_fn_sig(
88 iter::once(self.tcx.intern_tup(sig.inputs(), false)),
95 debug!("closure for {:?} --> sig={:?} opt_kind={:?}",
100 self.tables.borrow_mut().closure_tys.insert(expr.id, sig);
103 self.tables.borrow_mut().closure_kinds.insert(expr.id, kind);
111 fn deduce_expectations_from_expected_type
113 expected_ty: Ty<'tcx>)
114 -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
115 debug!("deduce_expectations_from_expected_type(expected_ty={:?})",
118 match expected_ty.sty {
119 ty::TyDynamic(ref object_type, ..) => {
120 let sig = object_type.projection_bounds()
122 let pb = pb.with_self_ty(self.tcx, self.tcx.types.err);
123 self.deduce_sig_from_projection(&pb)
126 let kind = object_type.principal()
127 .and_then(|p| self.tcx.lang_items.fn_trait_kind(p.def_id()));
130 ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
131 ty::TyFnPtr(sig) => (Some(sig.skip_binder().clone()), Some(ty::ClosureKind::Fn)),
136 fn deduce_expectations_from_obligations
138 expected_vid: ty::TyVid)
139 -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
140 let fulfillment_cx = self.fulfillment_cx.borrow();
141 // Here `expected_ty` is known to be a type inference variable.
143 let expected_sig = fulfillment_cx.pending_obligations()
145 .map(|obligation| &obligation.obligation)
146 .filter_map(|obligation| {
147 debug!("deduce_expectations_from_obligations: obligation.predicate={:?}",
148 obligation.predicate);
150 match obligation.predicate {
151 // Given a Projection predicate, we can potentially infer
152 // the complete signature.
153 ty::Predicate::Projection(ref proj_predicate) => {
154 let trait_ref = proj_predicate.to_poly_trait_ref();
155 self.self_type_matches_expected_vid(trait_ref, expected_vid)
156 .and_then(|_| self.deduce_sig_from_projection(proj_predicate))
163 // Even if we can't infer the full signature, we may be able to
164 // infer the kind. This can occur if there is a trait-reference
165 // like `F : Fn<A>`. Note that due to subtyping we could encounter
166 // many viable options, so pick the most restrictive.
167 let expected_kind = fulfillment_cx.pending_obligations()
169 .map(|obligation| &obligation.obligation)
170 .filter_map(|obligation| {
171 let opt_trait_ref = match obligation.predicate {
172 ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref()),
173 ty::Predicate::Trait(ref data) => Some(data.to_poly_trait_ref()),
174 ty::Predicate::Equate(..) => None,
175 ty::Predicate::Subtype(..) => None,
176 ty::Predicate::RegionOutlives(..) => None,
177 ty::Predicate::TypeOutlives(..) => None,
178 ty::Predicate::WellFormed(..) => None,
179 ty::Predicate::ObjectSafe(..) => None,
181 // NB: This predicate is created by breaking down a
182 // `ClosureType: FnFoo()` predicate, where
183 // `ClosureType` represents some `TyClosure`. It can't
184 // possibly be referring to the current closure,
185 // because we haven't produced the `TyClosure` for
186 // this closure yet; this is exactly why the other
187 // code is looking for a self type of a unresolved
188 // inference variable.
189 ty::Predicate::ClosureKind(..) => None,
191 opt_trait_ref.and_then(|tr| self.self_type_matches_expected_vid(tr, expected_vid))
192 .and_then(|tr| self.tcx.lang_items.fn_trait_kind(tr.def_id()))
195 |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur))));
197 (expected_sig, expected_kind)
200 /// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
201 /// everything we need to know about a closure.
202 fn deduce_sig_from_projection(&self,
203 projection: &ty::PolyProjectionPredicate<'tcx>)
204 -> Option<ty::FnSig<'tcx>> {
207 debug!("deduce_sig_from_projection({:?})", projection);
209 let trait_ref = projection.to_poly_trait_ref();
211 if tcx.lang_items.fn_trait_kind(trait_ref.def_id()).is_none() {
215 let arg_param_ty = trait_ref.substs().type_at(1);
216 let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty);
217 debug!("deduce_sig_from_projection: arg_param_ty {:?}",
220 let input_tys = match arg_param_ty.sty {
221 ty::TyTuple(tys, _) => tys.into_iter(),
227 let ret_param_ty = projection.0.ty;
228 let ret_param_ty = self.resolve_type_vars_if_possible(&ret_param_ty);
229 debug!("deduce_sig_from_projection: ret_param_ty {:?}", ret_param_ty);
231 let fn_sig = self.tcx.mk_fn_sig(
235 hir::Unsafety::Normal,
238 debug!("deduce_sig_from_projection: fn_sig {:?}", fn_sig);
243 fn self_type_matches_expected_vid(&self,
244 trait_ref: ty::PolyTraitRef<'tcx>,
245 expected_vid: ty::TyVid)
246 -> Option<ty::PolyTraitRef<'tcx>> {
247 let self_ty = self.shallow_resolve(trait_ref.self_ty());
248 debug!("self_type_matches_expected_vid(trait_ref={:?}, self_ty={:?})",
252 ty::TyInfer(ty::TyVar(v)) if expected_vid == v => Some(trait_ref),