@@ -6482,23 +6482,42 @@ fn trans_fn(cx: @local_ctxt, sp: &span, f: &ast::_fn, llfndecl: ValueRef,
64826482}
64836483
64846484// process_fwding_mthd: Create the forwarding function that appears in a
6485- // vtable slot for method calls that "fall through" to an inner object. A
6485+ // vtable slot for method calls that need to forward to another object. A
64866486// helper function for create_vtbl.
6487+ //
6488+ // We use forwarding functions in two situations:
6489+ //
6490+ // (1) Forwarding: For method calls that fall through to an inner object, For
6491+ // example, suppose an inner object has method foo and we extend it with
6492+ // a method bar. The only version of 'foo' we have is on the inner
6493+ // object, but we would like to be able to call outer.foo(). So we use a
6494+ // forwarding function to make the foo method available on the outer
6495+ // object. It takes all the same arguments as the foo method on the
6496+ // inner object does, calls inner.foo() with those arguments, and then
6497+ // returns the value returned from that call. (The inner object won't
6498+ // exist until run-time, but we know its type statically.)
6499+ //
6500+ // (2) Backwarding: For method calls that dispatch back through an outer
6501+ // object. For example, suppose an inner object has methods foo and bar,
6502+ // and bar contains the call self.foo(). We extend that object with a
6503+ // foo method that overrides the inner foo. Now, a call to outer.bar()
6504+ // should send us to to inner.bar() via a normal forwarding function, and
6505+ // then to self.foo(). But inner.bar() was already compiled under the
6506+ // assumption that self.foo() is inner.foo(), when we really want to
6507+ // reach outer.foo(). So, we give 'self' a vtable of backwarding
6508+ // functions, one for each method on inner, each of which takes all the
6509+ // same arguments as the corresponding method on inner does, calls that
6510+ // method on outer, and returns the value returned from that call.
6511+
64876512fn process_fwding_mthd ( cx : @local_ctxt , sp : & span , m : @ty:: method ,
6488- ty_params : & ast:: ty_param [ ] , inner_obj_ty : ty:: t ,
6513+ ty_params : & ast:: ty_param [ ] , target_obj_ty : ty:: t ,
64896514 backwarding_vtbl : option:: t [ ValueRef ] ,
64906515 additional_field_tys : & ty:: t [ ] ) -> ValueRef {
64916516
6492-
6493- // The method m is being called on the outer object, but the outer object
6494- // doesn't have that method; only the inner object does. So what we have
6495- // to do is synthesize that method on the outer object. It has to take
6496- // all the same arguments as the method on the inner object does, then
6497- // call m with those arguments on the inner object, and then return the
6498- // value returned from that call. It's like an eta-expansion around m,
6499- // except we also have to pass the inner object that m should be called
6500- // on. That object won't exist until run-time, but we know its type
6501- // statically.
6517+ // NB: target_obj_ty is the type of the object being forwarded to.
6518+ // Depending on whether this is a forwarding or backwarding function, it
6519+ // will be either the inner obj's type or the outer obj's type,
6520+ // respectively.
65026521
65036522 // Create a local context that's aware of the name of the method we're
65046523 // creating.
@@ -6534,16 +6553,24 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
65346553
65356554 // Do backwarding if necessary.
65366555 alt ( backwarding_vtbl) {
6537- none. { /* fall through */ }
6556+ none. {
6557+ // NB: As before, this means that we are processing a backwarding fn
6558+ // right now.
6559+ }
65386560 some ( bv) {
6539- // Grab the vtable out of the self-object.
6561+ // NB: As before, this means that we are processing a forwarding fn
6562+ // right now.
6563+
6564+ // Grab the vtable out of the self-object and replace it with the
6565+ // backwarding vtable.
65406566 let llself_obj_vtbl =
65416567 bcx. build . GEP ( llself_obj_ptr, ~[ C_int ( 0 ) ,
65426568 C_int ( abi:: obj_field_vtbl) ] ) ;
6543-
6544- // And replace it with the backwarding vtbl.
65456569 let llbv = bcx. build . PointerCast ( bv, T_ptr ( T_empty_struct ( ) ) ) ;
65466570 bcx. build . Store ( llbv, llself_obj_vtbl) ;
6571+
6572+ // NB: llself_obj is now a freakish combination of outer object body
6573+ // and backwarding (inner-object) vtable.
65476574 }
65486575 }
65496576
@@ -6595,6 +6622,15 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
65956622
65966623 // Tuple type for body:
65976624 // [tydesc, [typaram, ...], [field, ...], inner_obj]
6625+
6626+ // NB: When we're creating a forwarding fn, target_obj_ty is indeed the
6627+ // type of the inner object, so it makes sense to have 'target_obj_ty'
6628+ // appear here. When we're creating a backwarding fn, though,
6629+ // target_obj_ty is the outer object's type, so instead, we need to use
6630+ // the extra inner type we passed along.
6631+
6632+ let inner_obj_ty = target_obj_ty;
6633+
65986634 let body_ty: ty:: t =
65996635 ty:: mk_imm_tup ( cx. ccx . tcx ,
66006636 ~[ tydesc_ty, typarams_ty, fields_ty, inner_obj_ty] ) ;
@@ -6621,14 +6657,14 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
66216657
66226658 // Get the index of the method we want.
66236659 let ix: uint = 0 u;
6624- alt ty:: struct ( bcx_tcx ( bcx) , inner_obj_ty ) {
6660+ alt ty:: struct ( bcx_tcx ( bcx) , target_obj_ty ) {
66256661 ty:: ty_obj ( methods) {
66266662 ix = ty:: method_idx ( cx. ccx . sess , sp, m. ident , methods) ;
66276663 }
66286664 _ {
66296665 // Shouldn't happen.
66306666 cx. ccx . sess . bug ( "process_fwding_mthd(): non-object type passed \
6631- as inner_obj_ty ") ;
6667+ as target_obj_ty ") ;
66326668 }
66336669 }
66346670
@@ -6652,7 +6688,8 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
66526688
66536689 // Set up the three implicit arguments to the original method we'll need
66546690 // to call.
6655- let llorig_mthd_args: ValueRef [ ] = ~[ llretptr, fcx. lltaskptr , llself_obj] ;
6691+ let self_arg = llself_obj;
6692+ let llorig_mthd_args: ValueRef [ ] = ~[ llretptr, fcx. lltaskptr , self_arg] ;
66566693
66576694 // Copy the explicit arguments that are being passed into the forwarding
66586695 // function (they're in fcx.llargs) to llorig_mthd_args.
0 commit comments