about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorTim Chevalier <chevalier@alum.wellesley.edu>2012-03-03 17:49:23 -0800
committerTim Chevalier <chevalier@alum.wellesley.edu>2012-03-04 12:43:17 -0800
commite2fa6f03f5b3195b2f81e259a6b946567440b576 (patch)
treeed57e10c040505678b037902964f6d543d2cd52f /src/rustc
parent1d826b735c30a89bfe3aac8acbcda4efc8b5286f (diff)
downloadrust-e2fa6f03f5b3195b2f81e259a6b946567440b576.tar.gz
rust-e2fa6f03f5b3195b2f81e259a6b946567440b576.zip
Translate simple classes
    Programs using classes with fields only (no methods) compile and run,
    as long as nothing refers to a class in a different crate (todo).

    Also changed the AST representation of classes to have a separate
    record for constructor info (instead of inlining the fields in the
    item_class node), and fixed up spans and pretty-printing for
    classes.
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/metadata/astencode_gen.rs304
-rw-r--r--src/rustc/metadata/encoder.rs4
-rw-r--r--src/rustc/middle/resolve.rs22
-rw-r--r--src/rustc/middle/trans/base.rs169
-rw-r--r--src/rustc/middle/trans/closure.rs4
-rw-r--r--src/rustc/middle/trans/common.rs4
-rw-r--r--src/rustc/middle/trans/impl.rs2
-rw-r--r--src/rustc/middle/trans/native.rs3
-rw-r--r--src/rustc/middle/trans/type_of.rs24
-rw-r--r--src/rustc/middle/tstate/pre_post_conditions.rs2
-rw-r--r--src/rustc/middle/ty.rs58
-rw-r--r--src/rustc/middle/typeck.rs36
-rw-r--r--src/rustc/syntax/ast.rs12
-rw-r--r--src/rustc/syntax/fold.rs12
-rw-r--r--src/rustc/syntax/parse/parser.rs47
-rw-r--r--src/rustc/syntax/print/pprust.rs9
-rw-r--r--src/rustc/syntax/visit.rs6
17 files changed, 490 insertions, 228 deletions
diff --git a/src/rustc/metadata/astencode_gen.rs b/src/rustc/metadata/astencode_gen.rs
index 1c413de261c..5bf9829b99d 100644
--- a/src/rustc/metadata/astencode_gen.rs
+++ b/src/rustc/metadata/astencode_gen.rs
@@ -3783,9 +3783,40 @@ fn serialize_148<S: std::serialization::serializer>(s: S,
                               })
                });
 }
-/*syntax::ast::ty_method*/
+/*syntax::ast::class_ctor_*/
 fn serialize_156<S: std::serialization::serializer>(s: S,
                                                     v:
+                                                        syntax::ast::class_ctor_) {
+    s.emit_rec(/*syntax::ast::node_id*//*syntax::ast::fn_decl*/
+               /*syntax::ast::blk*/
+               {||
+                   {
+                       s.emit_rec_field("id", 0u,
+                                        {|| serialize_27(s, v.id) });
+                       s.emit_rec_field("dec", 1u,
+                                        {|| serialize_38(s, v.dec) });
+                       s.emit_rec_field("body", 2u,
+                                        {|| serialize_81(s, v.body) })
+                   }
+               });
+}
+/*syntax::ast::class_ctor*/
+fn serialize_155<S: std::serialization::serializer>(s: S,
+                                                    v:
+                                                        syntax::ast::class_ctor) {
+    s.emit_rec(/*syntax::ast::class_ctor_*//*syntax::codemap::span*/
+               {||
+                   {
+                       s.emit_rec_field("node", 0u,
+                                        {|| serialize_156(s, v.node) });
+                       s.emit_rec_field("span", 1u,
+                                        {|| serialize_19(s, v.span) })
+                   }
+               });
+}
+/*syntax::ast::ty_method*/
+fn serialize_158<S: std::serialization::serializer>(s: S,
+                                                    v:
                                                         syntax::ast::ty_method) {
     s.emit_rec(/*syntax::ast::ident*//*[syntax::ast::attribute]*/
                /*syntax::ast::fn_decl*//*[syntax::ast::ty_param]*/
@@ -3806,19 +3837,19 @@ fn serialize_156<S: std::serialization::serializer>(s: S,
                });
 }
 /*[syntax::ast::ty_method]*/
-fn serialize_155<S: std::serialization::serializer>(s: S,
+fn serialize_157<S: std::serialization::serializer>(s: S,
                                                     v:
                                                         [syntax::ast::ty_method]) {
     s.emit_vec(vec::len(v), /*syntax::ast::ty_method*/
                {||
                    vec::iteri(v,
                               {|i, e|
-                                  s.emit_vec_elt(i, {|| serialize_156(s, e) })
+                                  s.emit_vec_elt(i, {|| serialize_158(s, e) })
                               })
                });
 }
 /*core::option::t<@syntax::ast::ty>*/
-fn serialize_157<S: std::serialization::serializer>(s: S,
+fn serialize_159<S: std::serialization::serializer>(s: S,
                                                     v:
                                                         core::option::t<@syntax::ast::ty>) {
     s.emit_enum("core::option::t",
@@ -3846,7 +3877,7 @@ fn serialize_157<S: std::serialization::serializer>(s: S,
                 });
 }
 /*syntax::ast::method*/
-fn serialize_160<S: std::serialization::serializer>(s: S,
+fn serialize_162<S: std::serialization::serializer>(s: S,
                                                     v: syntax::ast::method) {
 
     s.emit_rec(/*syntax::ast::ident*//*[syntax::ast::attribute]*/
@@ -3873,20 +3904,20 @@ fn serialize_160<S: std::serialization::serializer>(s: S,
                });
 }
 /*@syntax::ast::method*/
-fn serialize_159<S: std::serialization::serializer>(s: S,
+fn serialize_161<S: std::serialization::serializer>(s: S,
                                                     v: @syntax::ast::method) {
 
-    s.emit_box(/*syntax::ast::method*/{|| serialize_160(s, *v) });
+    s.emit_box(/*syntax::ast::method*/{|| serialize_162(s, *v) });
 }
 /*[@syntax::ast::method]*/
-fn serialize_158<S: std::serialization::serializer>(s: S,
+fn serialize_160<S: std::serialization::serializer>(s: S,
                                                     v:
                                                         [@syntax::ast::method]) {
     s.emit_vec(vec::len(v), /*@syntax::ast::method*/
                {||
                    vec::iteri(v,
                               {|i, e|
-                                  s.emit_vec_elt(i, {|| serialize_159(s, e) })
+                                  s.emit_vec_elt(i, {|| serialize_161(s, e) })
                               })
                });
 }
@@ -3906,8 +3937,7 @@ fn serialize_28<S: std::serialization::serializer>(s: S,
                 /*syntax::ast::blk*//*syntax::ast::node_id*/
                 /*syntax::ast::node_id*/
                 /*[syntax::ast::ty_param]*//*[@syntax::ast::class_item]*/
-                /*syntax::ast::node_id*//*syntax::ast::fn_decl*/
-                /*syntax::ast::blk*/
+                /*syntax::ast::class_ctor*/
                 /*[syntax::ast::ty_param]*//*[syntax::ast::ty_method]*/
                 /*[syntax::ast::ty_param]*/
                 /*core::option::t<@syntax::ast::ty>*//*@syntax::ast::ty*/
@@ -4044,8 +4074,8 @@ fn serialize_28<S: std::serialization::serializer>(s: S,
                                                 }
                                             })
                       }
-                      syntax::ast::item_class(v0, v1, v2, v3, v4) {
-                        s.emit_enum_variant("syntax::ast::item_class", 7u, 5u,
+                      syntax::ast::item_class(v0, v1, v2) {
+                        s.emit_enum_variant("syntax::ast::item_class", 7u, 3u,
                                             {||
                                                 {
                                                     s.emit_enum_variant_arg(0u,
@@ -4060,18 +4090,8 @@ fn serialize_28<S: std::serialization::serializer>(s: S,
                                                                             });
                                                     s.emit_enum_variant_arg(2u,
                                                                             {||
-                                                                                serialize_27(s,
-                                                                                             v2)
-                                                                            });
-                                                    s.emit_enum_variant_arg(3u,
-                                                                            {||
-                                                                                serialize_38(s,
-                                                                                             v3)
-                                                                            });
-                                                    s.emit_enum_variant_arg(4u,
-                                                                            {||
-                                                                                serialize_81(s,
-                                                                                             v4)
+                                                                                serialize_155(s,
+                                                                                              v2)
                                                                             })
                                                 }
                                             })
@@ -4087,7 +4107,7 @@ fn serialize_28<S: std::serialization::serializer>(s: S,
                                                                             });
                                                     s.emit_enum_variant_arg(1u,
                                                                             {||
-                                                                                serialize_155(s,
+                                                                                serialize_157(s,
                                                                                               v1)
                                                                             })
                                                 }
@@ -4104,7 +4124,7 @@ fn serialize_28<S: std::serialization::serializer>(s: S,
                                                                             });
                                                     s.emit_enum_variant_arg(1u,
                                                                             {||
-                                                                                serialize_157(s,
+                                                                                serialize_159(s,
                                                                                               v1)
                                                                             });
                                                     s.emit_enum_variant_arg(2u,
@@ -4114,7 +4134,7 @@ fn serialize_28<S: std::serialization::serializer>(s: S,
                                                                             });
                                                     s.emit_enum_variant_arg(3u,
                                                                             {||
-                                                                                serialize_158(s,
+                                                                                serialize_160(s,
                                                                                               v3)
                                                                             })
                                                 }
@@ -7599,8 +7619,51 @@ fn deserialize_148<S: std::serialization::deserializer>(s: S) ->
                                 })
                })
 }
-/*syntax::ast::ty_method*/
+/*syntax::ast::class_ctor_*/
 fn deserialize_156<S: std::serialization::deserializer>(s: S) ->
