@@ -134,8 +134,8 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id,
134
134
typeck:: method_param( { trait_id: trait_id, method_num: off,
135
135
param_num: p, bound_num: b} ) => {
136
136
match bcx. fcx . param_substs {
137
- Some ( substs) => {
138
- let vtbl = find_vtable_in_fn_ctxt ( substs, p, b) ;
137
+ Some ( ref substs) => {
138
+ let vtbl = base :: find_vtable ( bcx . tcx ( ) , substs, p, b) ;
139
139
trans_monomorphized_callee ( bcx, callee_id, self , mentry,
140
140
trait_id, off, vtbl)
141
141
}
@@ -177,19 +177,17 @@ fn trans_static_method_callee(bcx: block,
177
177
bcx. fcx , ccx. maps . vtable_map . get ( callee_id) ) ;
178
178
179
179
match vtbls[ 0 ] { // is index 0 always the one we want?
180
- typeck:: vtable_static( impl_did, impl_substs , sub_origins ) => {
180
+ typeck:: vtable_static( impl_did, rcvr_substs , rcvr_origins ) => {
181
181
182
182
let mth_id = method_with_name ( bcx. ccx ( ) , impl_did, mname) ;
183
- let n_m_tps = method_ty_param_count ( ccx, mth_id, impl_did) ;
184
- let node_substs = node_id_type_params ( bcx, callee_id) ;
185
- let ty_substs
186
- = vec:: append ( impl_substs,
187
- vec:: tailn ( node_substs,
188
- node_substs. len ( ) - n_m_tps) ) ;
183
+ let callee_substs = combine_impl_and_methods_tps (
184
+ bcx, mth_id, impl_did, callee_id, rcvr_substs) ;
185
+ let callee_origins = combine_impl_and_methods_origins (
186
+ bcx, mth_id, impl_did, callee_id, rcvr_origins) ;
189
187
190
188
let FnData { llfn : lval} =
191
189
trans_fn_ref_with_vtables ( bcx, mth_id, callee_id,
192
- ty_substs , Some ( sub_origins ) ) ;
190
+ callee_substs , Some ( callee_origins ) ) ;
193
191
194
192
let callee_ty = node_id_type ( bcx, callee_id) ;
195
193
let llty = T_ptr ( type_of_fn_from_ty ( ccx, callee_ty) ) ;
@@ -248,8 +246,8 @@ fn trans_monomorphized_callee(bcx: block,
248
246
-> Callee
249
247
{
250
248
let _icx = bcx. insn_ctxt ( "impl::trans_monomorphized_callee" ) ;
251
- match vtbl {
252
- typeck:: vtable_static( impl_did, impl_substs , sub_origins ) => {
249
+ return match vtbl {
250
+ typeck:: vtable_static( impl_did, rcvr_substs , rcvr_origins ) => {
253
251
let ccx = bcx. ccx ( ) ;
254
252
let mname = ty:: trait_methods ( ccx. tcx , trait_id) [ n_method] . ident ;
255
253
let mth_id = method_with_name ( bcx. ccx ( ) , impl_did, mname) ;
@@ -260,20 +258,14 @@ fn trans_monomorphized_callee(bcx: block,
260
258
261
259
// create a concatenated set of substitutions which includes
262
260
// those from the impl and those from the method:
263
- let n_m_tps = method_ty_param_count ( ccx, mth_id, impl_did) ;
264
- let node_substs = node_id_type_params ( bcx, callee_id) ;
265
- let ty_substs
266
- = vec:: append ( impl_substs,
267
- vec:: tailn ( node_substs,
268
- node_substs. len ( ) - n_m_tps) ) ;
269
- debug ! ( "n_m_tps=%?" , n_m_tps) ;
270
- debug ! ( "impl_substs=%?" , impl_substs. map( |t| bcx. ty_to_str( t) ) ) ;
271
- debug ! ( "node_substs=%?" , node_substs. map( |t| bcx. ty_to_str( t) ) ) ;
272
- debug ! ( "ty_substs=%?" , ty_substs. map( |t| bcx. ty_to_str( t) ) ) ;
261
+ let callee_substs = combine_impl_and_methods_tps (
262
+ bcx, mth_id, impl_did, callee_id, rcvr_substs) ;
263
+ let callee_origins = combine_impl_and_methods_origins (
264
+ bcx, mth_id, impl_did, callee_id, rcvr_origins) ;
273
265
274
266
// translate the function
275
267
let callee = trans_fn_ref_with_vtables (
276
- bcx, mth_id, callee_id, ty_substs , Some ( sub_origins ) ) ;
268
+ bcx, mth_id, callee_id, callee_substs , Some ( callee_origins ) ) ;
277
269
278
270
// create a llvalue that represents the fn ptr
279
271
let fn_ty = node_id_type ( bcx, callee_id) ;
@@ -297,9 +289,99 @@ fn trans_monomorphized_callee(bcx: block,
297
289
typeck:: vtable_param( * ) => {
298
290
fail ~"vtable_param left in monomorphized function' s vtable substs";
299
291
}
300
- }
292
+ } ;
293
+
294
+ }
295
+
296
+ fn combine_impl_and_methods_tps ( bcx : block ,
297
+ mth_did : ast:: def_id ,
298
+ impl_did : ast:: def_id ,
299
+ callee_id : ast:: node_id ,
300
+ rcvr_substs : ~[ ty:: t ] )
301
+ -> ~[ ty:: t ]
302
+ {
303
+ /*!
304
+ *
305
+ * Creates a concatenated set of substitutions which includes
306
+ * those from the impl and those from the method. This are
307
+ * some subtle complications here. Statically, we have a list
308
+ * of type parameters like `[T0, T1, T2, M1, M2, M3]` where
309
+ * `Tn` are type parameters that appear on the receiver. For
310
+ * example, if the receiver is a method parameter `A` with a
311
+ * bound like `trait<B,C,D>` then `Tn` would be `[B,C,D]`.
312
+ *
313
+ * The weird part is that the type `A` might now be bound to
314
+ * any other type, such as `foo<X>`. In that case, the vector
315
+ * we want is: `[X, M1, M2, M3]`. Therefore, what we do now is
316
+ * to slice off the method type parameters and append them to
317
+ * the type parameters from the type that the receiver is
318
+ * mapped to. */
319
+
320
+ let ccx = bcx. ccx ( ) ;
321
+ let n_m_tps = method_ty_param_count ( ccx, mth_did, impl_did) ;
322
+ let node_substs = node_id_type_params ( bcx, callee_id) ;
323
+ let ty_substs
324
+ = vec:: append ( rcvr_substs,
325
+ vec:: tailn ( node_substs,
326
+ node_substs. len ( ) - n_m_tps) ) ;
327
+ debug ! ( "n_m_tps=%?" , n_m_tps) ;
328
+ debug ! ( "rcvr_substs=%?" , rcvr_substs. map( |t| bcx. ty_to_str( t) ) ) ;
329
+ debug ! ( "node_substs=%?" , node_substs. map( |t| bcx. ty_to_str( t) ) ) ;
330
+ debug ! ( "ty_substs=%?" , ty_substs. map( |t| bcx. ty_to_str( t) ) ) ;
331
+
332
+ return ty_substs;
333
+ }
334
+
335
+ fn combine_impl_and_methods_origins ( bcx : block ,
336
+ mth_did : ast:: def_id ,
337
+ impl_did : ast:: def_id ,
338
+ callee_id : ast:: node_id ,
339
+ rcvr_origins : typeck:: vtable_res )
340
+ -> typeck:: vtable_res
341
+ {
342
+ /*!
343
+ *
344
+ * Similar to `combine_impl_and_methods_tps`, but for vtables.
345
+ * This is much messier because of the flattened layout we are
346
+ * currently using (for some reason that I fail to understand).
347
+ * The proper fix is described in #3446.
348
+ */
349
+
350
+
351
+ // Find the bounds for the method, which are the tail of the
352
+ // bounds found in the item type, as the item type combines the
353
+ // rcvr + method bounds.
354
+ let ccx = bcx. ccx ( ) , tcx = bcx. tcx ( ) ;
355
+ let n_m_tps = method_ty_param_count ( ccx, mth_did, impl_did) ;
356
+ let { bounds: r_m_bounds , _} = ty:: lookup_item_type ( tcx, mth_did) ;
357
+ let n_r_m_tps = r_m_bounds. len ( ) ; // rcvr + method tps
358
+ let m_boundss = vec:: view ( * r_m_bounds, n_r_m_tps - n_m_tps, n_r_m_tps) ;
359
+
360
+ // Flatten out to find the number of vtables the method expects.
361
+ let m_vtables = m_boundss. foldl ( 0 , |sum, m_bounds| {
362
+ m_bounds. foldl ( sum, |sum, m_bound| {
363
+ sum + match m_bound {
364
+ ty:: bound_copy | ty:: bound_owned |
365
+ ty:: bound_send | ty:: bound_const => 0 ,
366
+ ty:: bound_trait( _) => 1
367
+ }
368
+ } )
369
+ } ) ;
370
+
371
+ // Find the vtables we computed at type check time and monomorphize them
372
+ let r_m_origins = match node_vtables ( bcx, callee_id) {
373
+ Some ( vt) => vt,
374
+ None => @~[ ]
375
+ } ;
376
+
377
+ // Extract those that belong to method:
378
+ let m_origins = vec:: tailn ( * r_m_origins, r_m_origins. len ( ) - m_vtables) ;
379
+
380
+ // Combine rcvr + method to find the final result:
381
+ @vec:: append ( * rcvr_origins, m_origins)
301
382
}
302
383
384
+
303
385
fn trans_trait_callee ( bcx : block ,
304
386
callee_id : ast:: node_id ,
305
387
n_method : uint ,
@@ -367,54 +449,6 @@ fn trans_trait_callee_from_llval(bcx: block,
367
449
} ;
368
450
}
369
451
370
- fn find_vtable_in_fn_ctxt ( ps : param_substs , n_param : uint , n_bound : uint )
371
- -> typeck:: vtable_origin
372
- {
373
- let mut vtable_off = n_bound, i = 0 u;
374
- // Vtables are stored in a flat array, finding the right one is
375
- // somewhat awkward
376
- for vec:: each( * ps. bounds ) |bounds| {
377
- if i >= n_param { break ; }
378
- for vec:: each( * bounds) |bound| {
379
- match bound { ty:: bound_trait( _) => vtable_off += 1 u, _ => ( ) }
380
- }
381
- i += 1 u;
382
- }
383
- option:: get ( ps. vtables ) [ vtable_off]
384
- }
385
-
386
- fn resolve_vtables_in_fn_ctxt( fcx: fn_ctxt, vts: typeck:: vtable_res)
387
- -> typeck:: vtable_res {
388
- @vec : : map ( * vts, |d| resolve_vtable_in_fn_ctxt ( fcx, d) )
389
- }
390
-
391
- // Apply the typaram substitutions in the fn_ctxt to a vtable. This should
392
- // eliminate any vtable_params.
393
- fn resolve_vtable_in_fn_ctxt( fcx: fn_ctxt, vt: typeck:: vtable_origin)
394
- -> typeck:: vtable_origin {
395
- match vt {
396
- typeck : : vtable_static ( trait_id, tys, sub) => {
397
- let tys = match fcx. param_substs {
398
- Some ( substs) => {
399
- vec:: map ( tys, |t| ty:: subst_tps ( fcx. ccx . tcx , substs. tys , t) )
400
- }
401
- _ => tys
402
- } ;
403
- typeck:: vtable_static ( trait_id, tys,
404
- resolve_vtables_in_fn_ctxt ( fcx, sub) )
405
- }
406
- typeck:: vtable_param( n_param, n_bound) => {
407
- match fcx. param_substs {
408
- Some ( substs) => {
409
- find_vtable_in_fn_ctxt ( substs, n_param, n_bound)
410
- }
411
- _ => fail ~"resolve_vtable_in_fn_ctxt: no substs"
412
- }
413
- }
414
- _ => vt
415
- }
416
- }
417
-
418
452
fn vtable_id ( ccx : @crate_ctxt , origin : typeck:: vtable_origin ) -> mono_id {
419
453
match origin {
420
454
typeck:: vtable_static( impl_id, substs, sub_vtables) => {
0 commit comments