Skip to content

Commit 6969f0f

Browse files
committed
Issue #2572: (trans) Fix self-referential classes.
1 parent 6b16325 commit 6969f0f

File tree

3 files changed

+58
-19
lines changed

3 files changed

+58
-19
lines changed

src/rustc/middle/trans/type_of.rs

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,13 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
7676
// this then, e.g. `option<{myfield: bool}>` would be a different
7777
// type than `option<myrec>`.
7878
let t_norm = ty::normalize_ty(cx.tcx, t);
79-
let llty = if t != t_norm {
80-
type_of(cx, t_norm)
79+
80+
let mut llty;
81+
if t != t_norm {
82+
llty = type_of(cx, t_norm);
83+
cx.lltypes.insert(t, llty);
8184
} else {
82-
alt ty::get(t).struct {
85+
llty = alt ty::get(t).struct {
8386
ty::ty_nil | ty::ty_bot { T_nil() }
8487
ty::ty_bool { T_bool() }
8588
ty::ty_int(t) { T_int_ty(cx, t) }
@@ -149,30 +152,46 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
149152
}
150153
ty::ty_opaque_closure_ptr(_) { T_opaque_box_ptr(cx) }
151154
ty::ty_constr(subt,_) { type_of(cx, subt) }
155+
ty::ty_class(*) {
156+
// Only create the named struct, but don't fill it in. We fill it
157+
// in *after* placing it into the type cache. This prevents
158+
// infinite recursion with recursive class types.
159+
160+
common::T_named_struct(llvm_type_name(cx, t))
161+
}
162+
ty::ty_self { cx.tcx.sess.unimpl("type_of: ty_self"); }
163+
ty::ty_var(_) { cx.tcx.sess.bug("type_of shouldn't see a ty_var"); }
164+
ty::ty_param(*) { cx.tcx.sess.bug("type_of with ty_param"); }
165+
ty::ty_var_integral(_) {
166+
cx.tcx.sess.bug("type_of shouldn't see a ty_var_integral");
167+
}
168+
};
169+
170+
cx.lltypes.insert(t, llty);
171+
172+
// If this was a class, fill in the type now.
173+
alt ty::get(t).struct {
152174
ty::ty_class(did, ts) {
153-
// only instance vars are record fields at runtime
175+
// Only instance vars are record fields at runtime.
154176
let fields = lookup_class_fields(cx.tcx, did);
155-
let tys = vec::map(fields) {|f|
177+
let mut tys = vec::map(fields) {|f|
156178
let t = ty::lookup_field_type(cx.tcx, did, f.id, ts);
157179
type_of(cx, t)
158180
};
159-
if ty::ty_dtor(cx.tcx, did) == none {
160-
T_struct(tys)
161-
}
162-
else {
181+
182+
if ty::ty_dtor(cx.tcx, did) != none {
163183
// resource type
164-
T_struct([T_i8(), T_struct(tys)])
184+
tys = [T_i8(), T_struct(tys)];
165185
}
186+
187+
common::set_struct_body(llty, tys);
166188
}
167-
ty::ty_self { cx.tcx.sess.unimpl("type_of: ty_self"); }
168-
ty::ty_var(_) { cx.tcx.sess.bug("type_of shouldn't see a ty_var"); }
169-
ty::ty_param(*) { cx.tcx.sess.bug("type_of with ty_param"); }
170-
ty::ty_var_integral(_) {
171-
cx.tcx.sess.bug("type_of shouldn't see a ty_var_integral");
189+
_ {
190+
// Nothing more to do.
172191
}
173192
}
174193
};
175-
cx.lltypes.insert(t, llty);
194+
176195
ret llty;
177196
}
178197

@@ -214,6 +233,9 @@ fn llvm_type_name(cx: @crate_ctxt, t: ty::t) -> str {
214233
ty::ty_enum(did, substs) {
215234
("enum", did, substs.tps)
216235
}
236+
ty::ty_class(did, substs) {
237+
("class", did, substs.tps)
238+
}
217239
};
218240
ret #fmt(
219241
"%s %s[#%d]",

src/rustc/middle/ty.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3036,9 +3036,16 @@ fn normalize_ty(cx: ctxt, t: t) -> t {
30363036
alt r.self_r {
30373037
some(_) {
30383038
// This enum has a self region. Get rid of it
3039-
mk_enum(cx, did, {self_r: none,
3040-
self_ty: none,
3041-
tps: r.tps})
3039+
mk_enum(cx, did, {self_r: none, self_ty: none, tps: r.tps})
3040+
}
3041+
none { t }
3042+
}
3043+
}
3044+
ty_class(did, r) {
3045+
alt r.self_r {
3046+
some(_) {
3047+
// Ditto.
3048+
mk_class(cx, did, {self_r: none, self_ty: none, tps: r.tps})
30423049
}
30433050
none { t }
30443051
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class kitten {
2+
let cat: option<cat>;
3+
new(cat: option<cat>) {
4+
self.cat = cat;
5+
}
6+
}
7+
8+
type cat = @kitten;
9+
10+
fn main() {}

0 commit comments

Comments
 (0)