diff options
| -rw-r--r-- | src/rustc/middle/trans/type_of.rs | 54 | ||||
| -rw-r--r-- | src/rustc/middle/ty.rs | 13 | ||||
| -rw-r--r-- | src/test/run-pass/classes-self-referential.rs | 10 |
3 files changed, 58 insertions, 19 deletions
diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs index e66ba7bc6c2..0d6ef8c6d12 100644 --- a/src/rustc/middle/trans/type_of.rs +++ b/src/rustc/middle/trans/type_of.rs @@ -76,10 +76,13 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef { // this then, e.g. `option<{myfield: bool}>` would be a different // type than `option<myrec>`. let t_norm = ty::normalize_ty(cx.tcx, t); - let llty = if t != t_norm { - type_of(cx, t_norm) + + let mut llty; + if t != t_norm { + llty = type_of(cx, t_norm); + cx.lltypes.insert(t, llty); } else { - alt ty::get(t).struct { + llty = alt ty::get(t).struct { ty::ty_nil | ty::ty_bot { T_nil() } ty::ty_bool { T_bool() } ty::ty_int(t) { T_int_ty(cx, t) } @@ -149,30 +152,46 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef { } ty::ty_opaque_closure_ptr(_) { T_opaque_box_ptr(cx) } ty::ty_constr(subt,_) { type_of(cx, subt) } + ty::ty_class(*) { + // Only create the named struct, but don't fill it in. We fill it + // in *after* placing it into the type cache. This prevents + // infinite recursion with recursive class types. + + common::T_named_struct(llvm_type_name(cx, t)) + } + ty::ty_self { cx.tcx.sess.unimpl("type_of: ty_self"); } + ty::ty_var(_) { cx.tcx.sess.bug("type_of shouldn't see a ty_var"); } + ty::ty_param(*) { cx.tcx.sess.bug("type_of with ty_param"); } + ty::ty_var_integral(_) { + cx.tcx.sess.bug("type_of shouldn't see a ty_var_integral"); + } + }; + + cx.lltypes.insert(t, llty); + + // If this was a class, fill in the type now. + alt ty::get(t).struct { ty::ty_class(did, ts) { - // only instance vars are record fields at runtime + // Only instance vars are record fields at runtime. let fields = lookup_class_fields(cx.tcx, did); - let tys = vec::map(fields) {|f| + let mut tys = vec::map(fields) {|f| let t = ty::lookup_field_type(cx.tcx, did, f.id, ts); type_of(cx, t) }; - if ty::ty_dtor(cx.tcx, did) == none { - T_struct(tys) - } - else { + + if ty::ty_dtor(cx.tcx, did) != none { // resource type - T_struct([T_i8(), T_struct(tys)]) + tys = [T_i8(), T_struct(tys)]; } + + common::set_struct_body(llty, tys); } - ty::ty_self { cx.tcx.sess.unimpl("type_of: ty_self"); } - ty::ty_var(_) { cx.tcx.sess.bug("type_of shouldn't see a ty_var"); } - ty::ty_param(*) { cx.tcx.sess.bug("type_of with ty_param"); } - ty::ty_var_integral(_) { - cx.tcx.sess.bug("type_of shouldn't see a ty_var_integral"); + _ { + // Nothing more to do. } } }; - cx.lltypes.insert(t, llty); + ret llty; } @@ -214,6 +233,9 @@ fn llvm_type_name(cx: @crate_ctxt, t: ty::t) -> str { ty::ty_enum(did, substs) { ("enum", did, substs.tps) } + ty::ty_class(did, substs) { + ("class", did, substs.tps) + } }; ret #fmt( "%s %s[#%d]", diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 0d4cc92b1ef..421bbf38e14 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -3036,9 +3036,16 @@ fn normalize_ty(cx: ctxt, t: t) -> t { alt r.self_r { some(_) { // This enum has a self region. Get rid of it - mk_enum(cx, did, {self_r: none, - self_ty: none, - tps: r.tps}) + mk_enum(cx, did, {self_r: none, self_ty: none, tps: r.tps}) + } + none { t } + } + } + ty_class(did, r) { + alt r.self_r { + some(_) { + // Ditto. + mk_class(cx, did, {self_r: none, self_ty: none, tps: r.tps}) } none { t } } diff --git a/src/test/run-pass/classes-self-referential.rs b/src/test/run-pass/classes-self-referential.rs new file mode 100644 index 00000000000..7add8fec1b1 --- /dev/null +++ b/src/test/run-pass/classes-self-referential.rs @@ -0,0 +1,10 @@ +class kitten { + let cat: option<cat>; + new(cat: option<cat>) { + self.cat = cat; + } +} + +type cat = @kitten; + +fn main() {} |
