Skip to content

Commit c426520

Browse files
committed
More tests for anonymous objects. Issues #702, #703.
1 parent c610d02 commit c426520

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//xfail-stage0
2+
//xfail-stage1
3+
//xfail-stage2
4+
use std;
5+
6+
fn main() {
7+
8+
obj a() {
9+
fn foo() -> int {
10+
ret 2;
11+
}
12+
fn bar() -> int {
13+
ret self.foo();
14+
}
15+
}
16+
17+
auto my_a = a();
18+
19+
// This compiles and shouldn't. You should only be able to
20+
// overload a method with one of the same type. Issue #703.
21+
auto my_b = obj() {
22+
fn foo() -> str {
23+
ret "hello";
24+
}
25+
with my_a
26+
};
27+
28+
log_err my_b.foo();
29+
}
+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//xfail-stage0
2+
//xfail-stage1
3+
//xfail-stage2
4+
use std;
5+
6+
fn main() {
7+
8+
obj inner() {
9+
fn a() -> int {
10+
ret 2;
11+
}
12+
fn m() -> uint {
13+
ret 3u;
14+
}
15+
fn z() -> uint {
16+
ret self.m();
17+
}
18+
}
19+
20+
auto my_inner = inner();
21+
22+
auto my_outer = obj() {
23+
fn b() -> uint {
24+
ret 5u;
25+
}
26+
fn n() -> str {
27+
ret "world!";
28+
}
29+
with my_inner
30+
};
31+
32+
log_err my_inner.z();
33+
assert (my_inner.z() == 3u);
34+
log_err my_outer.z();
35+
assert (my_outer.z() == 3u);
36+
}
37+
38+
/*
39+
Here, when we make the self-call to self.m() in inner, we're going
40+
back through the outer "self". That outer "self" has 5 methods in
41+
its vtable: a, b, m, n, z. But the method z has already been
42+
compiled, and at the time it was compiled, it expected "self" to
43+
only have three methods in its vtable: a, m, and z. So, the method
44+
z thinks that "self.m()" means "look up method #1 (indexing from 0)
45+
in my vtable and call it". That means that it'll call method #1 on
46+
the larger vtable that it thinks is "self", and method #1 at that
47+
point is b.
48+
49+
So, when we call my_inner.z(), we get 3, which is what we'd
50+
expect. When we call my_outer.z(), we should also get 3, because
51+
at no point is z being overridden.
52+
53+
To fix this bug, we need to add a second level of forwarding
54+
functions (let's call them "backwarding functions") on the inner
55+
object. Every time an object is extended with another object, we
56+
have to rewrite the inner object's vtable to account for the fact
57+
that future self-calls will get a larger object. The inner
58+
object's vtable will need to have five slots, too. The ones for b
59+
and n will point right back at the outer object. (These are the
60+
"backwarding" ones.) And the ones for a, m, and z will point at
61+
the original, real vtable for inner.
62+
63+
Adding support for this is issue #702.
64+
65+
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//xfail-stage0
2+
//xfail-stage1
3+
//xfail-stage2
4+
5+
// Reduced test case for issue #543.
6+
fn main() {
7+
8+
obj a() {
9+
fn foo() -> int {
10+
ret 2;
11+
}
12+
}
13+
14+
auto my_a = a();
15+
16+
auto my_b = obj() {
17+
fn foo() -> int {
18+
ret 3;
19+
}
20+
with my_a
21+
};
22+
23+
assert (my_b.foo() == 3);
24+
}

0 commit comments

Comments
 (0)