about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLindsey Kuper <lkuper@mozilla.com>2011-07-06 18:25:51 -0700
committerLindsey Kuper <lkuper@mozilla.com>2011-07-06 18:39:01 -0700
commit130006cdda2f40872f6b44665a9b2a0d2d9ded52 (patch)
tree6592ad6893b0e1848234c29378a21dfaf850e153
parentcf4c2ac0bee9a23a5f3ec230c6ea54fb2281dbcb (diff)
Tie the knot for self-calls inside extended objects. Closes #539.
-rw-r--r--src/comp/middle/trans.rs12
-rw-r--r--src/test/run-pass/anon-obj-degenerate.rs7
2 files changed, 9 insertions, 10 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 19a112afceb..e8139432ad2 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -7829,7 +7829,7 @@ fn process_fwding_mthd(@local_ctxt cx, &span sp, @ty::method m,
                        ty::t[] additional_field_tys) -> ValueRef {
 
     // NB: self_ty (and llself_ty) is the type of the outer object;
-    // with_obj_ty (and llwith_obj_ty) is the type of the inner object.
+    // with_obj_ty is the type of the inner object.
 
     // The method m is being called on the outer object, but the outer object
     // doesn't have that method; only the inner object does.  So what we have
@@ -7870,6 +7870,11 @@ fn process_fwding_mthd(@local_ctxt cx, &span sp, @ty::method m,
     auto llself_obj_ptr = alloca(bcx, llself_ty);
     bcx.build.Store(fcx.llenv, llself_obj_ptr);
 
+    // Grab hold of the outer object so we can pass it into the inner object,
+    // in case that inner object needs to make any self-calls.  (Such calls
+    // will need to dispatch back through the outer object.)
+    auto llself_obj = bcx.build.Load(llself_obj_ptr);
+
     // The 'llretptr' that will arrive in the forwarding function we're
     // creating also needs to be the correct size.  Cast it to the size of the
     // method's return type, if necessary.
@@ -7961,11 +7966,10 @@ fn process_fwding_mthd(@local_ctxt cx, &span sp, @ty::method m,
 
     // Set up the original method to be called.
     auto orig_mthd_ty = ty::method_ty_to_fn_ty(cx.ccx.tcx, *m);
-    auto llwith_obj_ty = val_ty(llwith_obj.val);
     auto llorig_mthd_ty =
         type_of_fn_full(bcx.fcx.lcx.ccx, sp,
                         ty::ty_fn_proto(bcx.fcx.lcx.ccx.tcx, orig_mthd_ty),
-                        some[TypeRef](llwith_obj_ty),
+                        some[TypeRef](llself_ty),
                         m.inputs,
                         m.output,
                         vec::len[ast::ty_param](ty_params));
@@ -7976,7 +7980,7 @@ fn process_fwding_mthd(@local_ctxt cx, &span sp, @ty::method m,
     // Set up the three implicit arguments to the original method we'll need
     // to call.
     let vec[ValueRef] llorig_mthd_args = [llretptr, fcx.lltaskptr, 
-                                          llwith_obj.val];
+                                          llself_obj];
 
     // Copy the explicit arguments that are being passed into the forwarding
     // function (they're in fcx.llargs) to llorig_mthd_args.
diff --git a/src/test/run-pass/anon-obj-degenerate.rs b/src/test/run-pass/anon-obj-degenerate.rs
index 721253376a7..dd0caf4bb4f 100644
--- a/src/test/run-pass/anon-obj-degenerate.rs
+++ b/src/test/run-pass/anon-obj-degenerate.rs
@@ -1,6 +1,4 @@
 //xfail-stage0
-//xfail-stage1
-//xfail-stage2
 use std;
 
 fn main() {
@@ -17,13 +15,10 @@ fn main() {
     auto my_a = a();
 
     // Degenerate anonymous object: one that doesn't add any new
-    // methods or fields.  Adding support for this is issue #539.
-    // (Making this work will also ensure that calls to anonymous
-    // objects "fall through" appropriately.)
+    // methods or fields.
 
     auto my_d = obj() { with my_a };
 
-    // Right now, this fails with "unknown method 'foo' of obj".
     assert (my_d.foo() == 2);
     assert (my_d.bar() == 2);