@@ -18,7 +18,7 @@ use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type};
18
18
use middle:: typeck:: infer;
19
19
use middle:: typeck:: { CrateCtxt , vtable_origin, vtable_res, vtable_param_res} ;
20
20
use middle:: typeck:: { vtable_static, vtable_param, impl_res} ;
21
- use middle:: typeck:: { param_numbered, param_self} ;
21
+ use middle:: typeck:: { param_numbered, param_self, param_index } ;
22
22
use middle:: subst:: Subst ;
23
23
use util:: common:: indenter;
24
24
use util:: ppaux;
@@ -244,51 +244,69 @@ fn lookup_vtable(vcx: &VtableContext,
244
244
}
245
245
} ;
246
246
247
- match ty:: get ( ty) . sty {
247
+ // If the type is self or a param, we look at the trait/supertrait
248
+ // bounds to see if they include the trait we are looking for.
249
+ let vtable_opt = match ty:: get ( ty) . sty {
248
250
ty:: ty_param( param_ty { idx : n, def_id : did} ) => {
249
- let mut n_bound = 0 ;
250
251
let type_param_def = tcx. ty_param_defs . get ( & did. node ) ;
251
- for ty:: each_bound_trait_and_supertraits(
252
- tcx, type_param_def. bounds. trait_bounds) |bound_trait_ref|
253
- {
254
- debug ! ( "checking bounds trait %s" , bound_trait_ref. repr( vcx. tcx( ) ) ) ;
255
-
256
- if bound_trait_ref. def_id == trait_ref. def_id {
257
- relate_trait_refs ( vcx,
258
- location_info,
259
- bound_trait_ref,
260
- trait_ref) ;
261
- let vtable = vtable_param ( param_numbered ( n) , n_bound) ;
262
- debug ! ( "found param vtable: %?" ,
263
- vtable) ;
264
- return Some ( vtable) ;
265
- }
266
-
267
- n_bound += 1 ;
268
- }
252
+ lookup_vtable_from_bounds ( vcx, location_info,
253
+ type_param_def. bounds . trait_bounds ,
254
+ param_numbered ( n) ,
255
+ trait_ref)
269
256
}
270
257
271
258
ty:: ty_self( trait_id) => {
272
- debug ! ( "trying to find %? vtable for type %?" ,
273
- trait_ref. def_id, trait_id) ;
274
-
275
- if trait_id == trait_ref. def_id {
276
- let vtable = vtable_param ( param_self, 0 ) ;
277
- debug ! ( "found self vtable: %?" , vtable) ;
278
- return Some ( vtable) ;
279
- }
259
+ let self_trait_ref = ty:: lookup_trait_def ( tcx, trait_id) . trait_ref ;
260
+ lookup_vtable_from_bounds ( vcx, location_info,
261
+ & [ self_trait_ref] ,
262
+ param_self,
263
+ trait_ref)
280
264
}
281
265
282
266
// Default case just falls through
283
- _ => { }
284
- }
267
+ _ => None
268
+ } ;
269
+
270
+ if vtable_opt. is_some ( ) { return vtable_opt; }
285
271
286
272
// If we aren't a self type or param, or it was, but we didn't find it,
287
273
// do a search.
288
274
return search_for_vtable ( vcx, location_info,
289
275
ty, trait_ref, is_early)
290
276
}
291
277
278
+ // Given a list of bounds on a type, search those bounds to see if any
279
+ // of them are the vtable we are looking for.
280
+ fn lookup_vtable_from_bounds ( vcx : & VtableContext ,
281
+ location_info : & LocationInfo ,
282
+ bounds : & [ @ty:: TraitRef ] ,
283
+ param : param_index ,
284
+ trait_ref : @ty:: TraitRef )
285
+ -> Option < vtable_origin > {
286
+ let tcx = vcx. tcx ( ) ;
287
+
288
+ let mut n_bound = 0 ;
289
+ for ty:: each_bound_trait_and_supertraits( tcx, bounds) |bound_trait_ref| {
290
+ debug ! ( "checking bounds trait %s" ,
291
+ bound_trait_ref. repr( vcx. tcx( ) ) ) ;
292
+
293
+ if bound_trait_ref. def_id == trait_ref. def_id {
294
+ relate_trait_refs ( vcx,
295
+ location_info,
296
+ bound_trait_ref,
297
+ trait_ref) ;
298
+ let vtable = vtable_param ( param, n_bound) ;
299
+ debug ! ( "found param vtable: %?" ,
300
+ vtable) ;
301
+ return Some ( vtable) ;
302
+ }
303
+
304
+ n_bound += 1 ;
305
+ }
306
+
307
+ return None ;
308
+ }
309
+
292
310
fn search_for_vtable ( vcx : & VtableContext ,
293
311
location_info : & LocationInfo ,
294
312
ty : ty:: t ,
0 commit comments