+   syntax::ast::class_ctor_ {
+
+    s.read_rec(
+
+
+               /*syntax::ast::node_id*/
+
+               /*syntax::ast::fn_decl*/
+
+               /*syntax::ast::blk*/
+
+               {||
+                   {id: s.read_rec_field("id", 0u, {|| deserialize_27(s) }),
+                    dec: s.read_rec_field("dec", 1u, {|| deserialize_38(s) }),
+                    body:
+                        s.read_rec_field("body", 2u,
+                                         {|| deserialize_81(s) }),}
+               })
+
+}
+/*syntax::ast::class_ctor*/
+fn deserialize_155<S: std::serialization::deserializer>(s: S) ->
+   syntax::ast::class_ctor {
+
+    s.read_rec(
+
+
+               /*syntax::ast::class_ctor_*/
+
+               /*syntax::codemap::span*/
+
+               {||
+                   {node:
+                        s.read_rec_field("node", 0u,
+                                         {|| deserialize_156(s) }),
+                    span:
+                        s.read_rec_field("span", 1u,
+                                         {|| deserialize_19(s) }),}
+               })
+
+}
+/*syntax::ast::ty_method*/
+fn deserialize_158<S: std::serialization::deserializer>(s: S) ->
    syntax::ast::ty_method {
 
     s.read_rec(
@@ -7632,7 +7695,7 @@ fn deserialize_156<S: std::serialization::deserializer>(s: S) ->
 
 }
 /*[syntax::ast::ty_method]*/
-fn deserialize_155<S: std::serialization::deserializer>(s: S) ->
+fn deserialize_157<S: std::serialization::deserializer>(s: S) ->
    [syntax::ast::ty_method] {
     s.read_vec(
 
@@ -7641,12 +7704,12 @@ fn deserialize_155<S: std::serialization::deserializer>(s: S) ->
                    vec::init_fn(len,
                                 {|i|
                                     s.read_vec_elt(i,
-                                                   {|| deserialize_156(s) })
+                                                   {|| deserialize_158(s) })
                                 })
                })
 }
 /*core::option::t<@syntax::ast::ty>*/
-fn deserialize_157<S: std::serialization::deserializer>(s: S) ->
+fn deserialize_159<S: std::serialization::deserializer>(s: S) ->
    core::option::t<@syntax::ast::ty> {
     s.read_enum("core::option::t",
 
@@ -7667,7 +7730,7 @@ fn deserialize_157<S: std::serialization::deserializer>(s: S) ->
                 })
 }
 /*syntax::ast::method*/
-fn deserialize_160<S: std::serialization::deserializer>(s: S) ->
+fn deserialize_162<S: std::serialization::deserializer>(s: S) ->
    syntax::ast::method {
 
     s.read_rec(
@@ -7706,14 +7769,14 @@ fn deserialize_160<S: std::serialization::deserializer>(s: S) ->
 
 }
 /*@syntax::ast::method*/
-fn deserialize_159<S: std::serialization::deserializer>(s: S) ->
+fn deserialize_161<S: std::serialization::deserializer>(s: S) ->
    @syntax::ast::method {
 
-    s.read_box(/*syntax::ast::method*/{|| @deserialize_160(s) })
+    s.read_box(/*syntax::ast::method*/{|| @deserialize_162(s) })
 
 }
 /*[@syntax::ast::method]*/
-fn deserialize_158<S: std::serialization::deserializer>(s: S) ->
+fn deserialize_160<S: std::serialization::deserializer>(s: S) ->
    [@syntax::ast::method] {
     s.read_vec(
 
@@ -7722,7 +7785,7 @@ fn deserialize_158<S: std::serialization::deserializer>(s: S) ->
                    vec::init_fn(len,
                                 {|i|
                                     s.read_vec_elt(i,
-                                                   {|| deserialize_159(s) })
+                                                   {|| deserialize_161(s) })
                                 })
                })
 }
@@ -7748,8 +7811,7 @@ fn deserialize_28<S: std::serialization::deserializer>(s: S) ->
                 /*syntax::ast::node_id*/
 
                 /*[syntax::ast::ty_param]*//*[@syntax::ast::class_item]*/
-                /*syntax::ast::node_id*//*syntax::ast::fn_decl*/
-                /*syntax::ast::blk*/
+                /*syntax::ast::class_ctor*/
 
                 /*[syntax::ast::ty_param]*//*[syntax::ast::ty_method]*/
 
@@ -7848,15 +7910,7 @@ fn deserialize_28<S: std::serialization::deserializer>(s: S) ->
                                                                                                 }),
                                                                         s.read_enum_variant_arg(2u,
                                                                                                 {||
-                                                                                                    deserialize_27(s)
-                                                                                                }),
-                                                                        s.read_enum_variant_arg(3u,
-                                                                                                {||
-                                                                                                    deserialize_38(s)
-                                                                                                }),
-                                                                        s.read_enum_variant_arg(4u,
-                                                                                                {||
-                                                                                                    deserialize_81(s)
+                                                                                                    deserialize_155(s)
                                                                                                 }))
                                               }
                                               8u {
@@ -7866,7 +7920,7 @@ fn deserialize_28<S: std::serialization::deserializer>(s: S) ->
                                                                                                 }),
                                                                         s.read_enum_variant_arg(1u,
                                                                                                 {||
-                                                                                                    deserialize_155(s)
+                                                                                                    deserialize_157(s)
                                                                                                 }))
                                               }
                                               9u {
@@ -7876,7 +7930,7 @@ fn deserialize_28<S: std::serialization::deserializer>(s: S) ->
                                                                                                }),
                                                                        s.read_enum_variant_arg(1u,
                                                                                                {||
-                                                                                                   deserialize_157(s)
+                                                                                                   deserialize_159(s)
                                                                                                }),
                                                                        s.read_enum_variant_arg(2u,
                                                                                                {||
@@ -7884,7 +7938,7 @@ fn deserialize_28<S: std::serialization::deserializer>(s: S) ->
                                                                                                }),
                                                                        s.read_enum_variant_arg(3u,
                                                                                                {||
-                                                                                                   deserialize_158(s)
+                                                                                                   deserialize_160(s)
                                                                                                }))
                                               }
                                             }
@@ -7927,27 +7981,27 @@ fn deserialize_syntax_ast_item<S: std::serialization::deserializer>(s: S) ->
     deserialize_0(s)
 }
 /*syntax::ast::crate_num*/
-fn serialize_163<S: std::serialization::serializer>(s: S,
+fn serialize_165<S: std::serialization::serializer>(s: S,
                                                     v:
                                                         syntax::ast::crate_num) {
     s.emit_int(v);
 }
 /*syntax::ast::def_id*/
-fn serialize_162<S: std::serialization::serializer>(s: S,
+fn serialize_164<S: std::serialization::serializer>(s: S,
                                                     v: syntax::ast::def_id) {
 
     s.emit_rec(/*syntax::ast::crate_num*//*syntax::ast::node_id*/
                {||
                    {
                        s.emit_rec_field("crate", 0u,
-                                        {|| serialize_163(s, v.crate) });
+                                        {|| serialize_165(s, v.crate) });
                        s.emit_rec_field("node", 1u,
                                         {|| serialize_27(s, v.node) })
                    }
                });
 }
 /*syntax::ast::prim_ty*/
-fn serialize_164<S: std::serialization::serializer>(s: S,
+fn serialize_166<S: std::serialization::serializer>(s: S,
                                                     v: syntax::ast::prim_ty) {
 
     s.emit_enum("syntax::ast::prim_ty",
@@ -8005,13 +8059,13 @@ fn serialize_164<S: std::serialization::serializer>(s: S,
                 });
 }
 /*@syntax::ast::def*/
-fn serialize_165<S: std::serialization::serializer>(s: S,
+fn serialize_167<S: std::serialization::serializer>(s: S,
                                                     v: @syntax::ast::def) {
 
-    s.emit_box(/*syntax::ast::def*/{|| serialize_161(s, *v) });
+    s.emit_box(/*syntax::ast::def*/{|| serialize_163(s, *v) });
 }
 /*syntax::ast::def*/
-fn serialize_161<S: std::serialization::serializer>(s: S,
+fn serialize_163<S: std::serialization::serializer>(s: S,
                                                     v: syntax::ast::def) {
 
     s.emit_enum("syntax::ast::def",
@@ -8042,7 +8096,7 @@ fn serialize_161<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v0)
                                                                             });
                                                     s.emit_enum_variant_arg(1u,
@@ -8071,7 +8125,7 @@ fn serialize_161<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v0)
                                                                             })
                                                 }
@@ -8084,7 +8138,7 @@ fn serialize_161<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v0)
                                                                             })
                                                 }
@@ -8096,7 +8150,7 @@ fn serialize_161<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v0)
                                                                             })
                                                 }
@@ -8143,12 +8197,12 @@ fn serialize_161<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v0)
                                                                             });
                                                     s.emit_enum_variant_arg(1u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v1)
                                                                             })
                                                 }
@@ -8160,7 +8214,7 @@ fn serialize_161<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v0)
                                                                             })
                                                 }
@@ -8173,7 +8227,7 @@ fn serialize_161<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_164(s,
+                                                                                serialize_166(s,
                                                                                               v0)
                                                                             })
                                                 }
@@ -8186,7 +8240,7 @@ fn serialize_161<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v0)
                                                                             });
                                                     s.emit_enum_variant_arg(1u,
@@ -8216,7 +8270,7 @@ fn serialize_161<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v0)
                                                                             })
                                                 }
@@ -8233,7 +8287,7 @@ fn serialize_161<S: std::serialization::serializer>(s: S,
                                                                             });
                                                     s.emit_enum_variant_arg(1u,
                                                                             {||
-                                                                                serialize_165(s,
+                                                                                serialize_167(s,
                                                                                               v1)
                                                                             });
                                                     s.emit_enum_variant_arg(2u,
@@ -8250,7 +8304,7 @@ fn serialize_161<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v0)
                                                                             })
                                                 }
