@@ -195,6 +195,58 @@ pub fn trans_fn_ref_with_vtables_to_callee(
195195 type_params, vtables) ) }
196196}
197197
198+ fn get_impl_resolutions ( bcx : block ,
199+ impl_id : ast:: def_id )
200+ -> typeck:: vtable_res {
201+ if impl_id. crate == ast:: local_crate {
202+ * bcx. ccx ( ) . maps . vtable_map . get ( & impl_id. node )
203+ } else {
204+ // XXX: This is a temporary hack to work around not properly
205+ // exporting information about resolutions for impls.
206+ // This doesn't actually work if the trait has param bounds,
207+ // but it does allow us to survive the case when it does not.
208+ let trait_ref = ty:: impl_trait_ref ( bcx. tcx ( ) , impl_id) . get ( ) ;
209+ @vec:: from_elem ( trait_ref. substs . tps . len ( ) , @~[ ] )
210+ }
211+ }
212+
213+ fn resolve_default_method_vtables ( bcx : block ,
214+ impl_id : ast:: def_id ,
215+ method : & ty:: Method ,
216+ substs : & ty:: substs ,
217+ impl_vtables : Option < typeck:: vtable_res > )
218+ -> typeck:: vtable_res {
219+
220+ // Get the vtables that the impl implements the trait at
221+ let trait_vtables = get_impl_resolutions ( bcx, impl_id) ;
222+
223+ // Build up a param_substs that we are going to resolve the
224+ // trait_vtables under.
225+ let param_substs = Some ( @param_substs {
226+ tys : copy substs. tps ,
227+ self_ty : substs. self_ty ,
228+ vtables : impl_vtables,
229+ self_vtable : None
230+ } ) ;
231+
232+ let trait_vtables_fixed = resolve_vtables_under_param_substs (
233+ bcx. tcx ( ) , param_substs, trait_vtables) ;
234+
235+ // Now we pull any vtables for parameters on the actual method.
236+ let num_method_vtables = method. generics . type_param_defs . len ( ) ;
237+ let method_vtables = match impl_vtables {
238+ Some ( vtables) => {
239+ let num_impl_type_parameters =
240+ vtables. len ( ) - num_method_vtables;
241+ vtables. tailn ( num_impl_type_parameters) . to_owned ( )
242+ } ,
243+ None => vec:: from_elem ( num_method_vtables, @~[ ] )
244+ } ;
245+
246+ @( * trait_vtables_fixed + method_vtables)
247+ }
248+
249+
198250pub fn trans_fn_ref_with_vtables (
199251 bcx : block , //
200252 def_id : ast:: def_id , // def id of fn
@@ -246,9 +298,9 @@ pub fn trans_fn_ref_with_vtables(
246298 // We need to do a bunch of special handling for default methods.
247299 // We need to modify the def_id and our substs in order to monomorphize
248300 // the function.
249- let ( def_id, opt_impl_did, substs, self_vtable) =
301+ let ( def_id, opt_impl_did, substs, self_vtable, vtables ) =
250302 match tcx. provided_method_sources . find ( & def_id) {
251- None => ( def_id, None , substs, None ) ,
303+ None => ( def_id, None , substs, None , vtables ) ,
252304 Some ( source) => {
253305 // There are two relevant substitutions when compiling
254306 // default methods. First, there is the substitution for
@@ -282,49 +334,31 @@ pub fn trans_fn_ref_with_vtables(
282334 let self_vtable =
283335 typeck:: vtable_static ( source. impl_id , receiver_substs,
284336 receiver_vtables) ;
285-
286- // XXX: I think that if the *trait* has vtables on it,
287- // it is all over
288-
289337 // Compute the first substitution
290338 let first_subst = make_substs_for_receiver_types (
291339 tcx, source. impl_id , trait_ref, method) ;
292340
293341 // And compose them
294342 let new_substs = first_subst. subst ( tcx, & substs) ;
343+
344+
345+ let vtables =
346+ resolve_default_method_vtables ( bcx, source. impl_id ,
347+ method, & new_substs, vtables) ;
348+
295349 debug ! ( "trans_fn_with_vtables - default method: \
296350 substs = %s, trait_subst = %s, \
297- first_subst = %s, new_subst = %s",
351+ first_subst = %s, new_subst = %s, \
352+ self_vtable = %s, vtables = %s",
298353 substs. repr( tcx) , trait_ref. substs. repr( tcx) ,
299- first_subst. repr( tcx) , new_substs. repr( tcx) ) ;
300-
354+ first_subst. repr( tcx) , new_substs. repr( tcx) ,
355+ self_vtable . repr ( tcx ) , vtables . repr ( tcx ) ) ;
301356
302357 ( source. method_id , Some ( source. impl_id ) ,
303- new_substs, Some ( self_vtable) )
358+ new_substs, Some ( self_vtable) , Some ( vtables ) )
304359 }
305360 } ;
306361
307- // XXX: this is *completely* bad and wrong. I feel bad. Handling
308- // of vtables is currently bogus for default methods, and changing
309- // to an unflattented representation of vtables causes this to
310- // show up in cases that it did not previously. We need to make
311- // the vtables list be the same length as the substs. There is
312- // nothing right about this. I really need to emphasize just how
313- // wrong it is: it is completely wrong.
314- // XXX: bad.
315- // This will be fixed in the next commit.
316- let vtables = do vtables. map |vtbls| {
317- if vtbls. len ( ) < substs. tps . len ( ) {
318- @( vec:: from_elem ( substs. tps . len ( ) - vtbls. len ( ) , @~[ ] ) +
319- * * vtbls)
320- } else if vtbls. len ( ) > substs. tps . len ( ) {
321- @vtbls. tailn ( vtbls. len ( ) - substs. tps . len ( ) ) . to_owned ( )
322- } else {
323- * vtbls
324- }
325- } ;
326-
327-
328362 // Check whether this fn has an inlined copy and, if so, redirect
329363 // def_id to the local id of the inlined copy.
330364 let def_id = {
0 commit comments