@@ -243,6 +243,7 @@ export iter_bound_traits_and_supertraits;
243
243
export count_traits_and_supertraits;
244
244
export IntVarValue , IntType , UintType ;
245
245
export creader_cache_key;
246
+ export get_impl_id;
246
247
247
248
// Data types
248
249
@@ -486,6 +487,9 @@ type ctxt =
486
487
487
488
// Records the value mode (read, copy, or move) for every value.
488
489
value_modes : HashMap < ast:: node_id , ValueMode > ,
490
+
491
+ // Maps a trait onto a mapping from self-ty to impl
492
+ trait_impls : HashMap < ast:: def_id , HashMap < t , @Impl > >
489
493
} ;
490
494
491
495
enum tbox_flag {
@@ -1051,7 +1055,9 @@ fn mk_ctxt(s: session::Session,
1051
1055
supertraits: HashMap ( ) ,
1052
1056
destructor_for_type: HashMap ( ) ,
1053
1057
destructors: HashMap ( ) ,
1054
- value_modes: HashMap ( ) }
1058
+ value_modes: HashMap ( ) ,
1059
+ trait_impls: HashMap ( )
1060
+ }
1055
1061
}
1056
1062
1057
1063
@@ -3130,7 +3136,8 @@ fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map,
3130
3136
trait_id : trt_id,
3131
3137
method_num : n_mth, _} ) |
3132
3138
typeck:: method_trait( trt_id, n_mth, _) |
3133
- typeck:: method_self( trt_id, n_mth) => {
3139
+ typeck:: method_self( trt_id, n_mth) |
3140
+ typeck:: method_super( trt_id, n_mth) => {
3134
3141
// ...trait methods bounds, in contrast, include only the
3135
3142
// method bounds, so we must preprend the tps from the
3136
3143
// trait itself. This ought to be harmonized.
@@ -4372,9 +4379,14 @@ pure fn determine_inherited_purity(parent_purity: ast::purity,
4372
4379
4373
4380
// Iterate over a type parameter's bounded traits and any supertraits
4374
4381
// of those traits, ignoring kinds.
4382
+ // Here, the supertraits are the transitive closure of the supertrait
4383
+ // relation on the supertraits from each bounded trait's constraint
4384
+ // list.
4375
4385
fn iter_bound_traits_and_supertraits ( tcx : ctxt ,
4376
4386
bounds : param_bounds ,
4377
4387
f : & fn ( t ) -> bool ) {
4388
+ let mut fin = false ;
4389
+
4378
4390
for bounds. each |bound| {
4379
4391
4380
4392
let bound_trait_ty = match * bound {
@@ -4386,34 +4398,45 @@ fn iter_bound_traits_and_supertraits(tcx: ctxt,
4386
4398
}
4387
4399
} ;
4388
4400
4389
- let mut worklist = ~[ ] ;
4390
-
4391
- let init_trait_ty = bound_trait_ty;
4392
-
4393
- worklist. push ( init_trait_ty) ;
4394
-
4401
+ let mut supertrait_map = HashMap ( ) ;
4402
+ let mut seen_def_ids = ~[ ] ;
4395
4403
let mut i = 0 ;
4396
- while i < worklist. len ( ) {
4397
- let init_trait_ty = worklist[ i] ;
4398
- i += 1 ;
4399
-
4400
- let init_trait_id = match ty_to_def_id ( init_trait_ty) {
4401
- Some ( id) => id,
4402
- None => tcx. sess . bug (
4403
- ~"trait type should have def_id")
4404
- } ;
4405
-
4406
- // Add supertraits to worklist
4407
- let supertraits = trait_supertraits ( tcx,
4408
- init_trait_id) ;
4409
- for supertraits. each |supertrait| {
4410
- worklist. push ( supertrait. tpt . ty ) ;
4411
- }
4412
-
4413
- if !f ( init_trait_ty) {
4414
- return ;
4404
+ let trait_ty_id = ty_to_def_id ( bound_trait_ty) . expect (
4405
+ ~"iter_trait_ty_supertraits got a non-trait type") ;
4406
+ let mut trait_ty = bound_trait_ty;
4407
+
4408
+ debug ! ( "iter_bound_traits_and_supertraits: trait_ty = %s" ,
4409
+ ty_to_str( tcx, trait_ty) ) ;
4410
+
4411
+ // Add the given trait ty to the hash map
4412
+ supertrait_map. insert ( trait_ty_id, trait_ty) ;
4413
+ seen_def_ids. push ( trait_ty_id) ;
4414
+
4415
+ if f ( trait_ty) {
4416
+ // Add all the supertraits to the hash map,
4417
+ // executing <f> on each of them
4418
+ while i < supertrait_map. size ( ) && !fin {
4419
+ let init_trait_id = seen_def_ids[ i] ;
4420
+ i += 1 ;
4421
+ // Add supertraits to supertrait_map
4422
+ let supertraits = trait_supertraits ( tcx, init_trait_id) ;
4423
+ for supertraits. each |supertrait| {
4424
+ let super_t = supertrait. tpt . ty ;
4425
+ let d_id = ty_to_def_id ( super_t) . expect ( "supertrait \
4426
+ should be a trait ty") ;
4427
+ if !supertrait_map. contains_key ( d_id) {
4428
+ supertrait_map. insert ( d_id, super_t) ;
4429
+ trait_ty = super_t;
4430
+ seen_def_ids. push ( d_id) ;
4431
+ }
4432
+ debug ! ( "A super_t = %s" , ty_to_str( tcx, trait_ty) ) ;
4433
+ if !f ( trait_ty) {
4434
+ fin = true ;
4435
+ }
4436
+ }
4415
4437
}
4416
- }
4438
+ } ;
4439
+ fin = false ;
4417
4440
}
4418
4441
}
4419
4442
@@ -4428,6 +4451,22 @@ fn count_traits_and_supertraits(tcx: ctxt,
4428
4451
return total;
4429
4452
}
4430
4453
4454
+ // Given a trait and a type, returns the impl of that type
4455
+ fn get_impl_id ( tcx : ctxt , trait_id : def_id , self_ty : t ) -> def_id {
4456
+ match tcx. trait_impls . find ( trait_id) {
4457
+ Some ( ty_to_impl) => match ty_to_impl. find ( self_ty) {
4458
+ Some ( the_impl) => the_impl. did ,
4459
+ None => // try autoderef!
4460
+ match deref ( tcx, self_ty, false ) {
4461
+ Some ( some_ty) => get_impl_id ( tcx, trait_id, some_ty. ty ) ,
4462
+ None => tcx. sess . bug ( ~"get_impl_id: no impl of trait for \
4463
+ this type")
4464
+ }
4465
+ } ,
4466
+ None => tcx. sess. bug( ~"get_impl_id: trait isn' t in trait_impls")
4467
+ }
4468
+ }
4469
+
4431
4470
impl mt : cmp:: Eq {
4432
4471
pure fn eq( & self , other: & mt) -> bool {
4433
4472
( * self ) . ty == ( * other) . ty && ( * self ) . mutbl == ( * other) . mutbl
0 commit comments