@@ -13,6 +13,8 @@ use super::AutorefArgs;
1313use super :: check_argument_types;
1414use super :: check_expr;
1515use super :: check_method_argument_types;
16+ use super :: demand;
17+ use super :: DeferredResolution ;
1618use super :: err_args;
1719use super :: Expectation ;
1820use super :: expected_types_for_fn_args;
@@ -24,13 +26,14 @@ use super::TupleArgumentsFlag;
2426use super :: UnresolvedTypeAction ;
2527use super :: write_call;
2628
29+ use CrateCtxt ;
2730use middle:: infer;
28- use middle:: ty:: { self , Ty } ;
31+ use middle:: ty:: { self , Ty , ClosureTyper } ;
2932use syntax:: ast;
3033use syntax:: codemap:: Span ;
3134use syntax:: parse:: token;
3235use syntax:: ptr:: P ;
33- use CrateCtxt ;
36+ use util :: ppaux :: Repr ;
3437
3538/// Check that it is legal to call methods of the trait corresponding
3639/// 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:
6669}
6770
6871pub 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 > ] ,
7275 expected : Expectation < ' tcx > )
7376{
7477 check_expr ( fcx, callee_expr) ;
@@ -96,24 +99,35 @@ pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
9699 confirm_builtin_call ( fcx, call_expr, callee_ty, arg_exprs, expected) ;
97100 }
98101
102+ Some ( CallStep :: Closure ( fn_sig) ) => {
103+ confirm_closure_call ( fcx, call_expr, arg_exprs, expected, fn_sig) ;
104+ }
105+
99106 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) ;
101109 }
102110 }
103111}
104112
105113enum CallStep < ' tcx > {
106114 Builtin ,
115+ Closure ( ty:: FnSig < ' tcx > ) ,
107116 Overloaded ( ty:: MethodCallee < ' tcx > )
108117}
109118
110119fn 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 ,
113122 adjusted_ty : Ty < ' tcx > ,
114123 autoderefref : ty:: AutoDerefRef < ' tcx > )
115124 -> Option < CallStep < ' tcx > >
116125{
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+
117131 // If the callee is a bare function or a closure, then we're all set.
118132 match structurally_resolved_type ( fcx, callee_expr. span , adjusted_ty) . sty {
119133 ty:: ty_bare_fn( ..) => {
@@ -123,9 +137,37 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
123137 return Some ( CallStep :: Builtin ) ;
124138 }
125139
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+
126157 _ => { }
127158 }
128159
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+ {
129171 // Try the options that are least restrictive on the caller first.
130172 for & ( opt_trait_def_id, method_name) in [
131173 ( fcx. tcx ( ) . lang_items . fn_trait ( ) , token:: intern ( "call" ) ) ,
@@ -147,7 +189,7 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
147189 None ) {
148190 None => continue ,
149191 Some ( method_callee) => {
150- return Some ( CallStep :: Overloaded ( method_callee) ) ;
192+ return Some ( method_callee) ;
151193 }
152194 }
153195 }
@@ -158,7 +200,7 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
158200fn confirm_builtin_call < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
159201 call_expr : & ast:: Expr ,
160202 callee_ty : Ty < ' tcx > ,
161- arg_exprs : & [ P < ast:: Expr > ] ,
203+ arg_exprs : & ' tcx [ P < ast:: Expr > ] ,
162204 expected : Expectation < ' tcx > )
163205{
164206 let error_fn_sig;
@@ -215,22 +257,124 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
215257 write_call ( fcx, call_expr, fn_sig. output ) ;
216258}
217259
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+
218290fn confirm_overloaded_call < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
219291 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 > )
223296{
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 > ) {
232314 let method_call = ty:: MethodCall :: expr ( call_expr. id ) ;
233315 fcx. inh . method_map . borrow_mut ( ) . insert ( method_call, method_callee) ;
234- write_call ( fcx, call_expr, output_type) ;
235316}
236317
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