@@ -140,7 +140,24 @@ struct lookup {
140140 immutable_reference_mode, mutable_reference_mode] ;
141141
142142 loop {
143- self . add_candidates_from_type ( ) ;
143+ // Try to find a method that is keyed directly off of the
144+ // type. This only happens for boxed traits, type params,
145+ // classes, and self. If we see some sort of pointer, then
146+ // we look at candidates for the pointed to type to match
147+ // them against methods that take explicit self parameters.
148+ // N.B.: this looking through boxes to match against
149+ // explicit self parameters is *not* the same as
150+ // autoderef.
151+ // Try each of the possible matching semantics in turn.
152+ for matching_modes. each |mode| {
153+ match ty:: get ( self . self_ty ) . struct {
154+ ty:: ty_box( mt) | ty:: ty_uniq( mt) | ty:: ty_rptr( _, mt) => {
155+ self . add_candidates_from_type ( mt. ty , mode) ;
156+ }
157+ _ => { self . add_candidates_from_type ( self . self_ty , mode) ; }
158+ }
159+ if self . candidates . len ( ) > 0 u { break ; }
160+ }
144161
145162 // if we found anything, stop now. otherwise continue to
146163 // loop for impls in scope. Note: I don't love these
@@ -235,18 +252,17 @@ struct lookup {
235252 ty:: item_path_str( self . tcx( ) , did) ) ) ;
236253 }
237254
238- fn add_candidates_from_type ( ) {
239- match ty:: get ( self . self_ty ) . struct {
255+ fn add_candidates_from_type ( inner_ty : ty :: t , mode : method_lookup_mode ) {
256+ match ty:: get ( inner_ty ) . struct {
240257 // First, see whether this is a bounded parameter.
241258 ty:: ty_param( p) => {
242- self . add_candidates_from_param ( p. idx , p. def_id ) ;
259+ self . add_candidates_from_param ( inner_ty , mode , p. idx , p. def_id ) ;
243260 }
244-
245261 ty:: ty_trait( did, substs, _) => {
246- self . add_candidates_from_trait ( did, substs) ;
262+ self . add_candidates_from_trait ( inner_ty , mode , did, substs) ;
247263 }
248264 ty:: ty_class( did, substs) => {
249- self . add_candidates_from_class ( did, substs) ;
265+ self . add_candidates_from_class ( inner_ty , mode , did, substs) ;
250266 }
251267 ty:: ty_self => {
252268 // Call is of the form "self.foo()" and appears in one
@@ -260,13 +276,15 @@ struct lookup {
260276 tps : ~[ ] ,
261277 } ;
262278
263- self . add_candidates_from_trait ( self_def_id, substs) ;
279+ self . add_candidates_from_trait ( inner_ty, mode,
280+ self_def_id, substs) ;
264281 }
265282 _ => ( )
266283 }
267284 }
268285
269- fn add_candidates_from_param ( n : uint , did : ast:: def_id ) {
286+ fn add_candidates_from_param ( inner_ty : ty:: t , mode : method_lookup_mode ,
287+ n : uint , did : ast:: def_id ) {
270288 debug ! ( "add_candidates_from_param" ) ;
271289
272290 let tcx = self . tcx ( ) ;
@@ -304,6 +322,8 @@ struct lookup {
304322 with bound_substs} ;
305323
306324 self . add_candidates_from_m (
325+ inner_ty,
326+ mode,
307327 substs, trt_methods[ pos] ,
308328 method_param ( { trait_id: trait_id,
309329 method_num: pos,
@@ -315,7 +335,10 @@ struct lookup {
315335
316336 }
317337
318- fn add_candidates_from_trait ( did : ast:: def_id , trait_substs : ty:: substs ) {
338+ fn add_candidates_from_trait ( inner_ty : ty:: t ,
339+ mode : method_lookup_mode ,
340+ did : ast:: def_id ,
341+ trait_substs : ty:: substs ) {
319342
320343 debug ! ( "add_candidates_from_trait" ) ;
321344
@@ -346,11 +369,14 @@ struct lookup {
346369 with trait_substs} ;
347370
348371 self . add_candidates_from_m (
349- substs, m, method_trait ( did, i) ) ;
372+ inner_ty , mode , substs, m, method_trait ( did, i) ) ;
350373 }
351374 }
352375
353- fn add_candidates_from_class ( did : ast:: def_id , class_substs : ty:: substs ) {
376+ fn add_candidates_from_class ( inner_ty : ty:: t ,
377+ mode : method_lookup_mode ,
378+ did : ast:: def_id ,
379+ class_substs : ty:: substs ) {
354380
355381 debug ! ( "add_candidates_from_class" ) ;
356382
@@ -371,7 +397,7 @@ struct lookup {
371397 self . tcx ( ) , did, self . m_name , self . expr . span ) ;
372398
373399 self . add_candidates_from_m (
374- class_substs, m, method_static ( m_declared) ) ;
400+ inner_ty , mode , class_substs, m, method_static ( m_declared) ) ;
375401 }
376402 }
377403
@@ -488,11 +514,42 @@ struct lookup {
488514 return added_any;
489515 }
490516
491- fn add_candidates_from_m ( self_substs : ty:: substs ,
517+ fn add_candidates_from_m ( inner_ty : ty:: t ,
518+ mode : method_lookup_mode ,
519+ self_substs : ty:: substs ,
492520 m : ty:: method ,
493521 origin : method_origin ) {
494522 let tcx = self . fcx . ccx . tcx ;
495523
524+ // If we don't have a self region but have an region pointer
525+ // explicit self, we need to make up a new region.
526+ let self_r = match self_substs. self_r {
527+ none => {
528+ match m. self_ty {
529+ ast:: sty_region( _) =>
530+ some ( self . fcx . infcx . next_region_var (
531+ self . self_expr . span ,
532+ self . self_expr . id ) ) ,
533+ _ => none
534+ }
535+ }
536+ some( _) => self_substs. self_r
537+ } ;
538+ let self_substs = { self_r: self_r with self_substs} ;
539+
540+ // Before we can be sure we succeeded we need to match the
541+ // self type against the impl type that we get when we apply
542+ // the explicit self parameter to whatever inner type we are
543+ // looking at (which may be something that the self_type
544+ // points to).
545+ let impl_ty = transform_self_type_for_method (
546+ self . tcx ( ) , self_substs. self_r ,
547+ inner_ty, m. self_ty ) ;
548+
549+ let matches = self . check_type_match ( impl_ty, mode) ;
550+ debug ! ( "matches = %?" , matches) ;
551+ if matches. is_err ( ) { return ; }
552+
496553 // a bit hokey, but the method unbound has a bare protocol, whereas
497554 // a.b has a protocol like fn@() (perhaps eventually fn&()):
498555 let fty = ty:: mk_fn ( tcx, { proto: ty:: proto_vstore ( ty:: vstore_box)
@@ -507,7 +564,7 @@ struct lookup {
507564 entry : { derefs : self . derefs ,
508565 self_mode : get_mode_from_self_type ( m. self_ty ) ,
509566 origin : origin} ,
510- mode: subtyping_mode } ) ;
567+ mode: mode } ) ;
511568 }
512569
513570 fn add_inherent_and_extension_candidates ( optional_inherent_methods :
0 commit comments