From c4265209a60ebb6227a6fff63c906e34f7210e49 Mon Sep 17 00:00:00 2001 From: Lindsey Kuper Date: Fri, 15 Jul 2011 15:33:40 -0700 Subject: [PATCH] More tests for anonymous objects. Issues #702, #703. --- .../anon-obj-overloading-wrong-type.rs | 29 +++++++++ src/test/run-pass/anon-obj-backwarding.rs | 65 +++++++++++++++++++ .../run-pass/anon-obj-overloading-reduced.rs | 24 +++++++ 3 files changed, 118 insertions(+) create mode 100644 src/test/compile-fail/anon-obj-overloading-wrong-type.rs create mode 100644 src/test/run-pass/anon-obj-backwarding.rs create mode 100644 src/test/run-pass/anon-obj-overloading-reduced.rs diff --git a/src/test/compile-fail/anon-obj-overloading-wrong-type.rs b/src/test/compile-fail/anon-obj-overloading-wrong-type.rs new file mode 100644 index 000000000000..d0e61ef99f88 --- /dev/null +++ b/src/test/compile-fail/anon-obj-overloading-wrong-type.rs @@ -0,0 +1,29 @@ +//xfail-stage0 +//xfail-stage1 +//xfail-stage2 +use std; + +fn main() { + + obj a() { + fn foo() -> int { + ret 2; + } + fn bar() -> int { + ret self.foo(); + } + } + + auto my_a = a(); + + // This compiles and shouldn't. You should only be able to + // overload a method with one of the same type. Issue #703. + auto my_b = obj() { + fn foo() -> str { + ret "hello"; + } + with my_a + }; + + log_err my_b.foo(); +} diff --git a/src/test/run-pass/anon-obj-backwarding.rs b/src/test/run-pass/anon-obj-backwarding.rs new file mode 100644 index 000000000000..e7d8a4b172f0 --- /dev/null +++ b/src/test/run-pass/anon-obj-backwarding.rs @@ -0,0 +1,65 @@ +//xfail-stage0 +//xfail-stage1 +//xfail-stage2 +use std; + +fn main() { + + obj inner() { + fn a() -> int { + ret 2; + } + fn m() -> uint { + ret 3u; + } + fn z() -> uint { + ret self.m(); + } + } + + auto my_inner = inner(); + + auto my_outer = obj() { + fn b() -> uint { + ret 5u; + } + fn n() -> str { + ret "world!"; + } + with my_inner + }; + + log_err my_inner.z(); + assert (my_inner.z() == 3u); + log_err my_outer.z(); + assert (my_outer.z() == 3u); +} + +/* + Here, when we make the self-call to self.m() in inner, we're going + back through the outer "self". That outer "self" has 5 methods in + its vtable: a, b, m, n, z. But the method z has already been + compiled, and at the time it was compiled, it expected "self" to + only have three methods in its vtable: a, m, and z. So, the method + z thinks that "self.m()" means "look up method #1 (indexing from 0) + in my vtable and call it". That means that it'll call method #1 on + the larger vtable that it thinks is "self", and method #1 at that + point is b. + + So, when we call my_inner.z(), we get 3, which is what we'd + expect. When we call my_outer.z(), we should also get 3, because + at no point is z being overridden. + + To fix this bug, we need to add a second level of forwarding + functions (let's call them "backwarding functions") on the inner + object. Every time an object is extended with another object, we + have to rewrite the inner object's vtable to account for the fact + that future self-calls will get a larger object. The inner + object's vtable will need to have five slots, too. The ones for b + and n will point right back at the outer object. (These are the + "backwarding" ones.) And the ones for a, m, and z will point at + the original, real vtable for inner. + + Adding support for this is issue #702. + +*/ diff --git a/src/test/run-pass/anon-obj-overloading-reduced.rs b/src/test/run-pass/anon-obj-overloading-reduced.rs new file mode 100644 index 000000000000..1b40c0484d24 --- /dev/null +++ b/src/test/run-pass/anon-obj-overloading-reduced.rs @@ -0,0 +1,24 @@ +//xfail-stage0 +//xfail-stage1 +//xfail-stage2 + +// Reduced test case for issue #543. +fn main() { + + obj a() { + fn foo() -> int { + ret 2; + } + } + + auto my_a = a(); + + auto my_b = obj() { + fn foo() -> int { + ret 3; + } + with my_a + }; + + assert (my_b.foo() == 3); +}