@@ -13,6 +13,8 @@ use super::AutorefArgs;
13
13
use super :: check_argument_types;
14
14
use super :: check_expr;
15
15
use super :: check_method_argument_types;
16
+ use super :: demand;
17
+ use super :: DeferredResolution ;
16
18
use super :: err_args;
17
19
use super :: Expectation ;
18
20
use super :: expected_types_for_fn_args;
@@ -24,13 +26,14 @@ use super::TupleArgumentsFlag;
24
26
use super :: UnresolvedTypeAction ;
25
27
use super :: write_call;
26
28
29
+ use CrateCtxt ;
27
30
use middle:: infer;
28
- use middle:: ty:: { self , Ty } ;
31
+ use middle:: ty:: { self , Ty , ClosureTyper } ;
29
32
use syntax:: ast;
30
33
use syntax:: codemap:: Span ;
31
34
use syntax:: parse:: token;
32
35
use syntax:: ptr:: P ;
33
- use CrateCtxt ;
36
+ use util :: ppaux :: Repr ;
34
37
35
38
/// Check that it is legal to call methods of the trait corresponding
36
39
/// to `trait_id` (this only cares about the trait, not the specific
@@ -66,9 +69,9 @@ pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id:
66
69
}
67
70
68
71
pub fn check_call < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
69
- call_expr : & ast:: Expr ,
70
- callee_expr : & ast:: Expr ,
71
- arg_exprs : & [ P < ast:: Expr > ] ,
72
+ call_expr : & ' tcx ast:: Expr ,
73
+ callee_expr : & ' tcx ast:: Expr ,
74
+ arg_exprs : & ' tcx [ P < ast:: Expr > ] ,
72
75
expected : Expectation < ' tcx > )
73
76
{
74
77
check_expr ( fcx, callee_expr) ;
@@ -96,24 +99,35 @@ pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
96
99
confirm_builtin_call ( fcx, call_expr, callee_ty, arg_exprs, expected) ;
97
100
}
98
101
102
+ Some ( CallStep :: Closure ( fn_sig) ) => {
103
+ confirm_closure_call ( fcx, call_expr, arg_exprs, expected, fn_sig) ;
104
+ }
105
+
99
106
Some ( CallStep :: Overloaded ( method_callee) ) => {
100
- confirm_overloaded_call ( fcx, call_expr, arg_exprs, method_callee, expected) ;
107
+ confirm_overloaded_call ( fcx, call_expr, callee_expr,
108
+ arg_exprs, expected, method_callee) ;
101
109
}
102
110
}
103
111
}
104
112
105
113
enum CallStep < ' tcx > {
106
114
Builtin ,
115
+ Closure ( ty:: FnSig < ' tcx > ) ,
107
116
Overloaded ( ty:: MethodCallee < ' tcx > )
108
117
}
109
118
110
119
fn try_overloaded_call_step < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
111
- call_expr : & ast:: Expr ,
112
- callee_expr : & ast:: Expr ,
120
+ call_expr : & ' tcx ast:: Expr ,
121
+ callee_expr : & ' tcx ast:: Expr ,
113
122
adjusted_ty : Ty < ' tcx > ,
114
123
autoderefref : ty:: AutoDerefRef < ' tcx > )
115
124
-> Option < CallStep < ' tcx > >
116
125
{
126
+ debug ! ( "try_overloaded_call_step(call_expr={}, adjusted_ty={}, autoderefref={})" ,
127
+ call_expr. repr( fcx. tcx( ) ) ,
128
+ adjusted_ty. repr( fcx. tcx( ) ) ,
129
+ autoderefref. repr( fcx. tcx( ) ) ) ;
130
+
117
131
// If the callee is a bare function or a closure, then we're all set.
118
132
match structurally_resolved_type ( fcx, callee_expr. span , adjusted_ty) . sty {
119
133
ty:: ty_bare_fn( ..) => {
@@ -123,9 +137,37 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
123
137
return Some ( CallStep :: Builtin ) ;
124
138
}
125
139
140
+ ty:: ty_closure( def_id, _, substs) => {
141
+ let closure_ty =
142
+ fcx. closure_type ( def_id, substs) ;
143
+ let fn_sig =
144
+ fcx. infcx ( ) . replace_late_bound_regions_with_fresh_var ( call_expr. span ,
145
+ infer:: FnCall ,
146
+ & closure_ty. sig ) . 0 ;
147
+ fcx. record_deferred_resolution ( box CallResolution {
148
+ call_expr : call_expr,
149
+ callee_expr : callee_expr,
150
+ adjusted_ty : adjusted_ty,
151
+ autoderefref : autoderefref,
152
+ fn_sig : fn_sig. clone ( ) ,
153
+ } ) ;
154
+ return Some ( CallStep :: Closure ( fn_sig) ) ;
155
+ }
156
+
126
157
_ => { }
127
158
}
128
159
160
+ try_overloaded_call_traits ( fcx, call_expr, callee_expr, adjusted_ty, autoderefref)
161
+ . map ( |method_callee| CallStep :: Overloaded ( method_callee) )
162
+ }
163
+
164
+ fn try_overloaded_call_traits < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
165
+ call_expr : & ast:: Expr ,
166
+ callee_expr : & ast:: Expr ,
167
+ adjusted_ty : Ty < ' tcx > ,
168
+ autoderefref : ty:: AutoDerefRef < ' tcx > )
169
+ -> Option < ty:: MethodCallee < ' tcx > >
170
+ {
129
171
// Try the options that are least restrictive on the caller first.
130
172
for & ( opt_trait_def_id, method_name) in [
131
173
( fcx. tcx ( ) . lang_items . fn_trait ( ) , token:: intern ( "call" ) ) ,
@@ -147,7 +189,7 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
147
189
None ) {
148
190
None => continue ,
149
191
Some ( method_callee) => {
150
- return Some ( CallStep :: Overloaded ( method_callee) ) ;
192
+ return Some ( method_callee) ;
151
193
}
152
194
}
153
195
}
@@ -158,7 +200,7 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
158
200
fn confirm_builtin_call < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
159
201
call_expr : & ast:: Expr ,
160
202
callee_ty : Ty < ' tcx > ,
161
- arg_exprs : & [ P < ast:: Expr > ] ,
203
+ arg_exprs : & ' tcx [ P < ast:: Expr > ] ,
162
204
expected : Expectation < ' tcx > )
163
205
{
164
206
let error_fn_sig;
@@ -215,22 +257,124 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
215
257
write_call ( fcx, call_expr, fn_sig. output ) ;
216
258
}
217
259
260
+ fn confirm_closure_call < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
261
+ call_expr : & ast:: Expr ,
262
+ arg_exprs : & ' tcx [ P < ast:: Expr > ] ,
263
+ expected : Expectation < ' tcx > ,
264
+ fn_sig : ty:: FnSig < ' tcx > )
265
+ {
266
+ // `fn_sig` is the *signature* of the cosure being called. We
267
+ // don't know the full details yet (`Fn` vs `FnMut` etc), but we
268
+ // do know the types expected for each argument and the return
269
+ // type.
270
+
271
+ let expected_arg_tys =
272
+ expected_types_for_fn_args ( fcx,
273
+ call_expr. span ,
274
+ expected,
275
+ fn_sig. output . clone ( ) ,
276
+ & * fn_sig. inputs ) ;
277
+
278
+ check_argument_types ( fcx,
279
+ call_expr. span ,
280
+ & * fn_sig. inputs ,
281
+ & * expected_arg_tys,
282
+ arg_exprs,
283
+ AutorefArgs :: No ,
284
+ fn_sig. variadic ,
285
+ TupleArgumentsFlag :: TupleArguments ) ;
286
+
287
+ write_call ( fcx, call_expr, fn_sig. output ) ;
288
+ }
289
+
218
290
fn confirm_overloaded_call < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
219
291
call_expr : & ast:: Expr ,
220
- arg_exprs : & [ P < ast:: Expr > ] ,
221
- method_callee : ty:: MethodCallee < ' tcx > ,
222
- expected : Expectation < ' tcx > )
292
+ callee_expr : & ' tcx ast:: Expr ,
293
+ arg_exprs : & ' tcx [ P < ast:: Expr > ] ,
294
+ expected : Expectation < ' tcx > ,
295
+ method_callee : ty:: MethodCallee < ' tcx > )
223
296
{
224
- let output_type = check_method_argument_types ( fcx,
225
- call_expr. span ,
226
- method_callee. ty ,
227
- call_expr,
228
- arg_exprs,
229
- AutorefArgs :: No ,
230
- TupleArgumentsFlag :: TupleArguments ,
231
- expected) ;
297
+ let output_type =
298
+ check_method_argument_types ( fcx,
299
+ call_expr. span ,
300
+ method_callee. ty ,
301
+ callee_expr,
302
+ arg_exprs,
303
+ AutorefArgs :: No ,
304
+ TupleArgumentsFlag :: TupleArguments ,
305
+ expected) ;
306
+ write_call ( fcx, call_expr, output_type) ;
307
+
308
+ write_overloaded_call_method_map ( fcx, call_expr, method_callee) ;
309
+ }
310
+
311
+ fn write_overloaded_call_method_map < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
312
+ call_expr : & ast:: Expr ,
313
+ method_callee : ty:: MethodCallee < ' tcx > ) {
232
314
let method_call = ty:: MethodCall :: expr ( call_expr. id ) ;
233
315
fcx. inh . method_map . borrow_mut ( ) . insert ( method_call, method_callee) ;
234
- write_call ( fcx, call_expr, output_type) ;
235
316
}
236
317
318
+ struct CallResolution < ' tcx > {
319
+ call_expr : & ' tcx ast:: Expr ,
320
+ callee_expr : & ' tcx ast:: Expr ,
321
+ adjusted_ty : Ty < ' tcx > ,
322
+ autoderefref : ty:: AutoDerefRef < ' tcx > ,
323
+ fn_sig : ty:: FnSig < ' tcx > ,
324
+ }
325
+
326
+ impl < ' tcx > Repr < ' tcx > for CallResolution < ' tcx > {
327
+ fn repr ( & self , tcx : & ty:: ctxt < ' tcx > ) -> String {
328
+ format ! ( "CallResolution(call_expr={}, callee_expr={}, adjusted_ty={}, \
329
+ autoderefref={}, fn_sig={})",
330
+ self . call_expr. repr( tcx) ,
331
+ self . callee_expr. repr( tcx) ,
332
+ self . adjusted_ty. repr( tcx) ,
333
+ self . autoderefref. repr( tcx) ,
334
+ self . fn_sig. repr( tcx) )
335
+ }
336
+ }
337
+
338
+ impl < ' tcx > DeferredResolution < ' tcx > for CallResolution < ' tcx > {
339
+ fn attempt_resolution < ' a > ( & self , fcx : & FnCtxt < ' a , ' tcx > ) -> bool {
340
+ debug ! ( "attempt_resolution() {}" ,
341
+ self . repr( fcx. tcx( ) ) ) ;
342
+
343
+ // We may now know enough to figure out fn vs fnmut etc.
344
+ match try_overloaded_call_traits ( fcx, self . call_expr , self . callee_expr ,
345
+ self . adjusted_ty , self . autoderefref . clone ( ) ) {
346
+ None => false ,
347
+ Some ( method_callee) => {
348
+ // One problem is that when we get here, we are going
349
+ // to have a newly instantiated function signature
350
+ // from the call trait. This has to be reconciled with
351
+ // the older function signature we had before. In
352
+ // principle we *should* be able to fn_sigs(), but we
353
+ // can't because of the annoying need for a TypeTrace.
354
+ // (This always bites me, should find a way to
355
+ // refactor it.)
356
+ let method_sig =
357
+ ty:: assert_no_late_bound_regions ( fcx. tcx ( ) ,
358
+ ty:: ty_fn_sig ( method_callee. ty ) ) ;
359
+
360
+ debug ! ( "attempt_resolution: method_callee={}" ,
361
+ method_callee. repr( fcx. tcx( ) ) ) ;
362
+
363
+ for ( & method_arg_ty, & self_arg_ty) in
364
+ method_sig. inputs [ 1 ..] . iter ( ) . zip ( self . fn_sig . inputs . iter ( ) )
365
+ {
366
+ demand:: eqtype ( fcx, self . call_expr . span , self_arg_ty, method_arg_ty) ;
367
+ }
368
+
369
+ demand:: eqtype ( fcx,
370
+ self . call_expr . span ,
371
+ method_sig. output . unwrap ( ) ,
372
+ self . fn_sig . output . unwrap ( ) ) ;
373
+
374
+ write_overloaded_call_method_map ( fcx, self . call_expr , method_callee) ;
375
+
376
+ true
377
+ }
378
+ }
379
+ }
380
+ }
0 commit comments