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