@@ -41,6 +41,7 @@ use middle::trans::meth;
41
41
use middle:: trans:: monomorphize;
42
42
use middle:: trans:: type_of;
43
43
use middle:: ty;
44
+ use middle:: subst:: Subst ;
44
45
use middle:: typeck;
45
46
use util:: ppaux:: Repr ;
46
47
@@ -230,11 +231,75 @@ pub fn trans_fn_ref_with_vtables(
230
231
// Polytype of the function item (may have type params)
231
232
let fn_tpt = ty:: lookup_item_type ( tcx, def_id) ;
232
233
233
- // Modify the def_id if this is a default method; we want to be
234
- // monomorphizing the trait's code.
235
- let ( def_id, opt_impl_did) = match tcx. provided_method_sources . find ( & def_id) {
236
- None => ( def_id, None ) ,
237
- Some ( source) => ( source. method_id , Some ( source. impl_id ) )
234
+ let substs = ty:: substs { self_r : None , self_ty : None ,
235
+ tps : /*bad*/ type_params. to_owned ( ) } ;
236
+
237
+
238
+ // We need to do a bunch of special handling for default methods.
239
+ // We need to modify the def_id and our substs in order to monomorphize
240
+ // the function.
241
+ let ( def_id, opt_impl_did, substs) = match tcx. provided_method_sources . find ( & def_id) {
242
+ None => ( def_id, None , substs) ,
243
+ Some ( source) => {
244
+ // There are two relevant substitutions when compiling
245
+ // default methods. First, there is the substitution for
246
+ // the type parameters of the impl we are using and the
247
+ // method we are calling. This substitution is the substs
248
+ // argument we already have.
249
+ // In order to compile a default method, though, we need
250
+ // to consider another substitution: the substitution for
251
+ // the type parameters on trait; the impl we are using
252
+ // implements the trait at some particular type
253
+ // parameters, and we need to substitute for those first.
254
+ // So, what we need to do is find this substitution and
255
+ // compose it with the one we already have.
256
+
257
+ // In order to find the substitution for the trait params,
258
+ // we look up the impl in the ast map, find its trait_ref
259
+ // id, then look up its trait ref. I feel like there
260
+ // should be a better way.
261
+ let map_node = session:: expect (
262
+ ccx. sess ,
263
+ ccx. tcx . items . find_copy ( & source. impl_id . node ) ,
264
+ || fmt ! ( "couldn't find node while monomorphizing \
265
+ default method: %?", source. impl_id. node) ) ;
266
+ let item = match map_node {
267
+ ast_map:: node_item( item, _) => item,
268
+ _ => ccx. tcx . sess . bug ( "Not an item" )
269
+ } ;
270
+ let ast_trait_ref = match copy item. node {
271
+ ast:: item_impl( _, Some ( tr) , _, _) => tr,
272
+ _ => ccx. tcx . sess . bug ( "Not an impl with trait_ref" )
273
+ } ;
274
+ let trait_ref = ccx. tcx . trait_refs . get ( & ast_trait_ref. ref_id ) ;
275
+
276
+ // The substs from the trait_ref only substitues for the
277
+ // trait parameters. Our substitution also needs to be
278
+ // able to substitute for the actual method type
279
+ // params. To do this, we figure out how many method
280
+ // parameters there are and pad out the substitution with
281
+ // substitution for the variables.
282
+ let item_ty = ty:: lookup_item_type ( tcx, source. method_id ) ;
283
+ let num_params = item_ty. generics . type_param_defs . len ( ) -
284
+ trait_ref. substs . tps . len ( ) ;
285
+ let id_subst = do vec:: from_fn ( num_params) |i| {
286
+ ty:: mk_param ( tcx, i, ast:: def_id { crate : 0 , node : 0 } )
287
+ } ;
288
+ // Merge the two substitions together now.
289
+ let first_subst = ty:: substs { tps : trait_ref. substs . tps + id_subst,
290
+ .. trait_ref. substs } ;
291
+
292
+ // And compose them.
293
+ let new_substs = first_subst. subst ( tcx, & substs) ;
294
+ debug ! ( "trans_fn_with_vtables - default method: \
295
+ substs = %s, id_subst = %s, trait_subst = %s, \
296
+ first_subst = %s, new_subst = %s",
297
+ substs. repr( tcx) ,
298
+ id_subst. repr( tcx) , trait_ref. substs. repr( tcx) ,
299
+ first_subst. repr( tcx) , new_substs. repr( tcx) ) ;
300
+
301
+ ( source. method_id , Some ( source. impl_id ) , new_substs)
302
+ }
238
303
} ;
239
304
240
305
// Check whether this fn has an inlined copy and, if so, redirect
@@ -279,7 +344,7 @@ pub fn trans_fn_ref_with_vtables(
279
344
assert_eq ! ( def_id. crate , ast:: local_crate) ;
280
345
281
346
let mut ( val, must_cast) =
282
- monomorphize:: monomorphic_fn ( ccx, def_id, type_params ,
347
+ monomorphize:: monomorphic_fn ( ccx, def_id, & substs ,
283
348
vtables, opt_impl_did, Some ( ref_id) ) ;
284
349
if must_cast && ref_id != 0 {
285
350
// Monotype of the REFERENCE to the function (type params
0 commit comments