Skip to content

Commit 9c087fa

Browse files
committed
---
yaml --- r: 7166 b: refs/heads/master c: 441a42c h: refs/heads/master v: v3
1 parent b3de099 commit 9c087fa

File tree

5 files changed

+82
-12
lines changed

5 files changed

+82
-12
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 0e334c6839566dfa7d173ce6a4f83d672d223114
2+
refs/heads/master: 441a42c5d2707ae93a8be3c6be5c426e7416e50b

trunk/src/rt/rust_cc.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ class irc : public shape::data<irc,shape::ptr> {
110110
maybe_record_irc(ref_count_dp);
111111
}
112112

113+
void walk_iface() {
114+
// an iface is always a ptr to a ref-counted obj.
115+
shape::data<irc,shape::ptr>::walk_box_contents();
116+
}
117+
113118
void walk_res(const shape::rust_fn *dtor, unsigned n_params,
114119
const shape::type_param *params, const uint8_t *end_sp,
115120
bool live) {
@@ -497,6 +502,10 @@ class sweep : public shape::data<sweep,shape::ptr> {
497502
return;
498503
}
499504

505+
void walk_iface() {
506+
shape::data<sweep,shape::ptr>::walk_box_contents();
507+
}
508+
500509
void walk_res(const shape::rust_fn *dtor, unsigned n_params,
501510
const shape::type_param *params, const uint8_t *end_sp,
502511
bool live) {

trunk/src/rt/rust_internal.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,23 @@ struct rust_opaque_closure;
260260
// no arguments (and hence the final void*) is harmless
261261
typedef void (*CDECL spawn_fn)(void*, rust_opaque_closure*, void *);
262262

263+
// corresponds to the layout of an iface value
264+
//
265+
// Note: eventually, we should inline the contents of opaque_iface_contents
266+
// into opaque_iface in the LLVM code. Otherwise, the alignment of
267+
// opaque_iface_contents depends on the opaque data!
268+
269+
struct opaque_iface_contents {
270+
const type_desc *td; // describes opaque_iface_contents
271+
const void *vtable;
272+
// (opaque data goes here)
273+
};
274+
275+
struct opaque_iface {
276+
intptr_t ref_count;
277+
opaque_iface_contents contents;
278+
};
279+
263280
// corresponds to the layout of a fn(), fn@(), fn~() etc
264281
struct fn_env_pair {
265282
spawn_fn f;

trunk/src/rt/rust_shape.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,12 @@ class data : public ctxt< data<T,U> > {
868868
dp = next_dp;
869869
}
870870

871-
void walk_iface() { DATA_SIMPLE(void *, walk_iface()); }
871+
void walk_iface() {
872+
ALIGN_TO(alignof<void *>());
873+
U next_dp = dp + sizeof(void *) * 2;
874+
static_cast<T *>(this)->walk_iface();
875+
dp = next_dp;
876+
}
872877

873878
void walk_res(const rust_fn *dtor, unsigned n_params,
874879
const type_param *params, const uint8_t *end_sp) {
@@ -999,17 +1004,11 @@ data<T,U>::walk_obj_contents(ptr &dp) {
9991004
template<typename T,typename U>
10001005
void
10011006
data<T,U>::walk_iface_value(ptr &dp) {
1002-
uint8_t *box_ptr = bump_dp<uint8_t *>(dp);
1007+
opaque_iface *box_ptr = bump_dp<opaque_iface *>(dp);
10031008
if (!box_ptr) return;
1004-
uint8_t *body_ptr = box_ptr + sizeof(void*);
1005-
type_desc *valtydesc =
1006-
*reinterpret_cast<type_desc **>(body_ptr);
1007-
ptr value_dp(body_ptr + sizeof(void*) * 2);
1008-
// FIXME The 5 is a hard-coded way to skip over a struct shape
1009-
// header and the first two (number-typed) fields. This is too
1010-
// fragile, but I didn't see a good way to properly encode it.
1011-
T sub(*static_cast<T *>(this), valtydesc->shape + 5, NULL, NULL,
1012-
value_dp);
1009+
const type_desc *contents_td = box_ptr->contents.td;
1010+
ptr contents_dp((uintptr_t)&box_ptr->contents);
1011+
T sub(*static_cast<T *>(this), contents_td->shape, NULL, NULL, contents_dp);
10131012
sub.align = true;
10141013
sub.walk();
10151014
}

trunk/src/test/run-pass/iface-cast.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Test cyclic detector when using iface instances.
2+
3+
tag Tree = TreeR;
4+
type TreeR = @{
5+
mutable left: option<Tree>,
6+
mutable right: option<Tree>,
7+
val: to_str
8+
};
9+
10+
iface to_str {
11+
fn to_str() -> str;
12+
}
13+
14+
impl <T: to_str> of to_str for option<T> {
15+
fn to_str() -> str {
16+
alt self {
17+
none. { "none" }
18+
some(t) { "some(" + t.to_str() + ")" }
19+
}
20+
}
21+
}
22+
23+
impl of to_str for int {
24+
fn to_str() -> str { int::str(self) }
25+
}
26+
27+
impl of to_str for Tree {
28+
fn to_str() -> str {
29+
#fmt["[%s, %s, %s]",
30+
self.val.to_str(),
31+
self.left.to_str(),
32+
self.right.to_str()]
33+
}
34+
}
35+
36+
fn main() {
37+
let t1 = Tree(@{mutable left: none,
38+
mutable right: none,
39+
val: 1 as to_str });
40+
let t2 = Tree(@{mutable left: some(t1),
41+
mutable right: some(t1),
42+
val: 2 as to_str });
43+
assert t2.to_str() == "[2, some([1, none, none]), some([1, none, none])]";
44+
t1.left = some(t2); // create cycle
45+
}

0 commit comments

Comments
 (0)