@@ -81,7 +81,6 @@ obtained the type `Foo`, we would never match this method.
8181
8282
8383use middle:: subst:: Subst ;
84- use middle:: resolve;
8584use middle:: ty:: * ;
8685use middle:: ty;
8786use middle:: typeck:: astconv:: AstConv ;
@@ -134,15 +133,14 @@ pub fn lookup(
134133 check_traits : CheckTraitsFlag , // Whether we check traits only.
135134 autoderef_receiver : AutoderefReceiverFlag )
136135 -> Option < method_origin > {
137- let impl_dups = @RefCell :: new ( HashSet :: new ( ) ) ;
138136 let lcx = LookupContext {
139137 fcx : fcx,
140138 expr : expr,
141139 self_expr : self_expr,
142140 callee_id : callee_id,
143141 m_name : m_name,
144142 supplied_tps : supplied_tps,
145- impl_dups : impl_dups ,
143+ impl_dups : @ RefCell :: new ( HashSet :: new ( ) ) ,
146144 inherent_candidates : @RefCell :: new ( ~[ ] ) ,
147145 extension_candidates : @RefCell :: new ( ~[ ] ) ,
148146 deref_args : deref_args,
@@ -164,11 +162,50 @@ pub fn lookup(
164162
165163 debug ! ( "searching extension candidates" ) ;
166164 lcx. reset_candidates ( ) ;
167- lcx. push_bound_candidates ( self_ty) ;
165+ lcx. push_bound_candidates ( self_ty, None ) ;
168166 lcx. push_extension_candidates ( ) ;
169167 return lcx. search ( self_ty) ;
170168}
171169
170+ pub fn lookup_in_trait (
171+ fcx : @FnCtxt ,
172+
173+ // In a call `a.b::<X, Y, ...>(...)`:
174+ expr : & ast:: Expr , // The expression `a.b(...)`.
175+ self_expr : & ast:: Expr , // The expression `a`.
176+ callee_id : NodeId , /* Where to store `a.b`'s type,
177+ * also the scope of the call */
178+ m_name : ast:: Name , // The name `b`.
179+ trait_did : DefId , // The trait to limit the lookup to.
180+ self_ty : ty:: t , // The type of `a`.
181+ supplied_tps : & [ ty:: t ] , // The list of types X, Y, ... .
182+ autoderef_receiver : AutoderefReceiverFlag )
183+ -> Option < method_origin > {
184+ let lcx = LookupContext {
185+ fcx : fcx,
186+ expr : expr,
187+ self_expr : self_expr,
188+ callee_id : callee_id,
189+ m_name : m_name,
190+ supplied_tps : supplied_tps,
191+ impl_dups : @RefCell :: new ( HashSet :: new ( ) ) ,
192+ inherent_candidates : @RefCell :: new ( ~[ ] ) ,
193+ extension_candidates : @RefCell :: new ( ~[ ] ) ,
194+ deref_args : check:: DoDerefArgs ,
195+ check_traits : CheckTraitsOnly ,
196+ autoderef_receiver : autoderef_receiver,
197+ } ;
198+
199+ let self_ty = structurally_resolved_type ( fcx, self_expr. span , self_ty) ;
200+ debug ! ( "method lookup_in_trait(self_ty={}, expr={}, self_expr={})" ,
201+ self_ty. repr( fcx. tcx( ) ) , expr. repr( fcx. tcx( ) ) ,
202+ self_expr. repr( fcx. tcx( ) ) ) ;
203+
204+ lcx. push_bound_candidates ( self_ty, Some ( trait_did) ) ;
205+ lcx. push_extension_candidate ( trait_did) ;
206+ lcx. search ( self_ty)
207+ }
208+
172209pub struct LookupContext < ' a > {
173210 fcx : @FnCtxt ,
174211 expr : & ' a ast:: Expr ,
@@ -319,17 +356,17 @@ impl<'a> LookupContext<'a> {
319356 }
320357 }
321358
322- fn push_bound_candidates ( & self , self_ty : ty:: t ) {
359+ fn push_bound_candidates ( & self , self_ty : ty:: t , restrict_to : Option < DefId > ) {
323360 let mut self_ty = self_ty;
324361 loop {
325362 match get ( self_ty) . sty {
326363 ty_param( p) => {
327- self . push_inherent_candidates_from_param ( self_ty, p) ;
364+ self . push_inherent_candidates_from_param ( self_ty, restrict_to , p) ;
328365 }
329366 ty_self( ..) => {
330367 // Call is of the form "self.foo()" and appears in one
331368 // of a trait's default method implementations.
332- self . push_inherent_candidates_from_self ( self_ty) ;
369+ self . push_inherent_candidates_from_self ( self_ty, restrict_to ) ;
333370 }
334371 _ => { /* No bound methods in these types */ }
335372 }
@@ -341,32 +378,27 @@ impl<'a> LookupContext<'a> {
341378 }
342379 }
343380
381+ fn push_extension_candidate ( & self , trait_did : DefId ) {
382+ ty:: populate_implementations_for_trait_if_necessary ( self . tcx ( ) , trait_did) ;
383+
384+ // Look for explicit implementations.
385+ let trait_impls = self . tcx ( ) . trait_impls . borrow ( ) ;
386+ for impl_infos in trait_impls. get ( ) . find ( & trait_did) . iter ( ) {
387+ for impl_info in impl_infos. borrow ( ) . get ( ) . iter ( ) {
388+ self . push_candidates_from_impl (
389+ self . extension_candidates . borrow_mut ( ) . get ( ) , * impl_info) ;
390+ }
391+ }
392+ }
393+
344394 fn push_extension_candidates ( & self ) {
345395 // If the method being called is associated with a trait, then
346396 // find all the impls of that trait. Each of those are
347397 // candidates.
348- let trait_map: & resolve:: TraitMap = & self . fcx . ccx . trait_map ;
349- let opt_applicable_traits = trait_map. find ( & self . expr . id ) ;
350- for applicable_traits in opt_applicable_traits. iter ( ) {
351- let applicable_traits = applicable_traits. borrow ( ) ;
352- for trait_did in applicable_traits. get ( ) . iter ( ) {
353- ty:: populate_implementations_for_trait_if_necessary (
354- self . tcx ( ) ,
355- * trait_did) ;
356-
357- // Look for explicit implementations.
358- let trait_impls = self . tcx ( ) . trait_impls . borrow ( ) ;
359- let opt_impl_infos = trait_impls. get ( ) . find ( trait_did) ;
360- for impl_infos in opt_impl_infos. iter ( ) {
361- let impl_infos = impl_infos. borrow ( ) ;
362- for impl_info in impl_infos. get ( ) . iter ( ) {
363- let mut extension_candidates =
364- self . extension_candidates . borrow_mut ( ) ;
365- self . push_candidates_from_impl (
366- extension_candidates. get ( ) , * impl_info) ;
367-
368- }
369- }
398+ let opt_applicable_traits = self . fcx . ccx . trait_map . find ( & self . expr . id ) ;
399+ for applicable_traits in opt_applicable_traits. move_iter ( ) {
400+ for trait_did in applicable_traits. iter ( ) {
401+ self . push_extension_candidate ( * trait_did) ;
370402 }
371403 }
372404 }
@@ -428,7 +460,7 @@ impl<'a> LookupContext<'a> {
428460 self . construct_transformed_self_ty_for_object (
429461 did, & rcvr_substs, & m) ;
430462
431- Candidate {
463+ Some ( Candidate {
432464 rcvr_match_condition : RcvrMatchesIfObject ( did) ,
433465 rcvr_substs : new_trait_ref. substs . clone ( ) ,
434466 method_ty : @m,
@@ -438,49 +470,61 @@ impl<'a> LookupContext<'a> {
438470 method_num : method_num,
439471 real_index : vtable_index
440472 } )
441- }
473+ } )
442474 } ) ;
443475 }
444476
445477 fn push_inherent_candidates_from_param ( & self ,
446478 rcvr_ty : ty:: t ,
479+ restrict_to : Option < DefId > ,
447480 param_ty : param_ty ) {
448481 debug ! ( "push_inherent_candidates_from_param(param_ty={:?})" ,
449482 param_ty) ;
450483 self . push_inherent_candidates_from_bounds (
451484 rcvr_ty,
452485 self . fcx . inh . param_env . type_param_bounds [ param_ty. idx ] . trait_bounds ,
486+ restrict_to,
453487 param_numbered ( param_ty. idx ) ) ;
454488 }
455489
456490
457491 fn push_inherent_candidates_from_self ( & self ,
458- rcvr_ty : ty:: t ) {
492+ rcvr_ty : ty:: t ,
493+ restrict_to : Option < DefId > ) {
459494 debug ! ( "push_inherent_candidates_from_self()" ) ;
460495 self . push_inherent_candidates_from_bounds (
461496 rcvr_ty,
462497 [ self . fcx . inh . param_env . self_param_bound . unwrap ( ) ] ,
498+ restrict_to,
463499 param_self)
464500 }
465501
466502 fn push_inherent_candidates_from_bounds ( & self ,
467503 self_ty : ty:: t ,
468504 bounds : & [ @TraitRef ] ,
505+ restrict_to : Option < DefId > ,
469506 param : param_index ) {
470507 self . push_inherent_candidates_from_bounds_inner ( bounds,
471508 |trait_ref, m, method_num, bound_num| {
472- Candidate {
473- rcvr_match_condition : RcvrMatchesIfSubtype ( self_ty) ,
474- rcvr_substs : trait_ref. substs . clone ( ) ,
475- method_ty : m,
476- origin : method_param (
477- method_param {
509+ match restrict_to {
510+ Some ( trait_did) => {
511+ if trait_did != trait_ref. def_id {
512+ return None ;
513+ }
514+ }
515+ _ => { }
516+ }
517+ Some ( Candidate {
518+ rcvr_match_condition : RcvrMatchesIfSubtype ( self_ty) ,
519+ rcvr_substs : trait_ref. substs . clone ( ) ,
520+ method_ty : m,
521+ origin : method_param ( method_param {
478522 trait_id : trait_ref. def_id ,
479523 method_num : method_num,
480524 param_num : param,
481525 bound_num : bound_num,
482526 } )
483- }
527+ } )
484528 } )
485529 }
486530
@@ -492,7 +536,7 @@ impl<'a> LookupContext<'a> {
492536 m : @ty:: Method ,
493537 method_num : uint ,
494538 bound_num : uint |
495- -> Candidate ) {
539+ -> Option < Candidate > ) {
496540 let tcx = self . tcx ( ) ;
497541 let mut next_bound_idx = 0 ; // count only trait bounds
498542
@@ -508,17 +552,17 @@ impl<'a> LookupContext<'a> {
508552 Some ( pos) => {
509553 let method = trait_methods[ pos] ;
510554
511- let cand = mk_cand ( bound_trait_ref, method,
512- pos , this_bound_idx ) ;
513-
514- debug ! ( "pushing inherent candidate for param: {:?}" , cand) ;
515- let mut inherent_candidates = self . inherent_candidates
516- . borrow_mut ( ) ;
517- inherent_candidates . get ( ) . push ( cand ) ;
555+ match mk_cand ( bound_trait_ref, method, pos , this_bound_idx ) {
556+ Some ( cand ) => {
557+ debug ! ( "pushing inherent candidate for param: {:?}" , cand ) ;
558+ self . inherent_candidates . borrow_mut ( ) . get ( ) . push ( cand) ;
559+ }
560+ None => { }
561+ }
518562 }
519563 None => {
520564 debug ! ( "trait doesn't contain method: {:?}" ,
521- bound_trait_ref. def_id) ;
565+ bound_trait_ref. def_id) ;
522566 // check next trait or bound
523567 }
524568 }
0 commit comments