@@ -41,6 +41,7 @@ use middle::trans::meth;
4141use middle:: trans:: monomorphize;
4242use middle:: trans:: type_of;
4343use middle:: ty;
44+ use middle:: subst:: Subst ;
4445use middle:: typeck;
4546use util:: ppaux:: Repr ;
4647
@@ -230,11 +231,75 @@ pub fn trans_fn_ref_with_vtables(
230231 // Polytype of the function item (may have type params)
231232 let fn_tpt = ty:: lookup_item_type ( tcx, def_id) ;
232233
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+ }
238303 } ;
239304
240305 // Check whether this fn has an inlined copy and, if so, redirect
@@ -279,7 +344,7 @@ pub fn trans_fn_ref_with_vtables(
279344 assert_eq ! ( def_id. crate , ast:: local_crate) ;
280345
281346 let mut ( val, must_cast) =
282- monomorphize:: monomorphic_fn ( ccx, def_id, type_params ,
347+ monomorphize:: monomorphic_fn ( ccx, def_id, & substs ,
283348 vtables, opt_impl_did, Some ( ref_id) ) ;
284349 if must_cast && ref_id != 0 {
285350 // Monotype of the REFERENCE to the function (type params
0 commit comments