@@ -19,13 +19,14 @@ use middle::def;
1919use middle:: freevars;
2020use middle:: pat_util;
2121use middle:: ty;
22- use middle:: typeck:: MethodCall ;
22+ use middle:: typeck:: { MethodCall , MethodObject , MethodOrigin , MethodParam } ;
23+ use middle:: typeck:: { MethodStatic } ;
2324use middle:: typeck;
24- use syntax:: ast;
25- use syntax:: codemap:: { Span } ;
2625use util:: ppaux:: Repr ;
2726
2827use std:: gc:: Gc ;
28+ use syntax:: ast;
29+ use syntax:: codemap:: Span ;
2930
3031///////////////////////////////////////////////////////////////////////////
3132// The Delegate trait
@@ -101,6 +102,74 @@ pub enum MutateMode {
101102 WriteAndRead , // x += y
102103}
103104
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+
104173///////////////////////////////////////////////////////////////////////////
105174// The ExprUseVisitor type
106175//
@@ -413,19 +482,37 @@ impl<'d,'t,TYPER:mc::Typer> ExprUseVisitor<'d,'t,TYPER> {
413482 }
414483 }
415484 _ => {
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 )
422494 }
423495 None => {
424496 self . tcx ( ) . sess . span_bug (
425497 callee. span ,
426498 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 ) ;
428514 }
515+ FnOnceOverloadedCall => self . consume_expr ( callee) ,
429516 }
430517 }
431518 }
0 commit comments