@@ -134,15 +134,14 @@ pub fn lookup(
134
134
check_traits : CheckTraitsFlag , // Whether we check traits only.
135
135
autoderef_receiver : AutoderefReceiverFlag )
136
136
-> Option < method_origin > {
137
- let impl_dups = @RefCell :: new ( HashSet :: new ( ) ) ;
138
137
let lcx = LookupContext {
139
138
fcx : fcx,
140
139
expr : expr,
141
140
self_expr : self_expr,
142
141
callee_id : callee_id,
143
142
m_name : m_name,
144
143
supplied_tps : supplied_tps,
145
- impl_dups : impl_dups ,
144
+ impl_dups : @ RefCell :: new ( HashSet :: new ( ) ) ,
146
145
inherent_candidates : @RefCell :: new ( ~[ ] ) ,
147
146
extension_candidates : @RefCell :: new ( ~[ ] ) ,
148
147
deref_args : deref_args,
@@ -164,11 +163,50 @@ pub fn lookup(
164
163
165
164
debug ! ( "searching extension candidates" ) ;
166
165
lcx. reset_candidates ( ) ;
167
- lcx. push_bound_candidates ( self_ty) ;
166
+ lcx. push_bound_candidates ( self_ty, None ) ;
168
167
lcx. push_extension_candidates ( ) ;
169
168
return lcx. search ( self_ty) ;
170
169
}
171
170
171
+ pub fn lookup_in_trait (
172
+ fcx : @FnCtxt ,
173
+
174
+ // In a call `a.b::<X, Y, ...>(...)`:
175
+ expr : & ast:: Expr , // The expression `a.b(...)`.
176
+ self_expr : & ast:: Expr , // The expression `a`.
177
+ callee_id : NodeId , /* Where to store `a.b`'s type,
178
+ * also the scope of the call */
179
+ m_name : ast:: Name , // The name `b`.
180
+ trait_did : DefId , // The trait to limit the lookup to.
181
+ self_ty : ty:: t , // The type of `a`.
182
+ supplied_tps : & [ ty:: t ] , // The list of types X, Y, ... .
183
+ autoderef_receiver : AutoderefReceiverFlag )
184
+ -> Option < method_origin > {
185
+ let lcx = LookupContext {
186
+ fcx : fcx,
187
+ expr : expr,
188
+ self_expr : self_expr,
189
+ callee_id : callee_id,
190
+ m_name : m_name,
191
+ supplied_tps : supplied_tps,
192
+ impl_dups : @RefCell :: new ( HashSet :: new ( ) ) ,
193
+ inherent_candidates : @RefCell :: new ( ~[ ] ) ,
194
+ extension_candidates : @RefCell :: new ( ~[ ] ) ,
195
+ deref_args : check:: DoDerefArgs ,
196
+ check_traits : CheckTraitsOnly ,
197
+ autoderef_receiver : autoderef_receiver,
198
+ } ;
199
+
200
+ let self_ty = structurally_resolved_type ( fcx, self_expr. span , self_ty) ;
201
+ debug ! ( "method lookup_in_trait(self_ty={}, expr={}, self_expr={})" ,
202
+ self_ty. repr( fcx. tcx( ) ) , expr. repr( fcx. tcx( ) ) ,
203
+ self_expr. repr( fcx. tcx( ) ) ) ;
204
+
205
+ lcx. push_bound_candidates ( self_ty, Some ( trait_did) ) ;
206
+ lcx. push_extension_candidate ( trait_did) ;
207
+ lcx. search ( self_ty)
208
+ }
209
+
172
210
pub struct LookupContext < ' a > {
173
211
fcx : @FnCtxt ,
174
212
expr : & ' a ast:: Expr ,
@@ -319,17 +357,17 @@ impl<'a> LookupContext<'a> {
319
357
}
320
358
}
321
359
322
- fn push_bound_candidates ( & self , self_ty : ty:: t ) {
360
+ fn push_bound_candidates ( & self , self_ty : ty:: t , restrict_to : Option < DefId > ) {
323
361
let mut self_ty = self_ty;
324
362
loop {
325
363
match get ( self_ty) . sty {
326
364
ty_param( p) => {
327
- self . push_inherent_candidates_from_param ( self_ty, p) ;
365
+ self . push_inherent_candidates_from_param ( self_ty, restrict_to , p) ;
328
366
}
329
367
ty_self( ..) => {
330
368
// Call is of the form "self.foo()" and appears in one
331
369
// of a trait's default method implementations.
332
- self . push_inherent_candidates_from_self ( self_ty) ;
370
+ self . push_inherent_candidates_from_self ( self_ty, restrict_to ) ;
333
371
}
334
372
_ => { /* No bound methods in these types */ }
335
373
}
@@ -341,6 +379,19 @@ impl<'a> LookupContext<'a> {
341
379
}
342
380
}
343
381
382
+ fn push_extension_candidate ( & self , trait_did : DefId ) {
383
+ ty:: populate_implementations_for_trait_if_necessary ( self . tcx ( ) , trait_did) ;
384
+
385
+ // Look for explicit implementations.
386
+ let trait_impls = self . tcx ( ) . trait_impls . borrow ( ) ;
387
+ for impl_infos in trait_impls. get ( ) . find ( & trait_did) . iter ( ) {
388
+ for impl_info in impl_infos. borrow ( ) . get ( ) . iter ( ) {
389
+ self . push_candidates_from_impl (
390
+ self . extension_candidates . borrow_mut ( ) . get ( ) , * impl_info) ;
391
+ }
392
+ }
393
+ }
394
+
344
395
fn push_extension_candidates ( & self ) {
345
396
// If the method being called is associated with a trait, then
346
397
// find all the impls of that trait. Each of those are
@@ -428,7 +479,7 @@ impl<'a> LookupContext<'a> {
428
479
self . construct_transformed_self_ty_for_object (
429
480
did, & rcvr_substs, & m) ;
430
481
431
- Candidate {
482
+ Some ( Candidate {
432
483
rcvr_match_condition : RcvrMatchesIfObject ( did) ,
433
484
rcvr_substs : new_trait_ref. substs . clone ( ) ,
434
485
method_ty : @m,
@@ -438,49 +489,61 @@ impl<'a> LookupContext<'a> {
438
489
method_num : method_num,
439
490
real_index : vtable_index
440
491
} )
441
- }
492
+ } )
442
493
} ) ;
443
494
}
444
495
445
496
fn push_inherent_candidates_from_param ( & self ,
446
497
rcvr_ty : ty:: t ,
498
+ restrict_to : Option < DefId > ,
447
499
param_ty : param_ty ) {
448
500
debug ! ( "push_inherent_candidates_from_param(param_ty={:?})" ,
449
501
param_ty) ;
450
502
self . push_inherent_candidates_from_bounds (
451
503
rcvr_ty,
452
504
self . fcx . inh . param_env . type_param_bounds [ param_ty. idx ] . trait_bounds ,
505
+ restrict_to,
453
506
param_numbered ( param_ty. idx ) ) ;
454
507
}
455
508
456
509
457
510
fn push_inherent_candidates_from_self ( & self ,
458
- rcvr_ty : ty:: t ) {
511
+ rcvr_ty : ty:: t ,
512
+ restrict_to : Option < DefId > ) {
459
513
debug ! ( "push_inherent_candidates_from_self()" ) ;
460
514
self . push_inherent_candidates_from_bounds (
461
515
rcvr_ty,
462
516
[ self . fcx . inh . param_env . self_param_bound . unwrap ( ) ] ,
517
+ restrict_to,
463
518
param_self)
464
519
}
465
520
466
521
fn push_inherent_candidates_from_bounds ( & self ,
467
522
self_ty : ty:: t ,
468
523
bounds : & [ @TraitRef ] ,
524
+ restrict_to : Option < DefId > ,
469
525
param : param_index ) {
470
526
self . push_inherent_candidates_from_bounds_inner ( bounds,
471
527
|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 {
528
+ match restrict_to {
529
+ Some ( trait_did) => {
530
+ if trait_did != trait_ref. def_id {
531
+ return None ;
532
+ }
533
+ }
534
+ _ => { }
535
+ }
536
+ Some ( Candidate {
537
+ rcvr_match_condition : RcvrMatchesIfSubtype ( self_ty) ,
538
+ rcvr_substs : trait_ref. substs . clone ( ) ,
539
+ method_ty : m,
540
+ origin : method_param ( method_param {
478
541
trait_id : trait_ref. def_id ,
479
542
method_num : method_num,
480
543
param_num : param,
481
544
bound_num : bound_num,
482
545
} )
483
- }
546
+ } )
484
547
} )
485
548
}
486
549
@@ -492,7 +555,7 @@ impl<'a> LookupContext<'a> {
492
555
m : @ty:: Method ,
493
556
method_num : uint ,
494
557
bound_num : uint |
495
- -> Candidate ) {
558
+ -> Option < Candidate > ) {
496
559
let tcx = self . tcx ( ) ;
497
560
let mut next_bound_idx = 0 ; // count only trait bounds
498
561
@@ -508,17 +571,17 @@ impl<'a> LookupContext<'a> {
508
571
Some ( pos) => {
509
572
let method = trait_methods[ pos] ;
510
573
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 ) ;
574
+ match mk_cand ( bound_trait_ref, method, pos , this_bound_idx ) {
575
+ Some ( cand ) => {
576
+ debug ! ( "pushing inherent candidate for param: {:?}" , cand ) ;
577
+ self . inherent_candidates . borrow_mut ( ) . get ( ) . push ( cand) ;
578
+ }
579
+ None => { }
580
+ }
518
581
}
519
582
None => {
520
583
debug ! ( "trait doesn't contain method: {:?}" ,
521
- bound_trait_ref. def_id) ;
584
+ bound_trait_ref. def_id) ;
522
585
// check next trait or bound
523
586
}
524
587
}
0 commit comments