@@ -19,13 +19,14 @@ use middle::def;
19
19
use middle:: freevars;
20
20
use middle:: pat_util;
21
21
use middle:: ty;
22
- use middle:: typeck:: MethodCall ;
22
+ use middle:: typeck:: { MethodCall , MethodObject , MethodOrigin , MethodParam } ;
23
+ use middle:: typeck:: { MethodStatic } ;
23
24
use middle:: typeck;
24
- use syntax:: ast;
25
- use syntax:: codemap:: { Span } ;
26
25
use util:: ppaux:: Repr ;
27
26
28
27
use std:: gc:: Gc ;
28
+ use syntax:: ast;
29
+ use syntax:: codemap:: Span ;
29
30
30
31
///////////////////////////////////////////////////////////////////////////
31
32
// The Delegate trait
@@ -101,6 +102,74 @@ pub enum MutateMode {
101
102
WriteAndRead , // x += y
102
103
}
103
104
105
+ enum OverloadedCallType {
106
+ FnOverloadedCall ,
107
+ FnMutOverloadedCall ,
108
+ FnOnceOverloadedCall ,
109
+ }
110
+
111
+ impl OverloadedCallType {
112
+ fn from_trait_id ( tcx : & ty:: ctxt , trait_id : ast:: DefId )
113
+ -> OverloadedCallType {
114
+ for & ( maybe_function_trait, overloaded_call_type) in [
115
+ ( tcx. lang_items . fn_once_trait ( ) , FnOnceOverloadedCall ) ,
116
+ ( tcx. lang_items . fn_mut_trait ( ) , FnMutOverloadedCall ) ,
117
+ ( tcx. lang_items . fn_trait ( ) , FnOverloadedCall )
118
+ ] . iter ( ) {
119
+ match maybe_function_trait {
120
+ Some ( function_trait) if function_trait == trait_id => {
121
+ return overloaded_call_type
122
+ }
123
+ _ => continue ,
124
+ }
125
+ }
126
+
127
+ tcx. sess . bug ( "overloaded call didn't map to known function trait" )
128
+ }
129
+
130
+ fn from_method_id ( tcx : & ty:: ctxt , method_id : ast:: DefId )
131
+ -> OverloadedCallType {
132
+ let method_descriptor =
133
+ match tcx. methods . borrow_mut ( ) . find ( & method_id) {
134
+ None => {
135
+ tcx. sess . bug ( "overloaded call method wasn't in method \
136
+ map")
137
+ }
138
+ Some ( ref method_descriptor) => ( * method_descriptor) . clone ( ) ,
139
+ } ;
140
+ let impl_id = match method_descriptor. container {
141
+ ty:: TraitContainer ( _) => {
142
+ tcx. sess . bug ( "statically resolved overloaded call method \
143
+ belonged to a trait?!")
144
+ }
145
+ ty:: ImplContainer ( impl_id) => impl_id,
146
+ } ;
147
+ let trait_ref = match ty:: impl_trait_ref ( tcx, impl_id) {
148
+ None => {
149
+ tcx. sess . bug ( "statically resolved overloaded call impl \
150
+ didn't implement a trait?!")
151
+ }
152
+ Some ( ref trait_ref) => ( * trait_ref) . clone ( ) ,
153
+ } ;
154
+ OverloadedCallType :: from_trait_id ( tcx, trait_ref. def_id )
155
+ }
156
+
157
+ fn from_method_origin ( tcx : & ty:: ctxt , origin : & MethodOrigin )
158
+ -> OverloadedCallType {
159
+ match * origin {
160
+ MethodStatic ( def_id) => {
161
+ OverloadedCallType :: from_method_id ( tcx, def_id)
162
+ }
163
+ MethodParam ( ref method_param) => {
164
+ OverloadedCallType :: from_trait_id ( tcx, method_param. trait_id )
165
+ }
166
+ MethodObject ( ref method_object) => {
167
+ OverloadedCallType :: from_trait_id ( tcx, method_object. trait_id )
168
+ }
169
+ }
170
+ }
171
+ }
172
+
104
173
///////////////////////////////////////////////////////////////////////////
105
174
// The ExprUseVisitor type
106
175
//
@@ -413,19 +482,37 @@ impl<'d,'t,TYPER:mc::Typer> ExprUseVisitor<'d,'t,TYPER> {
413
482
}
414
483
}
415
484
_ => {
416
- match self . tcx ( )
417
- . method_map
418
- . borrow ( )
419
- . find ( & MethodCall :: expr ( call. id ) ) {
420
- Some ( _) => {
421
- // FIXME(#14774, pcwalton): Implement this.
485
+ let overloaded_call_type =
486
+ match self . tcx ( )
487
+ . method_map
488
+ . borrow ( )
489
+ . find ( & MethodCall :: expr ( call. id ) ) {
490
+ Some ( ref method_callee) => {
491
+ OverloadedCallType :: from_method_origin (
492
+ self . tcx ( ) ,
493
+ & method_callee. origin )
422
494
}
423
495
None => {
424
496
self . tcx ( ) . sess . span_bug (
425
497
callee. span ,
426
498
format ! ( "unexpected callee type {}" ,
427
- callee_ty. repr( self . tcx( ) ) ) . as_slice ( ) ) ;
499
+ callee_ty. repr( self . tcx( ) ) ) . as_slice ( ) )
500
+ }
501
+ } ;
502
+ match overloaded_call_type {
503
+ FnMutOverloadedCall => {
504
+ self . borrow_expr ( callee,
505
+ ty:: ReScope ( call. id ) ,
506
+ ty:: MutBorrow ,
507
+ ClosureInvocation ) ;
508
+ }
509
+ FnOverloadedCall => {
510
+ self . borrow_expr ( callee,
511
+ ty:: ReScope ( call. id ) ,
512
+ ty:: ImmBorrow ,
513
+ ClosureInvocation ) ;
428
514
}
515
+ FnOnceOverloadedCall => self . consume_expr ( callee) ,
429
516
}
430
517
}
431
518
}
0 commit comments