@@ -81,7 +81,6 @@ obtained the type `Foo`, we would never match this method.
81
81
82
82
83
83
use middle:: subst:: Subst ;
84
- use middle:: resolve;
85
84
use middle:: ty:: * ;
86
85
use middle:: ty;
87
86
use middle:: typeck:: astconv:: AstConv ;
@@ -134,15 +133,14 @@ pub fn lookup(
134
133
check_traits : CheckTraitsFlag , // Whether we check traits only.
135
134
autoderef_receiver : AutoderefReceiverFlag )
136
135
-> Option < method_origin > {
137
- let impl_dups = @RefCell :: new ( HashSet :: new ( ) ) ;
138
136
let lcx = LookupContext {
139
137
fcx : fcx,
140
138
expr : expr,
141
139
self_expr : self_expr,
142
140
callee_id : callee_id,
143
141
m_name : m_name,
144
142
supplied_tps : supplied_tps,
145
- impl_dups : impl_dups ,
143
+ impl_dups : @ RefCell :: new ( HashSet :: new ( ) ) ,
146
144
inherent_candidates : @RefCell :: new ( ~[ ] ) ,
147
145
extension_candidates : @RefCell :: new ( ~[ ] ) ,
148
146
deref_args : deref_args,
@@ -164,11 +162,50 @@ pub fn lookup(
164
162
165
163
debug ! ( "searching extension candidates" ) ;
166
164
lcx. reset_candidates ( ) ;
167
- lcx. push_bound_candidates ( self_ty) ;
165
+ lcx. push_bound_candidates ( self_ty, None ) ;
168
166
lcx. push_extension_candidates ( ) ;
169
167
return lcx. search ( self_ty) ;
170
168
}
171
169
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
+
172
209
pub struct LookupContext < ' a > {
173
210
fcx : @FnCtxt ,
174
211
expr : & ' a ast:: Expr ,
@@ -319,17 +356,17 @@ impl<'a> LookupContext<'a> {
319
356
}
320
357
}
321
358
322
- fn push_bound_candidates ( & self , self_ty : ty:: t ) {
359
+ fn push_bound_candidates ( & self , self_ty : ty:: t , restrict_to : Option < DefId > ) {
323
360
let mut self_ty = self_ty;
324
361
loop {
325
362
match get ( self_ty) . sty {
326
363
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) ;
328
365
}
329
366
ty_self( ..) => {
330
367
// Call is of the form "self.foo()" and appears in one
331
368
// 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 ) ;
333
370
}
334
371
_ => { /* No bound methods in these types */ }
335
372
}
@@ -341,32 +378,27 @@ impl<'a> LookupContext<'a> {
341
378
}
342
379
}
343
380
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
+
344
394
fn push_extension_candidates ( & self ) {
345
395
// If the method being called is associated with a trait, then
346
396
// find all the impls of that trait. Each of those are
347
397
// 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) ;
370
402
}
371
403
}
372
404
}
@@ -428,7 +460,7 @@ impl<'a> LookupContext<'a> {
428
460
self . construct_transformed_self_ty_for_object (
429
461
did, & rcvr_substs, & m) ;
430
462
431
- Candidate {
463
+ Some ( Candidate {
432
464
rcvr_match_condition : RcvrMatchesIfObject ( did) ,
433
465
rcvr_substs : new_trait_ref. substs . clone ( ) ,
434
466
method_ty : @m,
@@ -438,49 +470,61 @@ impl<'a> LookupContext<'a> {
438
470
method_num : method_num,
439
471
real_index : vtable_index
440
472
} )
441
- }
473
+ } )
442
474
} ) ;
443
475
}
444
476
445
477
fn push_inherent_candidates_from_param ( & self ,
446
478
rcvr_ty : ty:: t ,
479
+ restrict_to : Option < DefId > ,
447
480
param_ty : param_ty ) {
448
481
debug ! ( "push_inherent_candidates_from_param(param_ty={:?})" ,
449
482
param_ty) ;
450
483
self . push_inherent_candidates_from_bounds (
451
484
rcvr_ty,
452
485
self . fcx . inh . param_env . type_param_bounds [ param_ty. idx ] . trait_bounds ,
486
+ restrict_to,
453
487
param_numbered ( param_ty. idx ) ) ;
454
488
}
455
489
456
490
457
491
fn push_inherent_candidates_from_self ( & self ,
458
- rcvr_ty : ty:: t ) {
492
+ rcvr_ty : ty:: t ,
493
+ restrict_to : Option < DefId > ) {
459
494
debug ! ( "push_inherent_candidates_from_self()" ) ;
460
495
self . push_inherent_candidates_from_bounds (
461
496
rcvr_ty,
462
497
[ self . fcx . inh . param_env . self_param_bound . unwrap ( ) ] ,
498
+ restrict_to,
463
499
param_self)
464
500
}
465
501
466
502
fn push_inherent_candidates_from_bounds ( & self ,
467
503
self_ty : ty:: t ,
468
504
bounds : & [ @TraitRef ] ,
505
+ restrict_to : Option < DefId > ,
469
506
param : param_index ) {
470
507
self . push_inherent_candidates_from_bounds_inner ( bounds,
471
508
|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 {
478
522
trait_id : trait_ref. def_id ,
479
523
method_num : method_num,
480
524
param_num : param,
481
525
bound_num : bound_num,
482
526
} )
483
- }
527
+ } )
484
528
} )
485
529
}
486
530
@@ -492,7 +536,7 @@ impl<'a> LookupContext<'a> {
492
536
m : @ty:: Method ,
493
537
method_num : uint ,
494
538
bound_num : uint |
495
- -> Candidate ) {
539
+ -> Option < Candidate > ) {
496
540
let tcx = self . tcx ( ) ;
497
541
let mut next_bound_idx = 0 ; // count only trait bounds
498
542
@@ -508,17 +552,17 @@ impl<'a> LookupContext<'a> {
508
552
Some ( pos) => {
509
553
let method = trait_methods[ pos] ;
510
554
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
+ }
518
562
}
519
563
None => {
520
564
debug ! ( "trait doesn't contain method: {:?}" ,
521
- bound_trait_ref. def_id) ;
565
+ bound_trait_ref. def_id) ;
522
566
// check next trait or bound
523
567
}
524
568
}
0 commit comments