@@ -25,46 +25,21 @@ use util::ppaux::Repr;
25
25
pub fn check_expr_closure < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
26
26
expr : & ast:: Expr ,
27
27
_capture : ast:: CaptureClause ,
28
- opt_kind : Option < ast:: ClosureKind > ,
29
28
decl : & ' tcx ast:: FnDecl ,
30
29
body : & ' tcx ast:: Block ,
31
30
expected : Expectation < ' tcx > ) {
32
31
debug ! ( "check_expr_closure(expr={},expected={})" ,
33
32
expr. repr( fcx. tcx( ) ) ,
34
33
expected. repr( fcx. tcx( ) ) ) ;
35
34
36
- let expected_sig_and_kind = expected. to_option ( fcx) . and_then ( |ty| {
37
- deduce_expectations_from_expected_type ( fcx, ty)
38
- } ) ;
39
-
40
- match opt_kind {
41
- None => {
42
- // If users didn't specify what sort of closure they want,
43
- // examine the expected type. For now, if we see explicit
44
- // evidence than an unboxed closure is desired, we'll use
45
- // that. Otherwise, we leave it unspecified, to be filled
46
- // in by upvar inference.
47
- match expected_sig_and_kind {
48
- None => { // don't have information about the kind, request explicit annotation
49
- check_closure ( fcx, expr, None , decl, body, None ) ;
50
- } ,
51
- Some ( ( sig, kind) ) => {
52
- check_closure ( fcx, expr, Some ( kind) , decl, body, Some ( sig) ) ;
53
- }
54
- }
55
- }
56
-
57
- Some ( kind) => {
58
- let kind = match kind {
59
- ast:: FnClosureKind => ty:: FnClosureKind ,
60
- ast:: FnMutClosureKind => ty:: FnMutClosureKind ,
61
- ast:: FnOnceClosureKind => ty:: FnOnceClosureKind ,
62
- } ;
63
-
64
- let expected_sig = expected_sig_and_kind. map ( |t| t. 0 ) ;
65
- check_closure ( fcx, expr, Some ( kind) , decl, body, expected_sig) ;
66
- }
67
- }
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 ( fcx) {
39
+ Some ( ty) => deduce_expectations_from_expected_type ( fcx, ty) ,
40
+ None => ( None , None )
41
+ } ;
42
+ check_closure ( fcx, expr, expected_kind, decl, body, expected_sig)
68
43
}
69
44
70
45
fn check_closure < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
@@ -133,55 +108,92 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
133
108
fn deduce_expectations_from_expected_type < ' a , ' tcx > (
134
109
fcx : & FnCtxt < ' a , ' tcx > ,
135
110
expected_ty : Ty < ' tcx > )
136
- -> Option < ( ty:: FnSig < ' tcx > , ty:: ClosureKind ) >
111
+ -> ( Option < ty:: FnSig < ' tcx > > , Option < ty:: ClosureKind > )
137
112
{
113
+ debug ! ( "deduce_expectations_from_expected_type(expected_ty={})" ,
114
+ expected_ty. repr( fcx. tcx( ) ) ) ;
115
+
138
116
match expected_ty. sty {
139
117
ty:: ty_trait( ref object_type) => {
140
118
let proj_bounds = object_type. projection_bounds_with_self_ty ( fcx. tcx ( ) ,
141
119
fcx. tcx ( ) . types . err ) ;
142
- proj_bounds. iter ( )
143
- . filter_map ( |pb| deduce_expectations_from_projection ( fcx, pb) )
144
- . next ( )
120
+ let expectations =
121
+ proj_bounds. iter ( )
122
+ . filter_map ( |pb| deduce_expectations_from_projection ( fcx, pb) )
123
+ . next ( ) ;
124
+
125
+ match expectations {
126
+ Some ( ( sig, kind) ) => ( Some ( sig) , Some ( kind) ) ,
127
+ None => ( None , None )
128
+ }
145
129
}
146
130
ty:: ty_infer( ty:: TyVar ( vid) ) => {
147
131
deduce_expectations_from_obligations ( fcx, vid)
148
132
}
149
133
_ => {
150
- None
134
+ ( None , None )
151
135
}
152
136
}
153
137
}
154
138
155
139
fn deduce_expectations_from_obligations < ' a , ' tcx > (
156
140
fcx : & FnCtxt < ' a , ' tcx > ,
157
141
expected_vid : ty:: TyVid )
158
- -> Option < ( ty:: FnSig < ' tcx > , ty:: ClosureKind ) >
142
+ -> ( Option < ty:: FnSig < ' tcx > > , Option < ty:: ClosureKind > )
159
143
{
160
144
let fulfillment_cx = fcx. inh . fulfillment_cx . borrow ( ) ;
161
145
// Here `expected_ty` is known to be a type inference variable.
162
146
163
- fulfillment_cx. pending_obligations ( )
164
- . iter ( )
165
- . filter_map ( |obligation| {
166
- match obligation. predicate {
167
- ty:: Predicate :: Projection ( ref proj_predicate) => {
168
- let trait_ref = proj_predicate. to_poly_trait_ref ( ) ;
169
- let self_ty = fcx. infcx ( ) . shallow_resolve ( trait_ref. self_ty ( ) ) ;
170
- match self_ty. sty {
171
- ty:: ty_infer( ty:: TyVar ( v) ) if expected_vid == v => {
172
- deduce_expectations_from_projection ( fcx, proj_predicate)
173
- }
174
- _ => {
175
- None
176
- }
177
- }
178
- }
179
- _ => {
180
- None
181
- }
182
- }
183
- } )
184
- . next ( )
147
+ let expected_sig_and_kind =
148
+ fulfillment_cx
149
+ . pending_obligations ( )
150
+ . iter ( )
151
+ . filter_map ( |obligation| {
152
+ debug ! ( "deduce_expectations_from_obligations: obligation.predicate={}" ,
153
+ obligation. predicate. repr( fcx. tcx( ) ) ) ;
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) => {
159
+ let trait_ref = proj_predicate. to_poly_trait_ref ( ) ;
160
+ self_type_matches_expected_vid ( fcx, trait_ref, expected_vid)
161
+ . and_then ( |_| deduce_expectations_from_projection ( fcx, proj_predicate) )
162
+ }
163
+ _ => {
164
+ None
165
+ }
166
+ }
167
+ } )
168
+ . next ( ) ;
169
+
170
+ match expected_sig_and_kind {
171
+ Some ( ( sig, kind) ) => { return ( Some ( sig) , Some ( kind) ) ; }
172
+ None => { }
173
+ }
174
+
175
+ // Even if we can't infer the full signature, we may be able to
176
+ // infer the kind. This can occur if there is a trait-reference
177
+ // like `F : Fn<A>`.
178
+ let expected_kind =
179
+ fulfillment_cx
180
+ . pending_obligations ( )
181
+ . iter ( )
182
+ . filter_map ( |obligation| {
183
+ let opt_trait_ref = match obligation. predicate {
184
+ ty:: Predicate :: Projection ( ref data) => Some ( data. to_poly_trait_ref ( ) ) ,
185
+ ty:: Predicate :: Trait ( ref data) => Some ( data. to_poly_trait_ref ( ) ) ,
186
+ ty:: Predicate :: Equate ( ..) => None ,
187
+ ty:: Predicate :: RegionOutlives ( ..) => None ,
188
+ ty:: Predicate :: TypeOutlives ( ..) => None ,
189
+ } ;
190
+ opt_trait_ref
191
+ . and_then ( |trait_ref| self_type_matches_expected_vid ( fcx, trait_ref, expected_vid) )
192
+ . and_then ( |trait_ref| fcx. tcx ( ) . lang_items . fn_trait_kind ( trait_ref. def_id ( ) ) )
193
+ } )
194
+ . next ( ) ;
195
+
196
+ ( None , expected_kind)
185
197
}
186
198
187
199
/// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
@@ -229,3 +241,20 @@ fn deduce_expectations_from_projection<'a,'tcx>(
229
241
return Some ( ( fn_sig, kind) ) ;
230
242
}
231
243
244
+ fn self_type_matches_expected_vid < ' a , ' tcx > (
245
+ fcx : & FnCtxt < ' a , ' tcx > ,
246
+ trait_ref : ty:: PolyTraitRef < ' tcx > ,
247
+ expected_vid : ty:: TyVid )
248
+ -> Option < ty:: PolyTraitRef < ' tcx > >
249
+ {
250
+ let self_ty = fcx. infcx ( ) . shallow_resolve ( trait_ref. self_ty ( ) ) ;
251
+ debug ! ( "self_type_matches_expected_vid(trait_ref={}, self_ty={})" ,
252
+ trait_ref. repr( fcx. tcx( ) ) ,
253
+ self_ty. repr( fcx. tcx( ) ) ) ;
254
+ match self_ty. sty {
255
+ ty:: ty_infer( ty:: TyVar ( v) ) if expected_vid == v => Some ( trait_ref) ,
256
+ _ => None ,
257
+ }
258
+ }
259
+
260
+
0 commit comments