@@ -45,6 +45,16 @@ use syntax::visit;
4545// *fully* resolved. (We could be less restrictive than that, but it
4646// would require much more care, and this seems to work decently in
4747// 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+
4858
4959/// Location info records the span and ID of the expression or item that is
5060/// responsible for this vtable instantiation. (This may not be an expression
@@ -83,11 +93,19 @@ fn lookup_vtables(vcx: &VtableContext,
8393 substs. repr( vcx. tcx( ) ) ) ;
8494 let _i = indenter ( ) ;
8595
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( ) ) ;
91109 debug ! ( "lookup_vtables result(\
92110 location_info=%?, \
93111 type_param_defs=%s, \
@@ -198,8 +216,7 @@ fn relate_trait_refs(vcx: &VtableContext,
198216 }
199217}
200218
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`
203220fn lookup_vtable ( vcx : & VtableContext ,
204221 location_info : & LocationInfo ,
205222 ty : ty:: t ,
@@ -261,13 +278,14 @@ fn lookup_vtable(vcx: &VtableContext,
261278 }
262279 }
263280
264- _ => {
265- return search_for_vtable ( vcx, location_info,
266- ty, trait_ref, is_early)
267- }
281+ // Default case just falls through
282+ _ => { }
268283 }
269284
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)
271289}
272290
273291fn search_for_vtable ( vcx : & VtableContext ,
@@ -359,16 +377,23 @@ fn search_for_vtable(vcx: &VtableContext,
359377 let of_trait_ref = of_trait_ref. subst ( tcx, & substs) ;
360378 relate_trait_refs ( vcx, location_info, of_trait_ref, trait_ref) ;
361379
380+
362381 // Recall that trait_ref -- the trait type we're casting to --
363382 // 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) ;
366393
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.
371394
395+ // substs might contain type variables, so we call
396+ // fixup_substs to resolve them.
372397 let substs_f = match fixup_substs ( vcx,
373398 location_info,
374399 trait_ref. def_id ,
@@ -392,13 +417,10 @@ fn search_for_vtable(vcx: &VtableContext,
392417 // ty with the substitutions from the trait type that we're
393418 // trying to cast to. connect_trait_tps requires these lists
394419 // 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
398423 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) ;
402424
403425 // Finally, we register that we found a matching impl, and
404426 // record the def ID of the impl as well as the resolved list
0 commit comments