@@ -45,6 +45,16 @@ use syntax::visit;
45
45
// *fully* resolved. (We could be less restrictive than that, but it
46
46
// would require much more care, and this seems to work decently in
47
47
// practice.)
48
+ //
49
+ // While resolution on a single type requires the type to be fully
50
+ // resolved, when resolving a substitution against a list of bounds,
51
+ // we do not require all of the types to be resolved in advance.
52
+ // Furthermore, we process substitutions in reverse order, which
53
+ // allows resolution on later parameters to give information on
54
+ // earlier params referenced by the typeclass bounds.
55
+ // It may be better to do something more clever, like processing fully
56
+ // resolved types first.
57
+
48
58
49
59
/// Location info records the span and ID of the expression or item that is
50
60
/// responsible for this vtable instantiation. (This may not be an expression
@@ -83,11 +93,19 @@ fn lookup_vtables(vcx: &VtableContext,
83
93
substs. repr( vcx. tcx( ) ) ) ;
84
94
let _i = indenter ( ) ;
85
95
86
- let mut result = ~[ ] ;
87
- for substs. tps. iter( ) . zip( type_param_defs. iter( ) ) . advance |( ty, def) | {
88
- result. push( lookup_vtables_for_param( vcx, location_info, Some ( substs) ,
89
- & * def. bounds, * ty, is_early) ) ;
90
- }
96
+
97
+ // We do this backwards for reasons discussed above.
98
+ assert_eq ! ( substs. tps. len( ) , type_param_defs. len( ) ) ;
99
+ let mut result =
100
+ substs. tps . rev_iter ( )
101
+ . zip ( type_param_defs. rev_iter ( ) )
102
+ . transform ( |( ty, def) |
103
+ lookup_vtables_for_param ( vcx, location_info, Some ( substs) ,
104
+ & * def. bounds , * ty, is_early) )
105
+ . to_owned_vec ( ) ;
106
+ result. reverse ( ) ;
107
+
108
+ assert_eq ! ( substs. tps. len( ) , result. len( ) ) ;
91
109
debug ! ( "lookup_vtables result(\
92
110
location_info=%?, \
93
111
type_param_defs=%s, \
@@ -198,8 +216,7 @@ fn relate_trait_refs(vcx: &VtableContext,
198
216
}
199
217
}
200
218
201
- // Look up the vtable to use when treating an item of type `t` as if it has
202
- // type `trait_ty`
219
+ // Look up the vtable implementing the trait `trait_ref` at type `t`
203
220
fn lookup_vtable ( vcx : & VtableContext ,
204
221
location_info : & LocationInfo ,
205
222
ty : ty:: t ,
@@ -261,13 +278,14 @@ fn lookup_vtable(vcx: &VtableContext,
261
278
}
262
279
}
263
280
264
- _ => {
265
- return search_for_vtable ( vcx, location_info,
266
- ty, trait_ref, is_early)
267
- }
281
+ // Default case just falls through
282
+ _ => { }
268
283
}
269
284
270
- return None ;
285
+ // If we aren't a self type or param, or it was, but we didn't find it,
286
+ // do a search.
287
+ return search_for_vtable ( vcx, location_info,
288
+ ty, trait_ref, is_early)
271
289
}
272
290
273
291
fn search_for_vtable ( vcx : & VtableContext ,
@@ -359,16 +377,23 @@ fn search_for_vtable(vcx: &VtableContext,
359
377
let of_trait_ref = of_trait_ref. subst ( tcx, & substs) ;
360
378
relate_trait_refs ( vcx, location_info, of_trait_ref, trait_ref) ;
361
379
380
+
362
381
// Recall that trait_ref -- the trait type we're casting to --
363
382
// is the trait with id trait_ref.def_id applied to the substs
364
- // trait_ref.substs. Now we extract out the types themselves
365
- // from trait_ref.substs.
383
+ // trait_ref.substs.
384
+
385
+ // Resolve any sub bounds. Note that there still may be free
386
+ // type variables in substs. This might still be OK: the
387
+ // process of looking up bounds might constrain some of them.
388
+ let im_generics =
389
+ ty:: lookup_item_type ( tcx, im. did ) . generics ;
390
+ let subres = lookup_vtables ( vcx, location_info,
391
+ * im_generics. type_param_defs , & substs,
392
+ is_early) ;
366
393
367
- // Recall that substs is the impl self type's list of
368
- // substitutions. That is, if this is an impl of some trait
369
- // for foo<T, U>, then substs is [T, U]. substs might contain
370
- // type variables, so we call fixup_substs to resolve them.
371
394
395
+ // substs might contain type variables, so we call
396
+ // fixup_substs to resolve them.
372
397
let substs_f = match fixup_substs ( vcx,
373
398
location_info,
374
399
trait_ref. def_id ,
@@ -392,13 +417,10 @@ fn search_for_vtable(vcx: &VtableContext,
392
417
// ty with the substitutions from the trait type that we're
393
418
// trying to cast to. connect_trait_tps requires these lists
394
419
// of types to unify pairwise.
395
-
396
- let im_generics =
397
- ty :: lookup_item_type ( tcx , im . did ) . generics ;
420
+ // I am a little confused about this, since it seems to be
421
+ // very similar to the relate_trait_refs we already do,
422
+ // but problems crop up if it is removed, so... -sully
398
423
connect_trait_tps ( vcx, location_info, & substs_f, trait_ref, im. did ) ;
399
- let subres = lookup_vtables ( vcx, location_info,
400
- * im_generics. type_param_defs , & substs_f,
401
- is_early) ;
402
424
403
425
// Finally, we register that we found a matching impl, and
404
426
// record the def ID of the impl as well as the resolved list
0 commit comments