17
17
// closure.
18
18
19
19
use core:: prelude:: * ;
20
+ use core:: vec;
20
21
21
22
use back:: abi;
22
23
use driver:: session;
@@ -194,6 +195,58 @@ pub fn trans_fn_ref_with_vtables_to_callee(
194
195
type_params, vtables) ) }
195
196
}
196
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
+
197
250
pub fn trans_fn_ref_with_vtables (
198
251
bcx : block , //
199
252
def_id : ast:: def_id , // def id of fn
@@ -233,15 +286,21 @@ pub fn trans_fn_ref_with_vtables(
233
286
// Polytype of the function item (may have type params)
234
287
let fn_tpt = ty:: lookup_item_type ( tcx, def_id) ;
235
288
236
- let substs = ty:: substs { self_r : None , self_ty : None ,
289
+ // For simplicity, we want to use the Subst trait when composing
290
+ // substitutions for default methods. The subst trait does
291
+ // substitutions with regions, though, so we put a dummy self
292
+ // region parameter in to keep it from failing. This is a hack.
293
+ let substs = ty:: substs { self_r : Some ( ty:: re_empty) ,
294
+ self_ty : None ,
237
295
tps : /*bad*/ type_params. to_owned ( ) } ;
238
296
239
297
240
298
// We need to do a bunch of special handling for default methods.
241
299
// We need to modify the def_id and our substs in order to monomorphize
242
300
// the function.
243
- let ( def_id, opt_impl_did, substs) = match tcx. provided_method_sources . find ( & def_id) {
244
- None => ( def_id, None , substs) ,
301
+ let ( def_id, opt_impl_did, substs, self_vtable, vtables) =
302
+ match tcx. provided_method_sources . find ( & def_id) {
303
+ None => ( def_id, None , substs, None , vtables) ,
245
304
Some ( source) => {
246
305
// There are two relevant substitutions when compiling
247
306
// default methods. First, there is the substitution for
@@ -261,20 +320,42 @@ pub fn trans_fn_ref_with_vtables(
261
320
default methods") ;
262
321
let method = ty:: method ( tcx, source. method_id ) ;
263
322
323
+ // Get all of the type params for the receiver
324
+ let param_defs = method. generics . type_param_defs ;
325
+ let receiver_substs =
326
+ type_params. initn ( param_defs. len ( ) ) . to_owned ( ) ;
327
+ let receiver_vtables = match vtables {
328
+ None => @~[ ] ,
329
+ Some ( call_vtables) => {
330
+ @call_vtables. initn ( param_defs. len ( ) ) . to_owned ( )
331
+ }
332
+ } ;
333
+
334
+ let self_vtable =
335
+ typeck:: vtable_static ( source. impl_id , receiver_substs,
336
+ receiver_vtables) ;
264
337
// Compute the first substitution
265
338
let first_subst = make_substs_for_receiver_types (
266
339
tcx, source. impl_id , trait_ref, method) ;
267
340
268
341
// And compose them
269
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
+
270
349
debug ! ( "trans_fn_with_vtables - default method: \
271
350
substs = %s, trait_subst = %s, \
272
- first_subst = %s, new_subst = %s",
351
+ first_subst = %s, new_subst = %s, \
352
+ self_vtable = %s, vtables = %s",
273
353
substs. repr( tcx) , trait_ref. substs. repr( tcx) ,
274
- first_subst. repr( tcx) , new_substs. repr( tcx) ) ;
275
-
354
+ first_subst. repr( tcx) , new_substs. repr( tcx) ,
355
+ self_vtable . repr ( tcx ) , vtables . repr ( tcx ) ) ;
276
356
277
- ( source. method_id , Some ( source. impl_id ) , new_substs)
357
+ ( source. method_id , Some ( source. impl_id ) ,
358
+ new_substs, Some ( self_vtable) , Some ( vtables) )
278
359
}
279
360
} ;
280
361
@@ -321,7 +402,8 @@ pub fn trans_fn_ref_with_vtables(
321
402
322
403
let ( val, must_cast) =
323
404
monomorphize:: monomorphic_fn ( ccx, def_id, & substs,
324
- vtables, opt_impl_did, Some ( ref_id) ) ;
405
+ vtables, self_vtable,
406
+ opt_impl_did, Some ( ref_id) ) ;
325
407
let mut val = val;
326
408
if must_cast && ref_id != 0 {
327
409
// Monotype of the REFERENCE to the function (type params
0 commit comments