@@ -195,6 +195,58 @@ pub fn trans_fn_ref_with_vtables_to_callee(
195
195
type_params, vtables) ) }
196
196
}
197
197
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
+
198
250
pub fn trans_fn_ref_with_vtables (
199
251
bcx : block , //
200
252
def_id : ast:: def_id , // def id of fn
@@ -246,9 +298,9 @@ pub fn trans_fn_ref_with_vtables(
246
298
// We need to do a bunch of special handling for default methods.
247
299
// We need to modify the def_id and our substs in order to monomorphize
248
300
// the function.
249
- let ( def_id, opt_impl_did, substs, self_vtable) =
301
+ let ( def_id, opt_impl_did, substs, self_vtable, vtables ) =
250
302
match tcx. provided_method_sources . find ( & def_id) {
251
- None => ( def_id, None , substs, None ) ,
303
+ None => ( def_id, None , substs, None , vtables ) ,
252
304
Some ( source) => {
253
305
// There are two relevant substitutions when compiling
254
306
// default methods. First, there is the substitution for
@@ -282,49 +334,31 @@ pub fn trans_fn_ref_with_vtables(
282
334
let self_vtable =
283
335
typeck:: vtable_static ( source. impl_id , receiver_substs,
284
336
receiver_vtables) ;
285
-
286
- // XXX: I think that if the *trait* has vtables on it,
287
- // it is all over
288
-
289
337
// Compute the first substitution
290
338
let first_subst = make_substs_for_receiver_types (
291
339
tcx, source. impl_id , trait_ref, method) ;
292
340
293
341
// And compose them
294
342
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
+
295
349
debug ! ( "trans_fn_with_vtables - default method: \
296
350
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",
298
353
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 ) ) ;
301
356
302
357
( source. method_id , Some ( source. impl_id ) ,
303
- new_substs, Some ( self_vtable) )
358
+ new_substs, Some ( self_vtable) , Some ( vtables ) )
304
359
}
305
360
} ;
306
361
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
-
328
362
// Check whether this fn has an inlined copy and, if so, redirect
329
363
// def_id to the local id of the inlined copy.
330
364
let def_id = {
0 commit comments