@@ -8263,12 +8317,12 @@ fn serialize_161<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v0)
                                                                             });
                                                     s.emit_enum_variant_arg(1u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v1)
                                                                             })
                                                 }
@@ -8281,12 +8335,12 @@ fn serialize_161<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v0)
                                                                             });
                                                     s.emit_enum_variant_arg(1u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v1)
                                                                             })
                                                 }
@@ -8298,15 +8352,15 @@ fn serialize_161<S: std::serialization::serializer>(s: S,
 fn serialize_syntax_ast_def<S: std::serialization::serializer>(s: S,
                                                                v:
                                                                    syntax::ast::def) {
-    serialize_161(s, v);
+    serialize_163(s, v);
 }
 /*syntax::ast::crate_num*/
-fn deserialize_163<S: std::serialization::deserializer>(s: S) ->
+fn deserialize_165<S: std::serialization::deserializer>(s: S) ->
    syntax::ast::crate_num {
     s.read_int()
 }
 /*syntax::ast::def_id*/
-fn deserialize_162<S: std::serialization::deserializer>(s: S) ->
+fn deserialize_164<S: std::serialization::deserializer>(s: S) ->
    syntax::ast::def_id {
 
     s.read_rec(
@@ -8319,7 +8373,7 @@ fn deserialize_162<S: std::serialization::deserializer>(s: S) ->
                {||
                    {crate:
                         s.read_rec_field("crate", 0u,
-                                         {|| deserialize_163(s) }),
+                                         {|| deserialize_165(s) }),
                     node:
                         s.read_rec_field("node", 1u,
                                          {|| deserialize_27(s) }),}
@@ -8327,7 +8381,7 @@ fn deserialize_162<S: std::serialization::deserializer>(s: S) ->
 
 }
 /*syntax::ast::prim_ty*/
-fn deserialize_164<S: std::serialization::deserializer>(s: S) ->
+fn deserialize_166<S: std::serialization::deserializer>(s: S) ->
    syntax::ast::prim_ty {
     s.read_enum("syntax::ast::prim_ty",
                 /*syntax::ast::int_ty*/
@@ -8367,14 +8421,14 @@ fn deserialize_164<S: std::serialization::deserializer>(s: S) ->
                 })
 }
 /*@syntax::ast::def*/
-fn deserialize_165<S: std::serialization::deserializer>(s: S) ->
+fn deserialize_167<S: std::serialization::deserializer>(s: S) ->
    @syntax::ast::def {
 
-    s.read_box(/*syntax::ast::def*/{|| @deserialize_161(s) })
+    s.read_box(/*syntax::ast::def*/{|| @deserialize_163(s) })
 
 }
 /*syntax::ast::def*/
-fn deserialize_161<S: std::serialization::deserializer>(s: S) ->
+fn deserialize_163<S: std::serialization::deserializer>(s: S) ->
    syntax::ast::def {
     s.read_enum("syntax::ast::def",
                 /*syntax::ast::def_id*//*syntax::ast::purity*/
@@ -8418,7 +8472,7 @@ fn deserialize_161<S: std::serialization::deserializer>(s: S) ->
                                               0u {
                                                 syntax::ast::def_fn(s.read_enum_variant_arg(0u,
                                                                                             {||
-                                                                                                deserialize_162(s)
+                                                                                                deserialize_164(s)
                                                                                             }),
                                                                     s.read_enum_variant_arg(1u,
                                                                                             {||
@@ -8434,19 +8488,19 @@ fn deserialize_161<S: std::serialization::deserializer>(s: S) ->
                                               2u {
                                                 syntax::ast::def_mod(s.read_enum_variant_arg(0u,
                                                                                              {||
-                                                                                                 deserialize_162(s)
+                                                                                                 deserialize_164(s)
                                                                                              }))
                                               }
                                               3u {
                                                 syntax::ast::def_native_mod(s.read_enum_variant_arg(0u,
                                                                                                     {||
-                                                                                                        deserialize_162(s)
+                                                                                                        deserialize_164(s)
                                                                                                     }))
                                               }
                                               4u {
                                                 syntax::ast::def_const(s.read_enum_variant_arg(0u,
                                                                                                {||
-                                                                                                   deserialize_162(s)
+                                                                                                   deserialize_164(s)
                                                                                                }))
                                               }
                                               5u {
@@ -8472,29 +8526,29 @@ fn deserialize_161<S: std::serialization::deserializer>(s: S) ->
                                               7u {
                                                 syntax::ast::def_variant(s.read_enum_variant_arg(0u,
                                                                                                  {||
-                                                                                                     deserialize_162(s)
+                                                                                                     deserialize_164(s)
                                                                                                  }),
                                                                          s.read_enum_variant_arg(1u,
                                                                                                  {||
-                                                                                                     deserialize_162(s)
+                                                                                                     deserialize_164(s)
                                                                                                  }))
                                               }
                                               8u {
                                                 syntax::ast::def_ty(s.read_enum_variant_arg(0u,
                                                                                             {||
-                                                                                                deserialize_162(s)
+                                                                                                deserialize_164(s)
                                                                                             }))
                                               }
                                               9u {
                                                 syntax::ast::def_prim_ty(s.read_enum_variant_arg(0u,
                                                                                                  {||
-                                                                                                     deserialize_164(s)
+                                                                                                     deserialize_166(s)
                                                                                                  }))
                                               }
                                               10u {
                                                 syntax::ast::def_ty_param(s.read_enum_variant_arg(0u,
                                                                                                   {||
-                                                                                                      deserialize_162(s)
+                                                                                                      deserialize_164(s)
                                                                                                   }),
                                                                           s.read_enum_variant_arg(1u,
                                                                                                   {||
@@ -8510,7 +8564,7 @@ fn deserialize_161<S: std::serialization::deserializer>(s: S) ->
                                               12u {
                                                 syntax::ast::def_use(s.read_enum_variant_arg(0u,
                                                                                              {||
-                                                                                                 deserialize_162(s)
+                                                                                                 deserialize_164(s)
                                                                                              }))
                                               }
                                               13u {
@@ -8520,7 +8574,7 @@ fn deserialize_161<S: std::serialization::deserializer>(s: S) ->
                                                                                                }),
                                                                        s.read_enum_variant_arg(1u,
                                                                                                {||
-                                                                                                   deserialize_165(s)
+                                                                                                   deserialize_167(s)
                                                                                                }),
                                                                        s.read_enum_variant_arg(2u,
                                                                                                {||
@@ -8530,27 +8584,27 @@ fn deserialize_161<S: std::serialization::deserializer>(s: S) ->
                                               14u {
                                                 syntax::ast::def_class(s.read_enum_variant_arg(0u,
                                                                                                {||
-                                                                                                   deserialize_162(s)
+                                                                                                   deserialize_164(s)
                                                                                                }))
                                               }
                                               15u {
                                                 syntax::ast::def_class_field(s.read_enum_variant_arg(0u,
                                                                                                      {||
-                                                                                                         deserialize_162(s)
+                                                                                                         deserialize_164(s)
                                                                                                      }),
                                                                              s.read_enum_variant_arg(1u,
                                                                                                      {||
-                                                                                                         deserialize_162(s)
+                                                                                                         deserialize_164(s)
                                                                                                      }))
                                               }
                                               16u {
                                                 syntax::ast::def_class_method(s.read_enum_variant_arg(0u,
                                                                                                       {||
-                                                                                                          deserialize_162(s)
+                                                                                                          deserialize_164(s)
                                                                                                       }),
                                                                               s.read_enum_variant_arg(1u,
                                                                                                       {||
-                                                                                                          deserialize_162(s)
+                                                                                                          deserialize_164(s)
                                                                                                       }))
                                               }
                                             }
@@ -8559,10 +8613,10 @@ fn deserialize_161<S: std::serialization::deserializer>(s: S) ->
 }
 fn deserialize_syntax_ast_def<S: std::serialization::deserializer>(s: S) ->
    syntax::ast::def {
-    deserialize_161(s)
+    deserialize_163(s)
 }
 /*middle::typeck::method_origin*/
-fn serialize_166<S: std::serialization::serializer>(s: S,
+fn serialize_168<S: std::serialization::serializer>(s: S,
                                                     v:
                                                         middle::typeck::method_origin) {
     s.emit_enum("middle::typeck::method_origin",
@@ -8578,7 +8632,7 @@ fn serialize_166<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v0)
                                                                             })
                                                 }
@@ -8591,7 +8645,7 @@ fn serialize_166<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v0)
                                                                             });
                                                     s.emit_enum_variant_arg(1u,
@@ -8619,7 +8673,7 @@ fn serialize_166<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v0)
                                                                             });
                                                     s.emit_enum_variant_arg(1u,
@@ -8637,10 +8691,10 @@ fn serialize_middle_typeck_method_origin<S: std::serialization::serializer>(s:
                                                                                 S,
                                                                             v:
                                                                                 middle::typeck::method_origin) {
-    serialize_166(s, v);
+    serialize_168(s, v);
 }
 /*middle::typeck::method_origin*/
-fn deserialize_166<S: std::serialization::deserializer>(s: S) ->
+fn deserialize_168<S: std::serialization::deserializer>(s: S) ->
    middle::typeck::method_origin {
     s.read_enum("middle::typeck::method_origin",
                 /*syntax::ast::def_id*/
@@ -8654,13 +8708,13 @@ fn deserialize_166<S: std::serialization::deserializer>(s: S) ->
                                               0u {
                                                 middle::typeck::method_static(s.read_enum_variant_arg(0u,
                                                                                                       {||
-                                                                                                          deserialize_162(s)
+                                                                                                          deserialize_164(s)
                                                                                                       }))
                                               }
                                               1u {
                                                 middle::typeck::method_param(s.read_enum_variant_arg(0u,
                                                                                                      {||
-                                                                                                         deserialize_162(s)
+                                                                                                         deserialize_164(s)
                                                                                                      }),
                                                                              s.read_enum_variant_arg(1u,
                                                                                                      {||
@@ -8678,7 +8732,7 @@ fn deserialize_166<S: std::serialization::deserializer>(s: S) ->
                                               2u {
                                                 middle::typeck::method_iface(s.read_enum_variant_arg(0u,
                                                                                                      {||
-                                                                                                         deserialize_162(s)
+                                                                                                         deserialize_164(s)
                                                                                                      }),
                                                                              s.read_enum_variant_arg(1u,
                                                                                                      {||
@@ -8692,17 +8746,17 @@ fn deserialize_166<S: std::serialization::deserializer>(s: S) ->
 fn deserialize_middle_typeck_method_origin<S: std::serialization::deserializer>(s:
                                                                                     S)
    -> middle::typeck::method_origin {
-    deserialize_166(s)
+    deserialize_168(s)
 }
 /*middle::freevars::freevar_entry*/
-fn serialize_167<S: std::serialization::serializer>(s: S,
+fn serialize_169<S: std::serialization::serializer>(s: S,
                                                     v:
                                                         middle::freevars::freevar_entry) {
     s.emit_rec(/*syntax::ast::def*//*syntax::codemap::span*/
                {||
                    {
                        s.emit_rec_field("def", 0u,
-                                        {|| serialize_161(s, v.def) });
+                                        {|| serialize_163(s, v.def) });
                        s.emit_rec_field("span", 1u,
                                         {|| serialize_19(s, v.span) })
                    }
@@ -8712,10 +8766,10 @@ fn serialize_middle_freevars_freevar_entry<S: std::serialization::serializer>(s:
                                                                                   S,
                                                                               v:
                                                                                   middle::freevars::freevar_entry) {
-    serialize_167(s, v);
+    serialize_169(s, v);
 }
 /*middle::freevars::freevar_entry*/
-fn deserialize_167<S: std::serialization::deserializer>(s: S) ->
+fn deserialize_169<S: std::serialization::deserializer>(s: S) ->
    middle::freevars::freevar_entry {
 
     s.read_rec(
@@ -8727,7 +8781,7 @@ fn deserialize_167<S: std::serialization::deserializer>(s: S) ->
 
                {||
                    {def:
-                        s.read_rec_field("def", 0u, {|| deserialize_161(s) }),
+                        s.read_rec_field("def", 0u, {|| deserialize_163(s) }),
                     span:
                         s.read_rec_field("span", 1u,
                                          {|| deserialize_19(s) }),}
@@ -8737,19 +8791,19 @@ fn deserialize_167<S: std::serialization::deserializer>(s: S) ->
 fn deserialize_middle_freevars_freevar_entry<S: std::serialization::deserializer>(s:
                                                                                       S)
    -> middle::freevars::freevar_entry {
-    deserialize_167(s)
+    deserialize_169(s)
 }
 fn serialize_syntax_ast_def_id<S: std::serialization::serializer>(s: S,
                                                                   v:
                                                                       syntax::ast::def_id) {
-    serialize_162(s, v);
+    serialize_164(s, v);
 }
 fn deserialize_syntax_ast_def_id<S: std::serialization::deserializer>(s: S) ->
    syntax::ast::def_id {
-    deserialize_162(s)
+    deserialize_164(s)
 }
 /*syntax::ast::inlined_item*/
-fn serialize_168<S: std::serialization::serializer>(s: S,
+fn serialize_170<S: std::serialization::serializer>(s: S,
                                                     v:
                                                         syntax::ast::inlined_item) {
     s.emit_enum("syntax::ast::inlined_item",
@@ -8775,12 +8829,12 @@ fn serialize_168<S: std::serialization::serializer>(s: S,
                                                 {
                                                     s.emit_enum_variant_arg(0u,
                                                                             {||
-                                                                                serialize_162(s,
+                                                                                serialize_164(s,
                                                                                               v0)
                                                                             });
                                                     s.emit_enum_variant_arg(1u,
                                                                             {||
-                                                                                serialize_159(s,
+                                                                                serialize_161(s,
                                                                                               v1)
                                                                             })
                                                 }
@@ -8792,10 +8846,10 @@ fn serialize_168<S: std::serialization::serializer>(s: S,
 fn serialize_syntax_ast_inlined_item<S: std::serialization::serializer>(s: S,
                                                                         v:
                                                                             syntax::ast::inlined_item) {
-    serialize_168(s, v);
+    serialize_170(s, v);
 }
 /*syntax::ast::inlined_item*/
-fn deserialize_168<S: std::serialization::deserializer>(s: S) ->
+fn deserialize_170<S: std::serialization::deserializer>(s: S) ->
    syntax::ast::inlined_item {
     s.read_enum("syntax::ast::inlined_item",
                 /*@syntax::ast::item*/
@@ -8813,11 +8867,11 @@ fn deserialize_168<S: std::serialization::deserializer>(s: S) ->
                                               1u {
                                                 syntax::ast::ii_method(s.read_enum_variant_arg(0u,
                                                                                                {||
-                                                                                                   deserialize_162(s)
+                                                                                                   deserialize_164(s)
                                                                                                }),
                                                                        s.read_enum_variant_arg(1u,
                                                                                                {||
-                                                                                                   deserialize_159(s)
+                                                                                                   deserialize_161(s)
                                                                                                }))
                                               }
                                             }
@@ -8827,5 +8881,5 @@ fn deserialize_168<S: std::serialization::deserializer>(s: S) ->
 fn deserialize_syntax_ast_inlined_item<S: std::serialization::deserializer>(s:
                                                                                 S)
    -> syntax::ast::inlined_item {
-    deserialize_168(s)
+    deserialize_170(s)
 }
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index 2da07511628..a8173d51f06 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -127,7 +127,7 @@ fn encode_module_item_paths(ebml_w: ebml::writer, module: _mod, path: [str],
             encode_def_id(ebml_w, local_def(it.id));
             ebml_w.end_tag();
           }
-          item_class(_,_,_,_,_) {
+          item_class(_,_,_) {
               fail "encode: implement item_class";
           }
           item_enum(variants, tps) {
@@ -384,7 +384,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_enum_variant_info(ecx, ebml_w, item.id, variants,
                                  path, index, tps);
       }
-      item_class(_,_,_,_,_) {
+      item_class(_,_,_) {
           fail "encode: implement item_class";
       }
       item_res(_, tps, _, _, ctor_id) {
diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs
index 117641c9fe8..aa8f7ac5367 100644
--- a/src/rustc/middle/resolve.rs
+++ b/src/rustc/middle/resolve.rs
@@ -541,12 +541,12 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
             v.visit_ty(m.decl.output, msc, v);
         }
       }
-      ast::item_class(tps, members, ctor_id, ctor_decl, ctor_block) {
+      ast::item_class(tps, members, ctor) {
         visit::visit_ty_params(tps, sc, v);
         let class_scope = cons(scope_item(i), @sc);
         /* visit the constructor... */
-        visit_fn_with_scope(e, visit::fk_item_fn(i.ident, tps), ctor_decl,
-                            ctor_block, ctor_block.span, ctor_id,
+        visit_fn_with_scope(e, visit::fk_item_fn(i.ident, tps), ctor.node.dec,
+                            ctor.node.body, ctor.span, ctor.node.id,
                             class_scope, v);
         /* visit the items */
         for cm in members {
@@ -1029,12 +1029,12 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
               ast::item_native_mod(m) {
                 ret lookup_in_local_native_mod(e, it.id, sp, name, ns);
               }
-              ast::item_class(tps, members, ctor_id, _, _) {
+              ast::item_class(tps, members, ctor) {
                   if ns == ns_type {
                     ret lookup_in_ty_params(e, name, tps);
                   }
                   if ns == ns_val(value_or_enum) && name == it.ident {
-                      ret some(ast::def_fn(local_def(ctor_id),
+                      ret some(ast::def_fn(local_def(ctor.node.id),
                                            ast::impure_fn));
                   }
                   if ns == ns_val(value_or_enum) {
@@ -1359,7 +1359,7 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option<def> {
           _ { }
         }
       }
-      ast::item_class(_, _, _, _, _) {
+      ast::item_class(_, _, _) {
           if ns == ns_type {
             ret some(ast::def_class(local_def(i.id)));
           }
@@ -1664,16 +1664,16 @@ fn index_mod(md: ast::_mod) -> mod_index {
                 variant_idx += 1u;
             }
           }
-          ast::item_class(tps, items, ctor_id, ctor_decl, ctor_body) {
+          ast::item_class(tps, items, ctor) {
               // add the class name itself
               add_to_index(index, it.ident, mie_item(it));
               // add the constructor decl
               add_to_index(index, it.ident,
                            mie_item(@{ident: it.ident, attrs: [],
-                                       id: ctor_id,
-                                       node:
-                                         item_fn(ctor_decl, tps, ctor_body),
-                                       span: ctor_body.span}));
+                            id: ctor.node.id,
+                            node:
+                              item_fn(ctor.node.dec, tps, ctor.node.body),
+                            span: ctor.node.body.span}));
               // add the members
               for ci in items {
                  add_to_index(index, class_item_ident(ci),
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 6947a6875c4..12beb363d04 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -49,6 +49,8 @@ import type_of::*;
 import type_of::type_of; // Issue #1873
 import ast_map::{path, path_mod, path_name};
 
+import std::smallintmap;
+
 // Destinations
 
 // These are passed around by the code generating functions to track the
@@ -1208,6 +1210,15 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
         }
         ret next_cx;
       }
+      ty::ty_class(did, tps) {
+          // a class is like a record type
+        let i: int = 0;
+        for fld: ty::field in ty::class_items_as_fields(cx.tcx(), did) {
+            let {bcx: bcx, val: llfld_a} = GEP_tup_like(cx, t, av, [0, i]);
+            cx = f(bcx, llfld_a, fld.mt.ty);
+            i += 1;
+        }
+      }
       _ { cx.sess().unimpl("type in iter_structural_ty"); }
     }
     ret cx;
@@ -2096,7 +2107,7 @@ fn monomorphic_fn(ccx: crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
     alt check map_node {
       ast_map::node_item(@{node: ast::item_fn(decl, _, body), _}, _) {
         trans_fn(ccx, pt, decl, body, lldecl, no_self, [],
-                 psubsts, fn_id.node);
+                 psubsts, fn_id.node, none);
       }
       ast_map::node_item(@{node: ast::item_res(decl, _, _, _, _), _}, _) {
         trans_res_ctor(ccx, pt, decl, fn_id.node, [], psubsts, lldecl);
@@ -2112,7 +2123,7 @@ fn monomorphic_fn(ccx: crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
         let selfty = ty::lookup_item_type(ccx.tcx, impl_def_id).ty;
         let selfty = ty::substitute_type_params(ccx.tcx, substs, selfty);
         trans_fn(ccx, pt, mth.decl, mth.body, lldecl,
-                 impl_self(selfty), [], psubsts, fn_id.node);
+                 impl_self(selfty), [], psubsts, fn_id.node, none);
       }
     }
     some({llfn: lldecl, fty: mono_ty})
@@ -2267,17 +2278,26 @@ fn trans_local_var(cx: block, def: ast::def) -> local_var_result {
         ret {val: ptr, kind: owned};
       }
       _ {
-        cx.sess().unimpl("unsupported def type in trans_local_def");
+        cx.sess().unimpl(#fmt("unsupported def type in trans_local_def: %?",
+                              def));
       }
     }
 }
 
-fn trans_path(cx: block, id: ast::node_id)
+// The third argument (path) ends up getting used when the id
+// refers to a field within the enclosing class, since the name
+// gets turned into a record field name.
+fn trans_path(cx: block, id: ast::node_id, path: @ast::path)
     -> lval_maybe_callee {
-    ret trans_var(cx, cx.tcx().def_map.get(id), id);
+    alt cx.tcx().def_map.find(id) {
+      none { cx.sess().bug("trans_path: unbound node ID"); }
+      some(df) {
+          ret trans_var(cx, df, id, path);
+      }
+    }
 }
 
-fn trans_var(cx: block, def: ast::def, id: ast::node_id)
+fn trans_var(cx: block, def: ast::def, id: ast::node_id, path: @ast::path)
     -> lval_maybe_callee {
     let ccx = cx.ccx();
     alt def {
@@ -2313,6 +2333,18 @@ fn trans_var(cx: block, def: ast::def, id: ast::node_id)
             ret lval_no_env(cx, load_if_immediate(cx, val, tp), owned_imm);
         }
       }
+      ast::def_class_field(parent, did) {
+          // base is implicitly "Self"
+          alt cx.fcx.self_id {
+            some(slf) {
+                let {bcx, val, kind} = trans_rec_field(cx, slf,
+                    // TODO: only supporting local objects for now
+                                          path_to_ident(path));
+                ret lval_no_env(bcx, val, kind);
+            }
+            _ { cx.sess().bug("unbound self param in class"); }
+          }
+     }
       _ {
         let loc = trans_local_var(cx, def);
         ret lval_no_env(cx, loc.val, loc.kind);
@@ -2326,6 +2358,7 @@ fn trans_rec_field(bcx: block, base: @ast::expr,
     let {bcx, val, ty} = autoderef(bcx, val, expr_ty(bcx, base));
     let fields = alt ty::get(ty).struct {
             ty::ty_rec(fs) { fs }
+            ty::ty_class(did,_) { ty::class_items_as_fields(bcx.tcx(), did) }
             // Constraint?
             _ { bcx.tcx().sess.span_bug(base.span, "trans_rec_field:\
                  base expr has non-record type"); }
@@ -2386,7 +2419,7 @@ fn expr_is_lval(bcx: block, e: @ast::expr) -> bool {
 
 fn trans_callee(bcx: block, e: @ast::expr) -> lval_maybe_callee {
     alt e.node {
-      ast::expr_path(_) { ret trans_path(bcx, e.id); }
+      ast::expr_path(path) { ret trans_path(bcx, e.id, path); }
       ast::expr_field(base, ident, _) {
         // Lval means this is a record field, so not a method
         if !expr_is_lval(bcx, e) {
@@ -2412,8 +2445,8 @@ fn trans_callee(bcx: block, e: @ast::expr) -> lval_maybe_callee {
 // immediate).
 fn trans_lval(cx: block, e: @ast::expr) -> lval_result {
     alt e.node {
-      ast::expr_path(_) {
-        let v = trans_path(cx, e.id);
+      ast::expr_path(p) {
+          let v = trans_path(cx, e.id, p);
         ret lval_maybe_callee_to_lval(v, expr_ty(cx, e));
       }
       ast::expr_field(base, ident, _) {
@@ -3839,6 +3872,7 @@ fn mk_standard_basic_blocks(llfn: ValueRef) ->
 //  - trans_args
 fn new_fn_ctxt_w_id(ccx: crate_ctxt, path: path,
                     llfndecl: ValueRef, id: ast::node_id,
+                    maybe_self_id: option<@ast::expr>,
                     param_substs: option<param_substs>,
                     sp: option<span>) -> fn_ctxt {
     let llbbs = mk_standard_basic_blocks(llfndecl);
@@ -3860,6 +3894,7 @@ fn new_fn_ctxt_w_id(ccx: crate_ctxt, path: path,
           mutable lltyparams: [],
           derived_tydescs: ty::new_ty_hash(),
           id: id,
+          self_id: maybe_self_id,
           param_substs: param_substs,
           span: sp,
           path: path,
@@ -3868,7 +3903,7 @@ fn new_fn_ctxt_w_id(ccx: crate_ctxt, path: path,
 
 fn new_fn_ctxt(ccx: crate_ctxt, path: path, llfndecl: ValueRef,
                sp: option<span>) -> fn_ctxt {
-    ret new_fn_ctxt_w_id(ccx, path, llfndecl, -1, none, sp);
+    ret new_fn_ctxt_w_id(ccx, path, llfndecl, -1, none, none, sp);
 }
 
 // NB: must keep 4 fns in sync:
@@ -3991,12 +4026,13 @@ fn trans_closure(ccx: crate_ctxt, path: path, decl: ast::fn_decl,
                  ty_self: self_arg,
                  tps_bounds: [ty::param_bounds],
                  param_substs: option<param_substs>,
-                 id: ast::node_id, maybe_load_env: fn(fn_ctxt)) {
+                 id: ast::node_id, maybe_self_id: option<@ast::expr>,
+                 maybe_load_env: fn(fn_ctxt)) {
     set_uwtable(llfndecl);
 
     // Set up arguments to the function.
-    let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, param_substs,
-                               some(body.span));
+            let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, maybe_self_id,
+                  param_substs, some(body.span));
     create_llargs_for_fn_args(fcx, ty_self, decl.inputs, tps_bounds);
 
     // Create the first basic block in the function and keep a handle on it to
@@ -4014,9 +4050,14 @@ fn trans_closure(ccx: crate_ctxt, path: path, decl: ast::fn_decl,
     // translation calls that don't have a return value (trans_crate,
     // trans_mod, trans_item, et cetera) and those that do
     // (trans_block, trans_expr, et cetera).
-    if option::is_none(body.node.expr) ||
+
+    if option::is_none(maybe_self_id) // hack --
+       /* avoids the need for special cases to assign a type to
+          the constructor body (since it has no explicit return) */
+      &&
+      (option::is_none(body.node.expr) ||
        ty::type_is_bot(block_ty) ||
-       ty::type_is_nil(block_ty) {
+       ty::type_is_nil(block_ty))  {
         bcx = trans_block(bcx, body, ignore);
     } else {
         bcx = trans_block(bcx, body, save_in(fcx.llretptr));
@@ -4037,12 +4078,13 @@ fn trans_fn(ccx: crate_ctxt,
             ty_self: self_arg,
             tps_bounds: [ty::param_bounds],
             param_substs: option<param_substs>,
-            id: ast::node_id) {
+            id: ast::node_id,
+            maybe_self_id: option<@ast::expr>) {
     let do_time = ccx.sess.opts.stats;
     let start = if do_time { time::get_time() }
                 else { {sec: 0u32, usec: 0u32} };
     trans_closure(ccx, path, decl, body, llfndecl, ty_self,
-                  tps_bounds, param_substs, id, {|fcx|
+                  tps_bounds, param_substs, id, maybe_self_id, {|fcx|
         if ccx.sess.opts.extra_debuginfo {
             debuginfo::create_function(fcx);
         }
@@ -4058,7 +4100,7 @@ fn trans_res_ctor(ccx: crate_ctxt, path: path, dtor: ast::fn_decl,
                   param_substs: option<param_substs>, llfndecl: ValueRef) {
     // Create a function for the constructor
     let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, ctor_id,
-                               param_substs, none);
+                               none, param_substs, none);
     create_llargs_for_fn_args(fcx, no_self, dtor.inputs, tps_bounds);
     let bcx = top_scope_block(fcx, none), lltop = bcx.llbb;
     let fty = node_id_type(bcx, ctor_id);
@@ -4100,7 +4142,7 @@ fn trans_enum_variant(ccx: crate_ctxt, enum_id: ast::node_id,
                      ident: "arg" + uint::to_str(i, 10u),
                      id: varg.id}];
     }
-    let fcx = new_fn_ctxt_w_id(ccx, [], llfndecl, variant.node.id,
+    let fcx = new_fn_ctxt_w_id(ccx, [], llfndecl, variant.node.id, none,
                                param_substs, none);
     create_llargs_for_fn_args(fcx, no_self, fn_args,
                               param_bounds(ccx, ty_params));
@@ -4261,7 +4303,7 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) {
         if decl.purity != ast::crust_fn  {
             trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
                      llfndecl, no_self, param_bounds(ccx, tps),
-                     none, item.id);
+                     none, item.id, none);
         } else {
             native::trans_crust_fn(ccx, *path + [path_name(item.ident)],
                                    decl, body, llfndecl, item.id);
@@ -4280,7 +4322,7 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) {
           some(lldtor_decl) {
             trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
                      lldtor_decl, no_self, param_bounds(ccx, tps),
-                     none, dtor_id);
+                     none, dtor_id, none);
           }
           _ {
             ccx.sess.span_fatal(item.span, "unbound dtor in trans_item");
@@ -4311,6 +4353,83 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) {
         };
         native::trans_native_mod(ccx, native_mod, abi);
       }
+      ast::item_class(tps, items, ctor) {
+          alt ccx.item_ids.find(ctor.node.id) {
+             some(llctor_decl) {
+             // Translate the ctor
+             // First, add a preamble that
+             // generates a new name, obj:
+             // let obj = { ... } (uninit record fields)
+                 let sess = ccx.sess;
+                 let rslt_path_ = {global: false,
+                                   idents: ["obj"],
+                                   types: []}; // ??
+                 let rslt_path = @{node: rslt_path_,
+                                  span: ctor.node.body.span};
+                 let rslt_id : ast::node_id = sess.next_node_id();
+                 let rslt_pat : @ast::pat =
+                     @{id: sess.next_node_id(),
+                       node: ast::pat_ident(rslt_path, none),
+                       span: ctor.node.body.span};
+                 // Set up obj's type
+                 let rslt_ast_ty : @ast::ty = @{node: ast::ty_infer,
+                                    span: ctor.node.body.span};
+                 // kludgy
+                 let ty_args = [], i = 0u;
+                 for tp in tps {
+                   ty_args += [ty::mk_param(ccx.tcx, i,
+                                            local_def(tps[i].id))];
+                 }
+                 let rslt_ty =  ty::mk_class(ccx.tcx,
+                                                  local_def(item.id),
+                                             ty_args);
+                 // Set up a local for obj
+                 let rslt_loc_ : ast::local_ = {is_mutbl: true,
+                                  ty: rslt_ast_ty, // ???
+                                  pat: rslt_pat,
+                                  init: none::<ast::initializer>,
+                                  id: rslt_id};
+                 // Register a type for obj
+                 smallintmap::insert(*ccx.tcx.node_types,
+                                     rslt_loc_.id as uint, rslt_ty);
+                 // Create the decl statement that initializers obj
+                 let rslt_loc : @ast::local =
+                     @{node: rslt_loc_, span: ctor.node.body.span};
+                 let rslt_decl_ : ast::decl_ = ast::decl_local([rslt_loc]);
+                 let rslt_decl : @ast::decl
+                     = @{node: rslt_decl_, span: ctor.node.body.span};
+                 let prologue : @ast::stmt = @{node: ast::stmt_decl(rslt_decl,
+                                                     sess.next_node_id()),
+                                              span: ctor.node.body.span};
+                 let rslt_node_id = sess.next_node_id();
+                 ccx.tcx.def_map.insert(rslt_node_id,
+                          ast::def_local(rslt_loc_.id, true));
+                 // And give the statement a type
+                 smallintmap::insert(*ccx.tcx.node_types,
+                                     rslt_node_id as uint, rslt_ty);
+                 // The result expression of the constructor is now a
+                 // reference to obj
+                 let rslt_expr : @ast::expr =
+                     @{id: rslt_node_id,
+                       node: ast::expr_path(rslt_path),
+                       span: ctor.node.body.span};
+                 let ctor_body_new : ast::blk_ = {stmts: [prologue]
+                                      + ctor.node.body.node.stmts,
+                                       expr: some(rslt_expr)
+                                     with ctor.node.body.node};
+                 let ctor_body__ : ast::blk = {node: ctor_body_new
+                                                with ctor.node.body};
+             trans_fn(ccx, *path + [path_name(item.ident)], ctor.node.dec,
+                      ctor_body__, llctor_decl, no_self,
+                      param_bounds(ccx, tps), none, ctor.node.id,
+                      some(rslt_expr));
+             // TODO: translate methods!
+             }
+             _ {
+               ccx.sess.span_bug(item.span, "unbound ctor in trans_item");
+             }
+          }
+      }
       _ {/* fall through */ }
     }
 }
@@ -4348,7 +4467,7 @@ fn trans_inlined_items(ccx: crate_ctxt, inline_map: inline_map) {
                 let llfndecl = ccx.item_ids.get(m.id);
                 trans_fn(ccx, m_path, m.decl, m.body,
                          llfndecl, impl_self(impl_ty), m_bounds,
-                         none, m.id);
+                         none, m.id, none);
             }
           }
         }
@@ -4605,6 +4724,12 @@ fn collect_item(ccx: crate_ctxt, abi: @mutable option<ast::native_abi>,
             }
         }
       }
+      ast::item_class(tps,_,ctor) {
+          // Register the ctor
+          let t = ty::node_id_to_type(ccx.tcx, ctor.node.id);
+          register_fn_full(ccx, i.span, my_path, "ctor",
+                           param_bounds(ccx, tps), ctor.node.id, t);
+      }
       _ { }
     }
 }
diff --git a/src/rustc/middle/trans/closure.rs b/src/rustc/middle/trans/closure.rs
index 4cd9eef01e3..6f85204ffe0 100644
--- a/src/rustc/middle/trans/closure.rs
+++ b/src/rustc/middle/trans/closure.rs
@@ -470,7 +470,7 @@ fn trans_expr_fn(bcx: block,
             ccx.tcx, id, proto, cap_clause);
         let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, ck, id);
         trans_closure(ccx, sub_path, decl, body, llfn, no_self, [],
-                      bcx.fcx.param_substs, id, {|fcx|
+                      bcx.fcx.param_substs, id, none, {|fcx|
             load_environment(bcx, fcx, cdata_ty, cap_vars, ck);
         });
         llbox
@@ -482,7 +482,7 @@ fn trans_expr_fn(bcx: block,
       ast::proto_uniq { trans_closure_env(ty::ck_uniq) }
       ast::proto_bare {
         trans_closure(ccx, sub_path, decl, body, llfn, no_self, [], none,
-                      id, {|_fcx|});
+                      id, none, {|_fcx|});
         C_null(T_opaque_box_ptr(ccx))
       }
     };
diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs
index 4bc264e4098..7b42ca61699 100644
--- a/src/rustc/middle/trans/common.rs
+++ b/src/rustc/middle/trans/common.rs
@@ -196,6 +196,10 @@ type fn_ctxt = @{
     // a user-defined function.
     id: ast::node_id,
 
+    // The expr for the "self" object (only if this function corresponds
+    // to a class constructor function)
+    self_id: option<@ast::expr>,
+
     // If this function is being monomorphized, this contains the type
     // substitutions used.
     param_substs: option<param_substs>,
diff --git a/src/rustc/middle/trans/impl.rs b/src/rustc/middle/trans/impl.rs
index b3660e3f672..e713a9979e4 100644
--- a/src/rustc/middle/trans/impl.rs
+++ b/src/rustc/middle/trans/impl.rs
@@ -52,7 +52,7 @@ fn trans_impl(ccx: crate_ctxt, path: path, name: ast::ident,
             let m_bounds = param_bounds(ccx, tps + m.tps);
             trans_fn(ccx, sub_path + [path_name(m.ident)], m.decl, m.body,
                      llfn, impl_self(ty::node_id_to_type(ccx.tcx, id)),
-                     m_bounds, none, m.id);
+                     m_bounds, none, m.id, none);
           }
           _ {
             ccx.sess.bug("Unbound id in trans_impl");
diff --git a/src/rustc/middle/trans/native.rs b/src/rustc/middle/trans/native.rs
index 22791047ef9..9753ef6bd33 100644
--- a/src/rustc/middle/trans/native.rs
+++ b/src/rustc/middle/trans/native.rs
@@ -274,7 +274,8 @@ fn trans_crust_fn(ccx: crate_ctxt, path: ast_map::path, decl: ast::fn_decl,
             ccx, path + [ast_map::path_name("__rust_abi")]);
         let llty = type_of_fn_from_ty(ccx, t, []);
         let llfndecl = decl_internal_cdecl_fn(ccx.llmod, ps, llty);
-        trans_fn(ccx, path, decl, body, llfndecl, no_self, [], none, id);
+        trans_fn(ccx, path, decl, body, llfndecl, no_self, [], none, id,
+                 none);
         ret llfndecl;
     }
 
diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs
index f7095be55ff..e613fdf3cd9 100644
--- a/src/rustc/middle/trans/type_of.rs
+++ b/src/rustc/middle/trans/type_of.rs
@@ -2,6 +2,9 @@ import common::*;
 import lib::llvm::{TypeRef};
 import syntax::ast;
 import lib::llvm::llvm;
+import driver::session::session;
+
+import ty::*;
 
 fn type_of_explicit_args(cx: crate_ctxt, inputs: [ty::arg]) -> [TypeRef] {
     vec::map(inputs) {|arg|
@@ -102,8 +105,25 @@ 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) }
-
-      _ { fail "type_of not implemented for this kind of type"; }
+      ty::ty_class(did, _) {
+        let tys: [TypeRef] = [];
+        // TODO: only handles local classes
+        let cls_items = lookup_class_items(cx.tcx, did);
+        for ci in cls_items {
+            // only instance vars are record fields at runtime
+            alt ci.node.decl {
+                ast::instance_var(_,_,_,_) {
+                  let fty = type_of(cx, class_item_type(cx.tcx, ci));
+                  tys += [fty];
+                }
+                _ {}
+            }
+        }
+        T_struct(tys)
+      }
+      ty::ty_self(_) { cx.tcx.sess.unimpl("type_of: ty_self \
+                         not implemented"); }
+      ty::ty_var(_) { cx.tcx.sess.bug("type_of shouldn't see a ty_var"); }
     };
     cx.lltypes.insert(t, llty);
     ret llty;
diff --git a/src/rustc/middle/tstate/pre_post_conditions.rs b/src/rustc/middle/tstate/pre_post_conditions.rs
index 8a83f7dd7b4..6c80234a54b 100644
--- a/src/rustc/middle/tstate/pre_post_conditions.rs
+++ b/src/rustc/middle/tstate/pre_post_conditions.rs
@@ -56,7 +56,7 @@ fn find_pre_post_item(ccx: crate_ctxt, i: item) {
              ccx: ccx};
         find_pre_post_fn(fcx, body);
       }
-      item_class(_,_,_,_,_) {
+      item_class(_,_,_) {
           fail "find_pre_post_item: implement item_class";
       }
       item_impl(_, _, _, ms) { for m in ms { find_pre_post_method(ccx, m); } }
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index a7e218e581b..6895630f879 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -18,6 +18,8 @@ export arg;
 export args_eq;
 export ast_constr_to_constr;
 export block_ty;
+export class_item_type;
+export class_items_as_fields;
 export constr;
 export constr_general;
 export constr_table;
@@ -37,6 +39,7 @@ export fm_general;
 export get_element_type;
 export is_binopable;
 export is_pred_ty;
+export lookup_class_items;
 export lookup_item_type;
 export method;
 export method_idx;
@@ -628,7 +631,7 @@ fn type_is_bool(ty: t) -> bool { get(ty).struct == ty_bool }
 
 fn type_is_structural(ty: t) -> bool {
     alt get(ty).struct {
-      ty_rec(_) | ty_tup(_) | ty_enum(_, _) | ty_fn(_) |
+      ty_rec(_) | ty_class(_,_) | ty_tup(_) | ty_enum(_, _) | ty_fn(_) |
       ty_iface(_, _) | ty_res(_, _, _) { true }
       _ { false }
     }
@@ -1228,7 +1231,10 @@ fn constrs_eq(cs: [@constr], ds: [@constr]) -> bool {
 }
 
 fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t {
-    smallintmap::get(*cx.node_types, id as uint)
+    alt smallintmap::find(*cx.node_types, id as uint) {
+       some(t) { t }
+       none { cx.sess.bug(#fmt("node_id_to_type: unbound node ID %?", id)); }
+    }
 }
 
 fn node_id_to_type_params(cx: ctxt, id: ast::node_id) -> [t] {
@@ -2292,6 +2298,54 @@ fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_bounds_and_ty {
     }
 }
 
+// Look up the list of items for a given class (in the item map).
+// Fails if the id is not bound to a class.
+fn lookup_class_items(cx: ctxt, did: ast::def_id) -> [@class_item] {
+    alt cx.items.find(did.node) {
+       some(ast_map::node_item(i,_)) {
+           alt i.node {
+              ast::item_class(_, items, _) {
+                  items
+              }
+              _ { cx.sess.bug("class ID bound to non-class"); }
+           }
+       }
+       _ { cx.sess.bug("class ID not bound to an item"); }
+    }
+}
+
+// Return a list of fields corresponding to the class's items
+// (as if the class was a record). trans uses this
+fn class_items_as_fields(cx:ctxt, did: ast::def_id) -> [field] {
+    let rslt = [];
+    for ci in lookup_class_items(cx, did) {
+       rslt += [alt ci.node.decl {
+         instance_var(i, _, _, id) {
+             // consider all instance vars mutable, because the
+             // constructor may mutate all vars
+             {ident: i, mt: {ty: node_id_to_type(cx, id),
+                         mutbl: m_mutbl}}
+         }
+         class_method(it) {
+             {ident:it.ident, mt: {ty: node_id_to_type(cx, it.id),
+                               mutbl: m_const}}
+         }
+       }];
+    }
+    rslt
+}
+
+// Looks up the type for a given class item. Must be called
+// post-typechecking.
+fn class_item_type(cx: ctxt, ci: @ast::class_item) -> t {
+    alt ci.node.decl {
+       ast::instance_var(_,_,_,id) { node_id_to_type(cx, id) }
+       // TODO: only works for local classes
+       ast::class_method(it) { lookup_item_type(cx,
+                                 ast_util::local_def(it.id)).ty }
+    }
+}
+
 fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool {
     const tycat_other: int = 0;
     const tycat_bool: int = 1;
diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs
index e1c56b9fc54..57d8fc29560 100644
--- a/src/rustc/middle/typeck.rs
+++ b/src/rustc/middle/typeck.rs
@@ -10,7 +10,7 @@ import pat_util::*;
 import middle::ty;
 import middle::ty::{node_id_to_type, arg, block_ty,
                     expr_ty, field, node_type_table, mk_nil,
-                    ty_param_bounds_and_ty};
+                    ty_param_bounds_and_ty, lookup_class_items};
 import util::ppaux::ty_to_str;
 import middle::ty::unify::{ures_ok, ures_err, fix_ok, fix_err};
 import std::smallintmap;
@@ -375,7 +375,7 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
           ast::def_class(class_id) {
               alt tcx.items.find(class_id.node) {
                  some(ast_map::node_item(
-                  @{node: ast::item_class(tps, _, _, _, _), _}, _)) {
+                  @{node: ast::item_class(tps, _, _), _}, _)) {
                      if vec::len(tps) != vec::len(path.node.types) {
                         tcx.sess.span_err(ast_ty.span, "incorrect number of \
                            type parameters to object type");
@@ -492,7 +492,7 @@ fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item)
         tcx.tcache.insert(local_def(it.id), tpt);
         ret tpt;
       }
-      ast::item_class(tps,_,_,_,_) {
+      ast::item_class(tps,_,_) {
           let {bounds,params} = mk_ty_params(tcx, tps);
           let t = ty::mk_class(tcx, local_def(it.id), params);
           let tpt = {bounds: bounds, ty: t};
@@ -944,7 +944,7 @@ mod collect {
             write_ty(tcx, it.id, tpt.ty);
             ensure_iface_methods(tcx, it.id);
           }
-          ast::item_class(tps, members, ctor_id, ctor_decl, ctor_block) {
+          ast::item_class(tps, members, ctor) {
               // Write the class type
               let {bounds,params} = mk_ty_params(tcx, tps);
               let class_ty = ty::mk_class(tcx, local_def(it.id), params);
@@ -954,9 +954,9 @@ mod collect {
               // Write the ctor type
               let t_ctor = ty::mk_fn(tcx,
                                      ty_of_fn_decl(tcx, m_collect,
-                                             ast::proto_any, ctor_decl));
-              write_ty(tcx, ctor_id, t_ctor);
-              tcx.tcache.insert(local_def(ctor_id),
+                                             ast::proto_any, ctor.node.dec));
+              write_ty(tcx, ctor.node.id, t_ctor);
+              tcx.tcache.insert(local_def(ctor.node.id),
                                    {bounds: bounds, ty: t_ctor});
               /* FIXME: check for proper public/privateness */
               // Write the type of each of the members
@@ -2549,19 +2549,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
               // For now, this code assumes the class is defined in the local
               // crate
               // FIXME: handle field references to classes in external crate
-              let err = "Class ID is not bound to a class";
-              let field_ty = alt fcx.ccx.tcx.items.find(base_id.node) {
-                      some(ast_map::node_item(i,_)) {
-                          alt i.node {
-                             ast::item_class(_, items, _, _, _) {
-                                 lookup_field_ty(fcx.ccx.tcx, items, field,
-                                    expr.span)
-                             }
-                             _ { fcx.ccx.tcx.sess.span_bug(expr.span, err); }
-                          }
-                      }
-                      _ { fcx.ccx.tcx.sess.span_bug(expr.span, err); }
-              };
+              let cls_items = lookup_class_items(tcx, base_id);
+              let field_ty = lookup_field_ty(fcx.ccx.tcx, cls_items, field,
+                                             expr.span);
               // (2) look up what field's type is, and return it
               // FIXME: actually instantiate any type params
               write_ty(tcx, id, field_ty);
@@ -3034,14 +3024,14 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
         for m in ms { check_method(ccx, m); }
         vec::pop(ccx.self_infos);
       }
-      ast::item_class(tps, members, ctor_id, ctor_decl, ctor_body) {
+      ast::item_class(tps, members, ctor) {
           let cid = some(it.id);
           let members_info = class_types(ccx, members);
           let class_ccx = @{enclosing_class_id:cid,
                             enclosing_class:members_info with *ccx};
           // typecheck the ctor
-          check_fn(class_ccx, ast::proto_bare, ctor_decl, ctor_body, ctor_id,
-                   none);
+          check_fn(class_ccx, ast::proto_bare, ctor.node.dec,
+                   ctor.node.body, ctor.node.id, none);
           // typecheck the members
           for m in members { check_class_member(class_ccx, m.node.decl); }
       }
diff --git a/src/rustc/syntax/ast.rs b/src/rustc/syntax/ast.rs
index eea47191eef..2f0c4bf7839 100644
--- a/src/rustc/syntax/ast.rs
+++ b/src/rustc/syntax/ast.rs
@@ -9,9 +9,6 @@ type ident = str;
 // Functions may or may not have names.
 type fn_ident = option<ident>;
 
-// FIXME: with typestate constraint, could say
-// idents and types are the same length, and are
-// non-empty
 type path_ = {global: bool, idents: [ident], types: [@ty]};
 
 type path = spanned<path_>;
@@ -499,9 +496,7 @@ enum item_ {
     item_class([ty_param], /* ty params for class */
                [@class_item], /* methods, etc. */
                              /* (not including ctor) */
-               node_id,  /* ctor id */
-               fn_decl, /* ctor decl */
-               blk /* ctor body */
+               class_ctor
                ),
     item_iface([ty_param], [ty_method]),
     item_impl([ty_param], option<@ty> /* iface */,
@@ -523,6 +518,11 @@ enum class_mutability { class_mutable, class_immutable }
 
 enum privacy { priv, pub }
 
+type class_ctor = spanned<class_ctor_>;
+type class_ctor_ = {id: node_id,
+                    dec: fn_decl,
+                    body: blk};
+
 type native_item =
     {ident: ident,
      attrs: [attribute],
diff --git a/src/rustc/syntax/fold.rs b/src/rustc/syntax/fold.rs
index 7ceae548769..d8088e39cb6 100644
--- a/src/rustc/syntax/fold.rs
+++ b/src/rustc/syntax/fold.rs
@@ -269,12 +269,14 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
             item_enum(vec::map(variants, fld.fold_variant),
                       fold_ty_params(typms, fld))
           }
-          item_class(typms, items, id, ctor_decl, ctor_body) {
-              item_class(fold_ty_params(typms, fld),
+          item_class(typms, items, ctor) {
+              let ctor_body = fld.fold_block(ctor.node.body);
+              let ctor_decl = fold_fn_decl(ctor.node.dec, fld);
+              item_class(typms,
                          vec::map(items, fld.fold_class_item),
-                         id,
-                         fold_fn_decl(ctor_decl, fld),
-                         fld.fold_block(ctor_body))
+                         {node: {body: ctor_body,
+                                     dec: ctor_decl with ctor.node}
+                             with ctor})
           }
           item_impl(tps, ifce, ty, methods) {
             item_impl(tps, option::map(ifce, fld.fold_ty), fld.fold_ty(ty),
diff --git a/src/rustc/syntax/parse/parser.rs b/src/rustc/syntax/parse/parser.rs
index 5837baf1ff9..e8df2f86305 100644
--- a/src/rustc/syntax/parse/parser.rs
+++ b/src/rustc/syntax/parse/parser.rs
@@ -1590,8 +1590,9 @@ fn parse_let(p: parser) -> @ast::decl {
     ret @spanned(lo, p.last_span.hi, ast::decl_local(locals));
 }
 
-fn parse_instance_var(p:parser) -> ast::class_member {
+fn parse_instance_var(p:parser) -> (ast::class_member, codemap::span) {
     let is_mutbl = ast::class_immutable;
+    let lo = p.span.lo;
     expect_word(p, "let");
     if eat_word(p, "mut") || eat_word(p, "mutable") {
             is_mutbl = ast::class_mutable;
@@ -1602,7 +1603,8 @@ fn parse_instance_var(p:parser) -> ast::class_member {
     let name = parse_ident(p);
     expect(p, token::COLON);
     let ty = parse_ty(p, false);
-    ret ast::instance_var(name, ty, is_mutbl, p.get_id());
+    ret (ast::instance_var(name, ty, is_mutbl, p.get_id()),
+         ast_util::mk_sp(lo, p.last_span.hi));
 }
 
 fn parse_stmt(p: parser, first_item_attrs: [ast::attribute]) -> @ast::stmt {
@@ -1976,27 +1978,33 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
     expect(p, token::LBRACE);
     let items: [@ast::class_item] = [];
     let ctor_id = p.get_id();
-    let the_ctor : option<(ast::fn_decl, ast::blk)> = none;
+    let the_ctor : option<(ast::fn_decl, ast::blk, codemap::span)> = none;
     while p.token != token::RBRACE {
         alt parse_class_item(p, class_path) {
-            ctor_decl(a_fn_decl, blk) {
-                the_ctor = some((a_fn_decl, blk));
+           ctor_decl(a_fn_decl, blk, s) {
+               the_ctor = some((a_fn_decl, blk, s));
             }
-            plain_decl(a_decl) {
+           plain_decl(a_decl, s) {
                 items += [@{node: {privacy: ast::pub, decl: a_decl},
-                            span: p.last_span}];
+                            span: s}];
             }
             priv_decls(some_decls) {
-                items += vec::map(some_decls, {|d|
+                items += vec::map(some_decls, {|p|
+                            let (d, s) = p;
                             @{node: {privacy: ast::priv, decl: d},
-                                span: p.last_span}});
+                                span: s}});
             }
        }
     }
     p.bump();
     alt the_ctor {
-       some((ct_d, ct_b)) { ret mk_item(p, lo, p.last_span.hi, class_name,
-         ast::item_class(ty_params, items, ctor_id, ct_d, ct_b), attrs); }
+      some((ct_d, ct_b, ct_s)) { ret mk_item(p, lo, p.last_span.hi,
+                                             class_name,
+         ast::item_class(ty_params, items,
+                         {node: {id: ctor_id,
+                                 dec: ct_d,
+                                 body: ct_b},
+                          span: ct_s}), attrs); }
        /*
          Is it strange for the parser to check this?
        */
@@ -2007,16 +2015,17 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
 // lets us identify the constructor declaration at
 // parse time
 // we don't really want just the fn_decl...
-enum class_contents { ctor_decl(ast::fn_decl, ast::blk),
+enum class_contents { ctor_decl(ast::fn_decl, ast::blk, codemap::span),
                       // assumed to be public
-                      plain_decl(ast::class_member),
+                      plain_decl(ast::class_member, codemap::span),
                       // contents of a priv section --
                       // parse_class_item ensures that
                       // none of these are a ctor decl
-                      priv_decls([ast::class_member])}
+                      priv_decls([(ast::class_member, codemap::span)])}
 
     fn parse_class_item(p:parser, class_name:@ast::path) -> class_contents {
     if eat_word(p, "new") {
+        let lo = p.last_span.lo;
         // Can ctors have attrs?
             // result type is always the type of the class
         let decl_ = parse_fn_decl(p, ast::impure_fn);
@@ -2024,7 +2033,7 @@ enum class_contents { ctor_decl(ast::fn_decl, ast::blk),
                                   span: decl_.output.span}
                     with decl_};
         let body = parse_block(p);
-        ret ctor_decl(decl, body);
+        ret ctor_decl(decl, body, ast_util::mk_sp(lo, p.last_span.hi));
     }
     // FIXME: refactor
     else if eat_word(p, "priv") {
@@ -2033,7 +2042,7 @@ enum class_contents { ctor_decl(ast::fn_decl, ast::blk),
             while p.token != token::RBRACE {
                alt parse_item(p, []) {
                  some(i) {
-                     results += [ast::class_method(i)];
+                     results += [(ast::class_method(i), i.span)];
                  }
                  _ {
                      let a_var = parse_instance_var(p);
@@ -2049,12 +2058,12 @@ enum class_contents { ctor_decl(ast::fn_decl, ast::blk),
         // Probably need to parse attrs
         alt parse_item(p, []) {
          some(i) {
-             ret plain_decl(ast::class_method(i));
+             ret plain_decl(ast::class_method(i), i.span);
          }
          _ {
-             let a_var = parse_instance_var(p);
+             let (a_var, a_span) = parse_instance_var(p);
              expect(p, token::SEMI);
-             ret plain_decl(a_var);
+             ret plain_decl(a_var, a_span);
          }
         }
     }
diff --git a/src/rustc/syntax/print/pprust.rs b/src/rustc/syntax/print/pprust.rs
index 5f92b5d5beb..d74d5d92c5f 100644
--- a/src/rustc/syntax/print/pprust.rs
+++ b/src/rustc/syntax/print/pprust.rs
@@ -471,22 +471,24 @@ fn print_item(s: ps, &&item: @ast::item) {
             bclose(s, item.span);
         }
       }
-      ast::item_class(tps,items,_,ctor_decl,ctor_body) {
+      ast::item_class(tps,items,ctor) {
           head(s, "class");
           word_nbsp(s, item.ident);
           print_type_params(s, tps);
           bopen(s);
           hardbreak_if_not_bol(s);
+          maybe_print_comment(s, ctor.span.lo);
           head(s, "new");
-          print_fn_args_and_ret(s, ctor_decl);
+          print_fn_args_and_ret(s, ctor.node.dec);
           space(s.s);
-          print_block(s, ctor_body);
+          print_block(s, ctor.node.body);
           for ci in items {
                   /*
                      FIXME: collect all private items and print them
                      in a single "priv" section
                    */
              hardbreak_if_not_bol(s);
+             maybe_print_comment(s, ci.span.lo);
              alt ci.node.privacy {
                 ast::priv {
                     head(s, "priv");
@@ -516,6 +518,7 @@ fn print_item(s: ps, &&item: @ast::item) {
                  _ {}
              }
           }
+          bclose(s, item.span);
        }
       ast::item_impl(tps, ifce, ty, methods) {
         head(s, "impl");
diff --git a/src/rustc/syntax/visit.rs b/src/rustc/syntax/visit.rs
index 55958abd7af..dd1a53942fa 100644
--- a/src/rustc/syntax/visit.rs
+++ b/src/rustc/syntax/visit.rs
@@ -133,13 +133,13 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
             visit_method_helper(m, e, v)
         }
       }
-      item_class(tps, members, _, ctor_decl, ctor_blk) {
+      item_class(tps, members, ctor) {
           v.visit_ty_params(tps, e, v);
           for m in members {
              v.visit_class_item(m.span, m.node.privacy, m.node.decl, e, v);
           }
-          visit_fn_decl(ctor_decl, e, v);
-          v.visit_block(ctor_blk, e, v);
+          visit_fn_decl(ctor.node.dec, e, v);
+          v.visit_block(ctor.node.body, e, v);
       }
       item_iface(tps, methods) {
         v.visit_ty_params(tps, e, v);