@@ -34,7 +34,7 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
34
34
expected. repr( fcx. tcx( ) ) ) ;
35
35
36
36
let expected_sig_and_kind = expected. to_option ( fcx) . and_then ( |ty| {
37
- deduce_closure_expectations_from_expected_type ( fcx, ty)
37
+ deduce_expectations_from_expected_type ( fcx, ty)
38
38
} ) ;
39
39
40
40
match opt_kind {
@@ -137,36 +137,73 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
137
137
fcx. inh . closures . borrow_mut ( ) . insert ( expr_def_id, closure) ;
138
138
}
139
139
140
- fn deduce_closure_expectations_from_expected_type < ' a , ' tcx > (
140
+ fn deduce_expectations_from_expected_type < ' a , ' tcx > (
141
141
fcx : & FnCtxt < ' a , ' tcx > ,
142
142
expected_ty : Ty < ' tcx > )
143
143
-> Option < ( ty:: FnSig < ' tcx > , ty:: ClosureKind ) >
144
144
{
145
145
match expected_ty. sty {
146
146
ty:: ty_trait( ref object_type) => {
147
- let trait_ref =
148
- object_type. principal_trait_ref_with_self_ty ( fcx. tcx ( ) ,
149
- fcx. tcx ( ) . types . err ) ;
150
- deduce_closure_expectations_from_trait_ref ( fcx, & trait_ref)
147
+ let proj_bounds = object_type. projection_bounds_with_self_ty ( fcx. tcx ( ) ,
148
+ fcx. tcx ( ) . types . err ) ;
149
+ proj_bounds. iter ( )
150
+ . filter_map ( |pb| deduce_expectations_from_projection ( fcx, pb) )
151
+ . next ( )
151
152
}
152
153
ty:: ty_infer( ty:: TyVar ( vid) ) => {
153
- deduce_closure_expectations_from_obligations ( fcx, vid)
154
+ deduce_expectations_from_obligations ( fcx, vid)
154
155
}
155
156
_ => {
156
157
None
157
158
}
158
159
}
159
160
}
160
161
161
- fn deduce_closure_expectations_from_trait_ref < ' a , ' tcx > (
162
+ fn deduce_expectations_from_obligations < ' a , ' tcx > (
162
163
fcx : & FnCtxt < ' a , ' tcx > ,
163
- trait_ref : & ty:: PolyTraitRef < ' tcx > )
164
+ expected_vid : ty:: TyVid )
165
+ -> Option < ( ty:: FnSig < ' tcx > , ty:: ClosureKind ) >
166
+ {
167
+ let fulfillment_cx = fcx. inh . fulfillment_cx . borrow ( ) ;
168
+ // Here `expected_ty` is known to be a type inference variable.
169
+
170
+ fulfillment_cx. pending_obligations ( )
171
+ . iter ( )
172
+ . filter_map ( |obligation| {
173
+ match obligation. predicate {
174
+ ty:: Predicate :: Projection ( ref proj_predicate) => {
175
+ let trait_ref = proj_predicate. to_poly_trait_ref ( ) ;
176
+ let self_ty = fcx. infcx ( ) . shallow_resolve ( trait_ref. self_ty ( ) ) ;
177
+ match self_ty. sty {
178
+ ty:: ty_infer( ty:: TyVar ( v) ) if expected_vid == v => {
179
+ deduce_expectations_from_projection ( fcx, proj_predicate)
180
+ }
181
+ _ => {
182
+ None
183
+ }
184
+ }
185
+ }
186
+ _ => {
187
+ None
188
+ }
189
+ }
190
+ } )
191
+ . next ( )
192
+ }
193
+
194
+ /// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
195
+ /// everything we need to know about a closure.
196
+ fn deduce_expectations_from_projection < ' a , ' tcx > (
197
+ fcx : & FnCtxt < ' a , ' tcx > ,
198
+ projection : & ty:: PolyProjectionPredicate < ' tcx > )
164
199
-> Option < ( ty:: FnSig < ' tcx > , ty:: ClosureKind ) >
165
200
{
166
201
let tcx = fcx. tcx ( ) ;
167
202
168
- debug ! ( "deduce_closure_expectations_from_object_type({})" ,
169
- trait_ref. repr( tcx) ) ;
203
+ debug ! ( "deduce_expectations_from_projection({})" ,
204
+ projection. repr( tcx) ) ;
205
+
206
+ let trait_ref = projection. to_poly_trait_ref ( ) ;
170
207
171
208
let kind = match tcx. lang_items . fn_trait_kind ( trait_ref. def_id ( ) ) {
172
209
Some ( k) => k,
@@ -185,7 +222,7 @@ fn deduce_closure_expectations_from_trait_ref<'a,'tcx>(
185
222
} ;
186
223
debug ! ( "input_tys {}" , input_tys. repr( tcx) ) ;
187
224
188
- let ret_param_ty = * trait_ref . substs ( ) . types . get ( subst :: TypeSpace , 1 ) ;
225
+ let ret_param_ty = projection . 0 . ty ;
189
226
let ret_param_ty = fcx. infcx ( ) . resolve_type_vars_if_possible ( & ret_param_ty) ;
190
227
debug ! ( "ret_param_ty {}" , ret_param_ty. repr( tcx) ) ;
191
228
@@ -199,30 +236,3 @@ fn deduce_closure_expectations_from_trait_ref<'a,'tcx>(
199
236
return Some ( ( fn_sig, kind) ) ;
200
237
}
201
238
202
- fn deduce_closure_expectations_from_obligations < ' a , ' tcx > (
203
- fcx : & FnCtxt < ' a , ' tcx > ,
204
- expected_vid : ty:: TyVid )
205
- -> Option < ( ty:: FnSig < ' tcx > , ty:: ClosureKind ) >
206
- {
207
- // Here `expected_ty` is known to be a type inference variable.
208
- for obligation in fcx. inh . fulfillment_cx . borrow ( ) . pending_obligations ( ) . iter ( ) {
209
- match obligation. predicate {
210
- ty:: Predicate :: Trait ( ref trait_predicate) => {
211
- let trait_ref = trait_predicate. to_poly_trait_ref ( ) ;
212
- let self_ty = fcx. infcx ( ) . shallow_resolve ( trait_ref. self_ty ( ) ) ;
213
- match self_ty. sty {
214
- ty:: ty_infer( ty:: TyVar ( v) ) if expected_vid == v => { }
215
- _ => { continue ; }
216
- }
217
-
218
- match deduce_closure_expectations_from_trait_ref ( fcx, & trait_ref) {
219
- Some ( e) => { return Some ( e) ; }
220
- None => { }
221
- }
222
- }
223
- _ => { }
224
- }
225
- }
226
-
227
- None
228
- }
0 commit comments