about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs304
-rw-r--r--src/libsyntax/ast_map.rs20
-rw-r--r--src/libsyntax/ast_util.rs19
-rw-r--r--src/libsyntax/attr.rs4
-rw-r--r--src/libsyntax/codemap.rs68
-rw-r--r--src/libsyntax/diagnostic.rs21
-rw-r--r--src/libsyntax/ext/auto_serialize.rs1731
-rw-r--r--src/libsyntax/ext/auto_serialize2.rs1025
-rw-r--r--src/libsyntax/ext/base.rs27
-rw-r--r--src/libsyntax/ext/env.rs4
-rw-r--r--src/libsyntax/ext/fmt.rs16
-rw-r--r--src/libsyntax/ext/pipes.rs4
-rw-r--r--src/libsyntax/ext/pipes/ast_builder.rs60
-rw-r--r--src/libsyntax/ext/pipes/check.rs4
-rw-r--r--src/libsyntax/ext/pipes/parse_proto.rs2
-rw-r--r--src/libsyntax/ext/pipes/pipec.rs8
-rw-r--r--src/libsyntax/ext/pipes/proto.rs12
-rw-r--r--src/libsyntax/ext/qquote.rs22
-rw-r--r--src/libsyntax/ext/simplext.rs4
-rw-r--r--src/libsyntax/ext/trace_macros.rs6
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs14
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs6
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs9
-rw-r--r--src/libsyntax/fold.rs28
-rw-r--r--src/libsyntax/parse.rs24
-rw-r--r--src/libsyntax/parse/attr.rs2
-rw-r--r--src/libsyntax/parse/common.rs94
-rw-r--r--src/libsyntax/parse/eval.rs2
-rw-r--r--src/libsyntax/parse/lexer.rs26
-rw-r--r--src/libsyntax/parse/obsolete.rs75
-rw-r--r--src/libsyntax/parse/parser.rs302
-rw-r--r--src/libsyntax/parse/prec.rs4
-rw-r--r--src/libsyntax/parse/token.rs90
-rw-r--r--src/libsyntax/print/pprust.rs81
-rw-r--r--src/libsyntax/syntax.rc8
-rw-r--r--src/libsyntax/util/interner.rs10
-rw-r--r--src/libsyntax/visit.rs52
37 files changed, 1692 insertions, 2496 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index a50189cf598..a3d2fe96b5d 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1,33 +1,14 @@
 // The Rust abstract syntax tree.
 
+use std::serialization::{Serializable,
+                         Deserializable,
+                         Serializer,
+                         Deserializer};
 use codemap::{span, filename};
-use std::serialization::{Serializer,
-                            Deserializer,
-                            serialize_Option,
-                            deserialize_Option,
-                            serialize_uint,
-                            deserialize_uint,
-                            serialize_int,
-                            deserialize_int,
-                            serialize_i64,
-                            deserialize_i64,
-                            serialize_u64,
-                            deserialize_u64,
-                            serialize_str,
-                            deserialize_str,
-                            serialize_bool,
-                            deserialize_bool};
 use parse::token;
 
-/* Note #1972 -- spans are serialized but not deserialized */
-fn serialize_span<S>(_s: S, _v: span) {
-}
-
-fn deserialize_span<D>(_d: D) -> span {
-    ast_util::dummy_sp()
-}
-
 #[auto_serialize]
+#[auto_deserialize]
 type spanned<T> = {node: T, span: span};
 
 
@@ -42,25 +23,62 @@ macro_rules! interner_key (
 // implemented.
 struct ident { repr: uint }
 
-fn serialize_ident<S: Serializer>(s: S, i: ident) {
-    let intr = match unsafe{
-        task::local_data::local_data_get(interner_key!())
-    } {
-        None => fail ~"serialization: TLS interner not set up",
-        Some(intr) => intr
-    };
+#[cfg(stage0)]
+impl ident: Serializable {
+    fn serialize<S: Serializer>(&self, s: &S) {
+        let intr = match unsafe {
+            task::local_data::local_data_get(interner_key!())
+        } {
+            None => fail ~"serialization: TLS interner not set up",
+            Some(intr) => intr
+        };
+
+        s.emit_owned_str(*(*intr).get(*self));
+    }
+}
+
+#[cfg(stage0)]
+impl ident: Deserializable {
+    static fn deserialize<D: Deserializer>(d: &D) -> ident {
+        let intr = match unsafe {
+            task::local_data::local_data_get(interner_key!())
+        } {
+            None => fail ~"deserialization: TLS interner not set up",
+            Some(intr) => intr
+        };
 
-    s.emit_str(*(*intr).get(i));
+        (*intr).intern(@d.read_owned_str())
+    }
 }
-fn deserialize_ident<D: Deserializer>(d: D) -> ident  {
-    let intr = match unsafe{
-        task::local_data::local_data_get(interner_key!())
-    } {
-        None => fail ~"deserialization: TLS interner not set up",
-        Some(intr) => intr
-    };
 
-    (*intr).intern(@d.read_str())
+#[cfg(stage1)]
+#[cfg(stage2)]
+impl<S: Serializer> ident: Serializable<S> {
+    fn serialize(&self, s: &S) {
+        let intr = match unsafe {
+            task::local_data::local_data_get(interner_key!())
+        } {
+            None => fail ~"serialization: TLS interner not set up",
+            Some(intr) => intr
+        };
+
+        s.emit_owned_str(*(*intr).get(*self));
+    }
+}
+
+#[cfg(stage1)]
+#[cfg(stage2)]
+impl<D: Deserializer> ident: Deserializable<D> {
+    static fn deserialize(d: &D) -> ident {
+        let intr = match unsafe {
+            task::local_data::local_data_get(interner_key!())
+        } {
+            None => fail ~"deserialization: TLS interner not set up",
+            Some(intr) => intr
+        };
+
+        (*intr).intern(@d.read_owned_str())
+    }
 }
 
 impl ident: cmp::Eq {
@@ -75,23 +93,22 @@ impl ident: to_bytes::IterBytes {
 }
 
 // Functions may or may not have names.
-#[auto_serialize]
 type fn_ident = Option<ident>;
 
 #[auto_serialize]
+#[auto_deserialize]
 type path = {span: span,
              global: bool,
              idents: ~[ident],
              rp: Option<@region>,
-             types: ~[@ty]};
+             types: ~[@Ty]};
 
-#[auto_serialize]
 type crate_num = int;
 
-#[auto_serialize]
 type node_id = int;
 
 #[auto_serialize]
+#[auto_deserialize]
 type def_id = {crate: crate_num, node: node_id};
 
 impl def_id : cmp::Eq {
@@ -105,21 +122,24 @@ const local_crate: crate_num = 0;
 const crate_node_id: node_id = 0;
 
 #[auto_serialize]
-enum ty_param_bound {
-    bound_copy,
-    bound_send,
-    bound_const,
-    bound_owned,
-    bound_trait(@ty),
-}
+#[auto_deserialize]
+// The AST represents all type param bounds as types.
+// typeck::collect::compute_bounds matches these against
+// the "special" built-in traits (see middle::lang_items) and
+// detects Copy, Send, Owned, and Const.
+enum ty_param_bound = @Ty;
 
 #[auto_serialize]
+#[auto_deserialize]
 type ty_param = {ident: ident, id: node_id, bounds: @~[ty_param_bound]};
 
 #[auto_serialize]
+#[auto_deserialize]
 enum def {
     def_fn(def_id, purity),
-    def_static_method(def_id, purity),
+    def_static_method(/* method */ def_id,
+                      /* trait */  Option<def_id>,
+                      purity),
     def_self(node_id),
     def_mod(def_id),
     def_foreign_mod(def_id),
@@ -136,7 +156,7 @@ enum def {
               @def,     // closed over def
               node_id,  // expr node that creates the closure
               node_id), // id for the block/body of the closure expr
-    def_class(def_id, bool /* has constructor */),
+    def_class(def_id),
     def_typaram_binder(node_id), /* class, impl or trait that has ty params */
     def_region(node_id),
     def_label(node_id)
@@ -151,9 +171,10 @@ impl def : cmp::Eq {
                     _ => false
                 }
             }
-            def_static_method(e0a, e1a) => {
+            def_static_method(e0a, e1a, e2a) => {
                 match (*other) {
-                    def_static_method(e0b, e1b) => e0a == e0b && e1a == e1b,
+                    def_static_method(e0b, e1b, e2b) =>
+                    e0a == e0b && e1a == e1b && e2a == e2b,
                     _ => false
                 }
             }
@@ -236,9 +257,9 @@ impl def : cmp::Eq {
                     _ => false
                 }
             }
-            def_class(e0a, e1a) => {
+            def_class(e0a) => {
                 match (*other) {
-                    def_class(e0b, e1b) => e0a == e0b && e1a == e1b,
+                    def_class(e0b) => e0a == e0b,
                     _ => false
                 }
             }
@@ -293,20 +314,20 @@ enum crate_directive_ {
 
 type crate_directive = spanned<crate_directive_>;
 
-#[auto_serialize]
 type meta_item = spanned<meta_item_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 enum meta_item_ {
     meta_word(~str),
     meta_list(~str, ~[@meta_item]),
     meta_name_value(~str, lit),
 }
 
-#[auto_serialize]
 type blk = spanned<blk_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 type blk_ = {view_items: ~[@view_item],
              stmts: ~[@stmt],
              expr: Option<@expr>,
@@ -314,12 +335,15 @@ type blk_ = {view_items: ~[@view_item],
              rules: blk_check_mode};
 
 #[auto_serialize]
+#[auto_deserialize]
 type pat = {id: node_id, node: pat_, span: span};
 
 #[auto_serialize]
+#[auto_deserialize]
 type field_pat = {ident: ident, pat: @pat};
 
 #[auto_serialize]
+#[auto_deserialize]
 enum binding_mode {
     bind_by_value,
     bind_by_move,
@@ -376,6 +400,7 @@ impl binding_mode : cmp::Eq {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 enum pat_ {
     pat_wild,
     // A pat_ident may either be a new bound variable,
@@ -399,6 +424,7 @@ enum pat_ {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 enum mutability { m_mutbl, m_imm, m_const, }
 
 impl mutability : to_bytes::IterBytes {
@@ -415,6 +441,7 @@ impl mutability : cmp::Eq {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 enum proto {
     proto_bare,    // foreign fn
     proto_uniq,    // fn~
@@ -430,18 +457,20 @@ impl proto : cmp::Eq {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 enum vstore {
-    // FIXME (#2112): Change uint to @expr (actually only constant exprs)
-    vstore_fixed(Option<uint>),   // [1,2,3,4]/_ or 4
+    // FIXME (#3469): Change uint to @expr (actually only constant exprs)
+    vstore_fixed(Option<uint>),   // [1,2,3,4]
     vstore_uniq,                  // ~[1,2,3,4]
     vstore_box,                   // @[1,2,3,4]
     vstore_slice(@region)         // &[1,2,3,4](foo)?
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 enum expr_vstore {
-    // FIXME (#2112): Change uint to @expr (actually only constant exprs)
-    expr_vstore_fixed(Option<uint>),   // [1,2,3,4]/_ or 4
+    // FIXME (#3469): Change uint to @expr (actually only constant exprs)
+    expr_vstore_fixed(Option<uint>),   // [1,2,3,4]
     expr_vstore_uniq,                  // ~[1,2,3,4]
     expr_vstore_box,                   // @[1,2,3,4]
     expr_vstore_slice                  // &[1,2,3,4]
@@ -455,6 +484,7 @@ pure fn is_blockish(p: ast::proto) -> bool {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 enum binop {
     add,
     subtract,
@@ -484,6 +514,7 @@ impl binop : cmp::Eq {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 enum unop {
     box(mutability),
     uniq(mutability),
@@ -535,6 +566,7 @@ impl unop : cmp::Eq {
 // Generally, after typeck you can get the inferred value
 // using ty::resolved_T(...).
 #[auto_serialize]
+#[auto_deserialize]
 enum inferable<T> {
     expl(T),
     infer(node_id)
@@ -574,6 +606,7 @@ impl<T:cmp::Eq> inferable<T> : cmp::Eq {
 
 // "resolved" mode: the real modes.
 #[auto_serialize]
+#[auto_deserialize]
 enum rmode { by_ref, by_val, by_move, by_copy }
 
 impl rmode : to_bytes::IterBytes {
@@ -591,13 +624,12 @@ impl rmode : cmp::Eq {
 }
 
 // inferable mode.
-#[auto_serialize]
 type mode = inferable<rmode>;
 
-#[auto_serialize]
 type stmt = spanned<stmt_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 enum stmt_ {
     stmt_decl(@decl, node_id),
 
@@ -609,6 +641,7 @@ enum stmt_ {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 enum init_op { init_assign, init_move, }
 
 impl init_op : cmp::Eq {
@@ -632,33 +665,36 @@ impl init_op : cmp::Eq {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 type initializer = {op: init_op, expr: @expr};
 
 // FIXME (pending discussion of #1697, #2178...): local should really be
 // a refinement on pat.
 #[auto_serialize]
-type local_ =  {is_mutbl: bool, ty: @ty, pat: @pat,
+#[auto_deserialize]
+type local_ =  {is_mutbl: bool, ty: @Ty, pat: @pat,
                 init: Option<initializer>, id: node_id};
 
-#[auto_serialize]
 type local = spanned<local_>;
 
-#[auto_serialize]
 type decl = spanned<decl_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 enum decl_ { decl_local(~[@local]), decl_item(@item), }
 
 #[auto_serialize]
+#[auto_deserialize]
 type arm = {pats: ~[@pat], guard: Option<@expr>, body: blk};
 
 #[auto_serialize]
+#[auto_deserialize]
 type field_ = {mutbl: mutability, ident: ident, expr: @expr};
 
-#[auto_serialize]
 type field = spanned<field_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 enum blk_check_mode { default_blk, unsafe_blk, }
 
 impl blk_check_mode : cmp::Eq {
@@ -674,17 +710,17 @@ impl blk_check_mode : cmp::Eq {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 type expr = {id: node_id, callee_id: node_id, node: expr_, span: span};
 // Extra node ID is only used for index, assign_op, unary, binary
 
 #[auto_serialize]
+#[auto_deserialize]
 enum log_level { error, debug, other }
 // 0 = error, 1 = debug, 2 = other
 
 #[auto_serialize]
-enum alt_mode { alt_check, alt_exhaustive, }
-
-#[auto_serialize]
+#[auto_deserialize]
 enum expr_ {
     expr_vstore(@expr, expr_vstore),
     expr_vec(~[@expr], mutability),
@@ -694,7 +730,7 @@ enum expr_ {
     expr_binary(binop, @expr, @expr),
     expr_unary(unop, @expr),
     expr_lit(@lit),
-    expr_cast(@expr, @ty),
+    expr_cast(@expr, @Ty),
     expr_if(@expr, blk, Option<@expr>),
     expr_while(@expr, blk),
     /* Conditionless loop (can be exited with break, cont, ret, or fail)
@@ -718,7 +754,7 @@ enum expr_ {
     expr_assign(@expr, @expr),
     expr_swap(@expr, @expr),
     expr_assign_op(binop, @expr, @expr),
-    expr_field(@expr, ident, ~[@ty]),
+    expr_field(@expr, ident, ~[@Ty]),
     expr_index(@expr, @expr),
     expr_path(@path),
     expr_addr_of(mutability, @expr),
@@ -741,14 +777,16 @@ enum expr_ {
 }
 
 #[auto_serialize]
-type capture_item = @{
+#[auto_deserialize]
+type capture_item_ = {
     id: int,
     is_move: bool,
     name: ident, // Currently, can only capture a local var.
     span: span
 };
 
-#[auto_serialize]
+type capture_item = @capture_item_;
+
 type capture_clause = @~[capture_item];
 
 //
@@ -768,12 +806,13 @@ type capture_clause = @~[capture_item];
 // error.
 //
 #[auto_serialize]
+#[auto_deserialize]
 #[doc="For macro invocations; parsing is delegated to the macro"]
 enum token_tree {
-    tt_tok(span, token::token),
+    tt_tok(span, token::Token),
     tt_delim(~[token_tree]),
     // These only make sense for right-hand-sides of MBE macros
-    tt_seq(span, ~[token_tree], Option<token::token>, bool),
+    tt_seq(span, ~[token_tree], Option<token::Token>, bool),
     tt_nonterminal(span, ident)
 }
 
@@ -829,33 +868,32 @@ enum token_tree {
 // If you understand that, you have closed to loop and understand the whole
 // macro system. Congratulations.
 //
-#[auto_serialize]
 type matcher = spanned<matcher_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 enum matcher_ {
     // match one token
-    match_tok(token::token),
+    match_tok(token::Token),
     // match repetitions of a sequence: body, separator, zero ok?,
     // lo, hi position-in-match-array used:
-    match_seq(~[matcher], Option<token::token>, bool, uint, uint),
+    match_seq(~[matcher], Option<token::Token>, bool, uint, uint),
     // parse a Rust NT: name to bind, name of NT, position in match array:
     match_nonterminal(ident, ident, uint)
 }
 
-#[auto_serialize]
 type mac = spanned<mac_>;
 
-#[auto_serialize]
 type mac_arg = Option<@expr>;
 
 #[auto_serialize]
+#[auto_deserialize]
 type mac_body_ = {span: span};
 
-#[auto_serialize]
 type mac_body = Option<mac_body_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 enum mac_ {
     mac_invoc(@path, mac_arg, mac_body), // old macro-invocation
     mac_invoc_tt(@path,~[token_tree]),   // new macro-invocation
@@ -866,10 +904,10 @@ enum mac_ {
     mac_var(uint)
 }
 
-#[auto_serialize]
 type lit = spanned<lit_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 enum lit_ {
     lit_str(@~str),
     lit_int(i64, int_ty),
@@ -911,20 +949,23 @@ impl ast::lit_: cmp::Eq {
 // NB: If you change this, you'll probably want to change the corresponding
 // type structure in middle/ty.rs as well.
 #[auto_serialize]
-type mt = {ty: @ty, mutbl: mutability};
+#[auto_deserialize]
+type mt = {ty: @Ty, mutbl: mutability};
 
 #[auto_serialize]
+#[auto_deserialize]
 type ty_field_ = {ident: ident, mt: mt};
 
-#[auto_serialize]
 type ty_field = spanned<ty_field_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 type ty_method = {ident: ident, attrs: ~[attribute], purity: purity,
                   decl: fn_decl, tps: ~[ty_param], self_ty: self_ty,
                   id: node_id, span: span};
 
 #[auto_serialize]
+#[auto_deserialize]
 // A trait method is either required (meaning it doesn't have an
 // implementation, just a signature) or provided (meaning it has a default
 // implementation).
@@ -934,6 +975,7 @@ enum trait_method {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, }
 
 impl int_ty : to_bytes::IterBytes {
@@ -963,6 +1005,7 @@ impl int_ty : cmp::Eq {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, }
 
 impl uint_ty : to_bytes::IterBytes {
@@ -990,6 +1033,7 @@ impl uint_ty : cmp::Eq {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 enum float_ty { ty_f, ty_f32, ty_f64, }
 
 impl float_ty : to_bytes::IterBytes {
@@ -1008,10 +1052,12 @@ impl float_ty : cmp::Eq {
 }
 
 #[auto_serialize]
-type ty = {id: node_id, node: ty_, span: span};
+#[auto_deserialize]
+type Ty = {id: node_id, node: ty_, span: span};
 
 // Not represented directly in the AST, referred to by name through a ty_path.
 #[auto_serialize]
+#[auto_deserialize]
 enum prim_ty {
     ty_int(int_ty),
     ty_uint(uint_ty),
@@ -1059,9 +1105,11 @@ impl prim_ty : cmp::Eq {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 type region = {id: node_id, node: region_};
 
 #[auto_serialize]
+#[auto_deserialize]
 enum region_ {
     re_anon,
     re_static,
@@ -1070,6 +1118,7 @@ enum region_ {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 enum ty_ {
     ty_nil,
     ty_bot, /* bottom type */
@@ -1080,9 +1129,9 @@ enum ty_ {
     ty_rptr(@region, mt),
     ty_rec(~[ty_field]),
     ty_fn(proto, purity, @~[ty_param_bound], fn_decl),
-    ty_tup(~[@ty]),
+    ty_tup(~[@Ty]),
     ty_path(@path, node_id),
-    ty_fixed_length(@ty, Option<uint>),
+    ty_fixed_length(@Ty, Option<uint>),
     ty_mac(mac),
     // ty_infer means the type should be inferred instead of it having been
     // specified. This should only appear at the "top level" of a type and not
@@ -1092,16 +1141,16 @@ enum ty_ {
 
 // Equality and byte-iter (hashing) can be quite approximate for AST types.
 // since we only care about this for normalizing them to "real" types.
-impl ty : cmp::Eq {
-    pure fn eq(other: &ty) -> bool {
+impl Ty : cmp::Eq {
+    pure fn eq(other: &Ty) -> bool {
         ptr::addr_of(&self) == ptr::addr_of(&(*other))
     }
-    pure fn ne(other: &ty) -> bool {
+    pure fn ne(other: &Ty) -> bool {
         ptr::addr_of(&self) != ptr::addr_of(&(*other))
     }
 }
 
-impl ty : to_bytes::IterBytes {
+impl Ty : to_bytes::IterBytes {
     pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
         to_bytes::iter_bytes_2(&self.span.lo, &self.span.hi, lsb0, f);
     }
@@ -1109,15 +1158,18 @@ impl ty : to_bytes::IterBytes {
 
 
 #[auto_serialize]
-type arg = {mode: mode, ty: @ty, ident: ident, id: node_id};
+#[auto_deserialize]
+type arg = {mode: mode, ty: @Ty, ident: ident, id: node_id};
 
 #[auto_serialize]
+#[auto_deserialize]
 type fn_decl =
     {inputs: ~[arg],
-     output: @ty,
+     output: @Ty,
      cf: ret_style};
 
 #[auto_serialize]
+#[auto_deserialize]
 enum purity {
     pure_fn, // declared with "pure fn"
     unsafe_fn, // declared with "unsafe fn"
@@ -1139,6 +1191,7 @@ impl purity : cmp::Eq {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 enum ret_style {
     noreturn, // functions with return type _|_ that always
               // raise an error or exit (i.e. never return to the caller)
@@ -1164,6 +1217,7 @@ impl ret_style : cmp::Eq {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 enum self_ty_ {
     sty_static,                         // no self: static method
     sty_by_ref,                         // old by-reference self: ``
@@ -1217,10 +1271,10 @@ impl self_ty_ : cmp::Eq {
     pure fn ne(other: &self_ty_) -> bool { !self.eq(other) }
 }
 
-#[auto_serialize]
 type self_ty = spanned<self_ty_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 type method = {ident: ident, attrs: ~[attribute],
                tps: ~[ty_param], self_ty: self_ty,
                purity: purity, decl: fn_decl, body: blk,
@@ -1228,9 +1282,11 @@ type method = {ident: ident, attrs: ~[attribute],
                vis: visibility};
 
 #[auto_serialize]
+#[auto_deserialize]
 type _mod = {view_items: ~[@view_item], items: ~[@item]};
 
 #[auto_serialize]
+#[auto_deserialize]
 enum foreign_abi {
     foreign_abi_rust_intrinsic,
     foreign_abi_cdecl,
@@ -1239,6 +1295,7 @@ enum foreign_abi {
 
 // Foreign mods can be named or anonymous
 #[auto_serialize]
+#[auto_deserialize]
 enum foreign_mod_sort { named, anonymous }
 
 impl foreign_mod_sort : cmp::Eq {
@@ -1263,15 +1320,18 @@ impl foreign_abi : cmp::Eq {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 type foreign_mod =
     {sort: foreign_mod_sort,
      view_items: ~[@view_item],
      items: ~[@foreign_item]};
 
 #[auto_serialize]
-type variant_arg = {ty: @ty, id: node_id};
+#[auto_deserialize]
+type variant_arg = {ty: @Ty, id: node_id};
 
 #[auto_serialize]
+#[auto_deserialize]
 enum variant_kind {
     tuple_variant_kind(~[variant_arg]),
     struct_variant_kind(@struct_def),
@@ -1279,22 +1339,28 @@ enum variant_kind {
 }
 
 #[auto_serialize]
-enum enum_def = { variants: ~[variant], common: Option<@struct_def> };
+#[auto_deserialize]
+type enum_def_ = { variants: ~[variant], common: Option<@struct_def> };
+
+#[auto_serialize]
+#[auto_deserialize]
+enum enum_def = enum_def_;
 
 #[auto_serialize]
+#[auto_deserialize]
 type variant_ = {name: ident, attrs: ~[attribute], kind: variant_kind,
                  id: node_id, disr_expr: Option<@expr>, vis: visibility};
 
-#[auto_serialize]
 type variant = spanned<variant_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 type path_list_ident_ = {name: ident, id: node_id};
 
-#[auto_serialize]
 type path_list_ident = spanned<path_list_ident_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 enum namespace { module_ns, type_value_ns }
 
 impl namespace : cmp::Eq {
@@ -1304,10 +1370,10 @@ impl namespace : cmp::Eq {
     pure fn ne(other: &namespace) -> bool { !self.eq(other) }
 }
 
-#[auto_serialize]
 type view_path = spanned<view_path_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 enum view_path_ {
 
     // quux = foo::bar::baz
@@ -1325,10 +1391,12 @@ enum view_path_ {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 type view_item = {node: view_item_, attrs: ~[attribute],
                   vis: visibility, span: span};
 
 #[auto_serialize]
+#[auto_deserialize]
 enum view_item_ {
     view_item_use(ident, ~[@meta_item], node_id),
     view_item_import(~[@view_path]),
@@ -1336,13 +1404,13 @@ enum view_item_ {
 }
 
 // Meta-data associated with an item
-#[auto_serialize]
 type attribute = spanned<attribute_>;
 
 // Distinguishes between attributes that decorate items and attributes that
 // are contained as statements within items. These two cases need to be
 // distinguished for pretty-printing.
 #[auto_serialize]
+#[auto_deserialize]
 enum attr_style { attr_outer, attr_inner, }
 
 impl attr_style : cmp::Eq {
@@ -1354,6 +1422,7 @@ impl attr_style : cmp::Eq {
 
 // doc-comments are promoted to attributes that have is_sugared_doc = true
 #[auto_serialize]
+#[auto_deserialize]
 type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool};
 
 /*
@@ -1366,9 +1435,11 @@ type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool};
   trait)
  */
 #[auto_serialize]
+#[auto_deserialize]
 type trait_ref = {path: @path, ref_id: node_id, impl_id: node_id};
 
 #[auto_serialize]
+#[auto_deserialize]
 enum visibility { public, private, inherited }
 
 impl visibility : cmp::Eq {
@@ -1386,29 +1457,29 @@ impl visibility : cmp::Eq {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 type struct_field_ = {
     kind: struct_field_kind,
     id: node_id,
-    ty: @ty
+    ty: @Ty
 };
 
-#[auto_serialize]
 type struct_field = spanned<struct_field_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 enum struct_field_kind {
     named_field(ident, class_mutability, visibility),
     unnamed_field   // element of a tuple-like struct
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 type struct_def = {
     traits: ~[@trait_ref],   /* traits this struct implements */
     fields: ~[@struct_field], /* fields */
     methods: ~[@method],    /* methods */
     /* (not including ctor or dtor) */
-    /* ctor is optional, and will soon go away */
-    ctor: Option<class_ctor>,
     /* dtor is optional */
     dtor: Option<class_dtor>
 };
@@ -1418,28 +1489,31 @@ type struct_def = {
   we just use dummy names for anon items.
  */
 #[auto_serialize]
+#[auto_deserialize]
 type item = {ident: ident, attrs: ~[attribute],
              id: node_id, node: item_,
              vis: visibility, span: span};
 
 #[auto_serialize]
+#[auto_deserialize]
 enum item_ {
-    item_const(@ty, @expr),
+    item_const(@Ty, @expr),
     item_fn(fn_decl, purity, ~[ty_param], blk),
     item_mod(_mod),
     item_foreign_mod(foreign_mod),
-    item_ty(@ty, ~[ty_param]),
+    item_ty(@Ty, ~[ty_param]),
     item_enum(enum_def, ~[ty_param]),
     item_class(@struct_def, ~[ty_param]),
     item_trait(~[ty_param], ~[@trait_ref], ~[trait_method]),
     item_impl(~[ty_param],
               Option<@trait_ref>, /* (optional) trait this impl implements */
-              @ty, /* self */
+              @Ty, /* self */
               ~[@method]),
     item_mac(mac),
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 enum class_mutability { class_mutable, class_immutable }
 
 impl class_mutability : to_bytes::IterBytes {
@@ -1460,26 +1534,27 @@ impl class_mutability : cmp::Eq {
     pure fn ne(other: &class_mutability) -> bool { !self.eq(other) }
 }
 
-#[auto_serialize]
 type class_ctor = spanned<class_ctor_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 type class_ctor_ = {id: node_id,
                     attrs: ~[attribute],
                     self_id: node_id,
                     dec: fn_decl,
                     body: blk};
 
-#[auto_serialize]
 type class_dtor = spanned<class_dtor_>;
 
 #[auto_serialize]
+#[auto_deserialize]
 type class_dtor_ = {id: node_id,
                     attrs: ~[attribute],
                     self_id: node_id,
                     body: blk};
 
 #[auto_serialize]
+#[auto_deserialize]
 type foreign_item =
     {ident: ident,
      attrs: ~[attribute],
@@ -1489,20 +1564,21 @@ type foreign_item =
      vis: visibility};
 
 #[auto_serialize]
+#[auto_deserialize]
 enum foreign_item_ {
     foreign_item_fn(fn_decl, purity, ~[ty_param]),
-    foreign_item_const(@ty)
+    foreign_item_const(@Ty)
 }
 
 // The data we save and restore about an inlined item or method.  This is not
 // part of the AST that we parse from a file, but it becomes part of the tree
 // that we trans.
 #[auto_serialize]
+#[auto_deserialize]
 enum inlined_item {
     ii_item(@item),
     ii_method(def_id /* impl id */, @method),
     ii_foreign(@foreign_item),
-    ii_ctor(class_ctor, ident, ~[ty_param], def_id /* parent id */),
     ii_dtor(class_dtor, ident, ~[ty_param], def_id /* parent id */)
 }
 
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index d05c6eadaf6..8555ceed2db 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -71,9 +71,6 @@ enum ast_node {
     // order they are introduced.
     node_arg(arg, uint),
     node_local(uint),
-    // Constructor for a class
-    // def_id is parent id
-    node_ctor(ident, ~[ty_param], @class_ctor, def_id, @path),
     // Destructor for a class
     node_dtor(~[ty_param], @class_dtor, def_id, @path),
     node_block(blk),
@@ -132,7 +129,7 @@ fn map_decoded_item(diag: span_handler,
     // don't decode and instantiate the impl, but just the method, we have to
     // add it to the table now:
     match ii {
-      ii_item(*) | ii_ctor(*) | ii_dtor(*) => { /* fallthrough */ }
+      ii_item(*) | ii_dtor(*) => { /* fallthrough */ }
       ii_foreign(i) => {
         cx.map.insert(i.id, node_foreign_item(i, foreign_abi_rust_intrinsic,
                                              @path));
@@ -155,18 +152,6 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
         cx.local_id += 1u;
     }
     match fk {
-      visit::fk_ctor(nm, attrs, tps, self_id, parent_id) => {
-          let ct = @{node: {id: id,
-                            attrs: attrs,
-                            self_id: self_id,
-                            dec: /* FIXME (#2543) */ copy decl,
-                            body: /* FIXME (#2543) */ copy body},
-                    span: sp};
-          cx.map.insert(id, node_ctor(/* FIXME (#2543) */ copy nm,
-                                      /* FIXME (#2543) */ copy tps,
-                                      ct, parent_id,
-                                      @/* FIXME (#2543) */ copy cx.path));
-      }
       visit::fk_dtor(tps, attrs, self_id, parent_id) => {
           let dt = @{node: {id: id, attrs: attrs, self_id: self_id,
                      body: /* FIXME (#2543) */ copy body}, span: sp};
@@ -382,9 +367,6 @@ fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str {
       Some(node_local(_)) => { // add more info here
         fmt!("local (id=%?)", id)
       }
-      Some(node_ctor(*)) => { // add more info here
-        fmt!("node_ctor (id=%?)", id)
-      }
       Some(node_dtor(*)) => { // add more info here
         fmt!("node_dtor (id=%?)", id)
       }
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index e8099de246c..6fd84c3317f 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -54,10 +54,10 @@ fn variant_def_ids(d: def) -> {enm: def_id, var: def_id} {
 
 pure fn def_id_of_def(d: def) -> def_id {
     match d {
-      def_fn(id, _) | def_static_method(id, _) | def_mod(id) |
+      def_fn(id, _) | def_static_method(id, _, _) | def_mod(id) |
       def_foreign_mod(id) | def_const(id) |
       def_variant(_, id) | def_ty(id) | def_ty_param(id, _) |
-      def_use(id) | def_class(id, _) => {
+      def_use(id) | def_class(id) => {
         id
       }
       def_arg(id, _) | def_local(id, _) | def_self(id) |
@@ -233,7 +233,6 @@ fn is_exported(i: ident, m: _mod) -> bool {
                     }
                   }
 
-                  // FIXME: glob-exports aren't supported yet. (#2006)
                   _ => ()
                 }
             }
@@ -339,7 +338,6 @@ impl inlined_item: inlined_item_utils {
           ii_item(i) => /* FIXME (#2543) */ copy i.ident,
           ii_foreign(i) => /* FIXME (#2543) */ copy i.ident,
           ii_method(_, m) => /* FIXME (#2543) */ copy m.ident,
-          ii_ctor(_, nm, _, _) => /* FIXME (#2543) */ copy nm,
           ii_dtor(_, nm, _, _) => /* FIXME (#2543) */ copy nm
         }
     }
@@ -349,7 +347,6 @@ impl inlined_item: inlined_item_utils {
           ii_item(i) => i.id,
           ii_foreign(i) => i.id,
           ii_method(_, m) => m.id,
-          ii_ctor(ctor, _, _, _) => ctor.node.id,
           ii_dtor(dtor, _, _, _) => dtor.node.id
         }
     }
@@ -359,9 +356,6 @@ impl inlined_item: inlined_item_utils {
           ii_item(i) => v.visit_item(i, e, v),
           ii_foreign(i) => v.visit_foreign_item(i, e, v),
           ii_method(_, m) => visit::visit_method_helper(m, e, v),
-          ii_ctor(ctor, nm, tps, parent_id) => {
-              visit::visit_class_ctor_helper(ctor, nm, tps, parent_id, e, v);
-          }
           ii_dtor(dtor, _, tps, parent_id) => {
               visit::visit_class_dtor_helper(dtor, tps, parent_id, e, v);
           }
@@ -407,6 +401,7 @@ fn dtor_dec() -> fn_decl {
 // Enumerating the IDs which appear in an AST
 
 #[auto_serialize]
+#[auto_deserialize]
 type id_range = {min: node_id, max: node_id};
 
 fn empty(range: id_range) -> bool {
@@ -476,7 +471,7 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
         visit_expr_post: fn@(_e: @expr) {
         },
 
-        visit_ty: fn@(t: @ty) {
+        visit_ty: fn@(t: @Ty) {
             match t.node {
               ty_path(_, id) => vfn(id),
               _ => { /* fall through */ }
@@ -494,12 +489,6 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
             vfn(id);
 
             match fk {
-                visit::fk_ctor(_, _, tps, self_id, parent_id) => {
-                    for vec::each(tps) |tp| { vfn(tp.id); }
-                    vfn(id);
-                    vfn(self_id);
-                    vfn(parent_id.node);
-                }
                 visit::fk_dtor(tps, _, self_id, parent_id) => {
                     for vec::each(tps) |tp| { vfn(tp.id); }
                     vfn(id);
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 374300f07c7..8c19814350c 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -90,9 +90,7 @@ fn attr_meta(attr: ast::attribute) -> @ast::meta_item { @attr.node.value }
 
 // Get the meta_items from inside a vector of attributes
 fn attr_metas(attrs: ~[ast::attribute]) -> ~[@ast::meta_item] {
-    let mut mitems = ~[];
-    for attrs.each |a| { mitems.push(attr_meta(*a)); }
-    return mitems;
+    do attrs.map |a| { attr_meta(*a) }
 }
 
 fn desugar_doc_attr(attr: &ast::attribute) -> ast::attribute {
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index e07985119ec..69a80d0bac1 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -1,4 +1,8 @@
 use dvec::DVec;
+use std::serialization::{Serializable,
+                         Deserializable,
+                         Serializer,
+                         Deserializer};
 
 export filename;
 export filemap;
@@ -7,7 +11,7 @@ export file_substr;
 export fss_none;
 export fss_internal;
 export fss_external;
-export codemap;
+export CodeMap;
 export expn_info;
 export expn_info_;
 export expanded_from;
@@ -55,11 +59,11 @@ type filemap =
     @{name: filename, substr: file_substr, src: @~str,
       start_pos: file_pos, mut lines: ~[file_pos]};
 
-type codemap = @{files: DVec<filemap>};
+type CodeMap = @{files: DVec<filemap>};
 
 type loc = {file: filemap, line: uint, col: uint};
 
-fn new_codemap() -> codemap { @{files: DVec()} }
+fn new_codemap() -> CodeMap { @{files: DVec()} }
 
 fn new_filemap_w_substr(+filename: filename, +substr: file_substr,
                         src: @~str,
@@ -77,7 +81,7 @@ fn new_filemap(+filename: filename, src: @~str,
                              start_pos_ch, start_pos_byte);
 }
 
-fn mk_substr_filename(cm: codemap, sp: span) -> ~str
+fn mk_substr_filename(cm: CodeMap, sp: span) -> ~str
 {
     let pos = lookup_char_pos(cm, sp.lo);
     return fmt!("<%s:%u:%u>", pos.file.name, pos.line, pos.col);
@@ -89,7 +93,7 @@ fn next_line(file: filemap, chpos: uint, byte_pos: uint) {
 
 type lookup_fn = pure fn(file_pos) -> uint;
 
-fn lookup_line(map: codemap, pos: uint, lookup: lookup_fn)
+fn lookup_line(map: CodeMap, pos: uint, lookup: lookup_fn)
     -> {fm: filemap, line: uint}
 {
     let len = map.files.len();
@@ -112,22 +116,22 @@ fn lookup_line(map: codemap, pos: uint, lookup: lookup_fn)
     return {fm: f, line: a};
 }
 
-fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
+fn lookup_pos(map: CodeMap, pos: uint, lookup: lookup_fn) -> loc {
     let {fm: f, line: a} = lookup_line(map, pos, lookup);
     return {file: f, line: a + 1u, col: pos - lookup(f.lines[a])};
 }
 
-fn lookup_char_pos(map: codemap, pos: uint) -> loc {
+fn lookup_char_pos(map: CodeMap, pos: uint) -> loc {
     pure fn lookup(pos: file_pos) -> uint { return pos.ch; }
     return lookup_pos(map, pos, lookup);
 }
 
-fn lookup_byte_pos(map: codemap, pos: uint) -> loc {
+fn lookup_byte_pos(map: CodeMap, pos: uint) -> loc {
     pure fn lookup(pos: file_pos) -> uint { return pos.byte; }
     return lookup_pos(map, pos, lookup);
 }
 
-fn lookup_char_pos_adj(map: codemap, pos: uint)
+fn lookup_char_pos_adj(map: CodeMap, pos: uint)
     -> {filename: ~str, line: uint, col: uint, file: Option<filemap>}
 {
     let loc = lookup_char_pos(map, pos);
@@ -150,7 +154,7 @@ fn lookup_char_pos_adj(map: codemap, pos: uint)
     }
 }
 
-fn adjust_span(map: codemap, sp: span) -> span {
+fn adjust_span(map: CodeMap, sp: span) -> span {
     pure fn lookup(pos: file_pos) -> uint { return pos.ch; }
     let line = lookup_line(map, sp.lo, lookup);
     match (line.fm.substr) {
@@ -178,14 +182,42 @@ impl span : cmp::Eq {
     pure fn ne(other: &span) -> bool { !self.eq(other) }
 }
 
-fn span_to_str_no_adj(sp: span, cm: codemap) -> ~str {
+#[cfg(stage0)]
+impl span: Serializable {
+    /* Note #1972 -- spans are serialized but not deserialized */
+    fn serialize<S: Serializer>(&self, _s: &S) { }
+}
+
+#[cfg(stage0)]
+impl span: Deserializable {
+    static fn deserialize<D: Deserializer>(_d: &D) -> span {
+        ast_util::dummy_sp()
+    }
+}
+
+#[cfg(stage1)]
+#[cfg(stage2)]
+impl<S: Serializer> span: Serializable<S> {
+    /* Note #1972 -- spans are serialized but not deserialized */
+    fn serialize(&self, _s: &S) { }
+}
+
+#[cfg(stage1)]
+#[cfg(stage2)]
+impl<D: Deserializer> span: Deserializable<D> {
+    static fn deserialize(_d: &D) -> span {
+        ast_util::dummy_sp()
+    }
+}
+
+fn span_to_str_no_adj(sp: span, cm: CodeMap) -> ~str {
     let lo = lookup_char_pos(cm, sp.lo);
     let hi = lookup_char_pos(cm, sp.hi);
     return fmt!("%s:%u:%u: %u:%u", lo.file.name,
              lo.line, lo.col, hi.line, hi.col)
 }
 
-fn span_to_str(sp: span, cm: codemap) -> ~str {
+fn span_to_str(sp: span, cm: CodeMap) -> ~str {
     let lo = lookup_char_pos_adj(cm, sp.lo);
     let hi = lookup_char_pos_adj(cm, sp.hi);
     return fmt!("%s:%u:%u: %u:%u", lo.filename,
@@ -194,12 +226,12 @@ fn span_to_str(sp: span, cm: codemap) -> ~str {
 
 type file_lines = {file: filemap, lines: ~[uint]};
 
-fn span_to_filename(sp: span, cm: codemap::codemap) -> filename {
+fn span_to_filename(sp: span, cm: codemap::CodeMap) -> filename {
     let lo = lookup_char_pos(cm, sp.lo);
     return /* FIXME (#2543) */ copy lo.file.name;
 }
 
-fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines {
+fn span_to_lines(sp: span, cm: codemap::CodeMap) -> @file_lines {
     let lo = lookup_char_pos(cm, sp.lo);
     let hi = lookup_char_pos(cm, sp.hi);
     let mut lines = ~[];
@@ -218,7 +250,7 @@ fn get_line(fm: filemap, line: int) -> ~str unsafe {
     str::slice(*fm.src, begin, end)
 }
 
-fn lookup_byte_offset(cm: codemap::codemap, chpos: uint)
+fn lookup_byte_offset(cm: codemap::CodeMap, chpos: uint)
     -> {fm: filemap, pos: uint} {
     pure fn lookup(pos: file_pos) -> uint { return pos.ch; }
     let {fm, line} = lookup_line(cm, chpos, lookup);
@@ -228,20 +260,20 @@ fn lookup_byte_offset(cm: codemap::codemap, chpos: uint)
     {fm: fm, pos: line_offset + col_offset}
 }
 
-fn span_to_snippet(sp: span, cm: codemap::codemap) -> ~str {
+fn span_to_snippet(sp: span, cm: codemap::CodeMap) -> ~str {
     let begin = lookup_byte_offset(cm, sp.lo);
     let end = lookup_byte_offset(cm, sp.hi);
     assert begin.fm.start_pos == end.fm.start_pos;
     return str::slice(*begin.fm.src, begin.pos, end.pos);
 }
 
-fn get_snippet(cm: codemap::codemap, fidx: uint, lo: uint, hi: uint) -> ~str
+fn get_snippet(cm: codemap::CodeMap, fidx: uint, lo: uint, hi: uint) -> ~str
 {
     let fm = cm.files[fidx];
     return str::slice(*fm.src, lo, hi)
 }
 
-fn get_filemap(cm: codemap, filename: ~str) -> filemap {
+fn get_filemap(cm: CodeMap, filename: ~str) -> filemap {
     for cm.files.each |fm| { if fm.name == filename { return *fm; } }
     //XXjdm the following triggers a mismatched type bug
     //      (or expected function, found _|_)
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index 7f208a3a710..855b0ca3ef5 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -9,7 +9,7 @@ export codemap_span_handler, codemap_handler;
 export ice_msg;
 export expect;
 
-type emitter = fn@(cmsp: Option<(codemap::codemap, span)>,
+type emitter = fn@(cmsp: Option<(codemap::CodeMap, span)>,
                    msg: &str, lvl: level);
 
 
@@ -33,7 +33,7 @@ trait handler {
     fn note(msg: &str);
     fn bug(msg: &str) -> !;
     fn unimpl(msg: &str) -> !;
-    fn emit(cmsp: Option<(codemap::codemap, span)>, msg: &str, lvl: level);
+    fn emit(cmsp: Option<(codemap::CodeMap, span)>, msg: &str, lvl: level);
 }
 
 type handler_t = @{
@@ -43,7 +43,7 @@ type handler_t = @{
 
 type codemap_t = @{
     handler: handler,
-    cm: codemap::codemap
+    cm: codemap::CodeMap
 };
 
 impl codemap_t: span_handler {
@@ -107,7 +107,7 @@ impl handler_t: handler {
         self.fatal(ice_msg(msg));
     }
     fn unimpl(msg: &str) -> ! { self.bug(~"unimplemented " + msg); }
-    fn emit(cmsp: Option<(codemap::codemap, span)>, msg: &str, lvl: level) {
+    fn emit(cmsp: Option<(codemap::CodeMap, span)>, msg: &str, lvl: level) {
         self.emit(cmsp, msg, lvl);
     }
 }
@@ -116,7 +116,7 @@ fn ice_msg(msg: &str) -> ~str {
     fmt!("internal compiler error: %s", msg)
 }
 
-fn mk_span_handler(handler: handler, cm: codemap::codemap) -> span_handler {
+fn mk_span_handler(handler: handler, cm: codemap::CodeMap) -> span_handler {
     @{ handler: handler, cm: cm } as span_handler
 }
 
@@ -125,7 +125,7 @@ fn mk_handler(emitter: Option<emitter>) -> handler {
     let emit = match emitter {
       Some(e) => e,
       None => {
-        let f = fn@(cmsp: Option<(codemap::codemap, span)>,
+        let f = fn@(cmsp: Option<(codemap::CodeMap, span)>,
             msg: &str, t: level) {
             emit(cmsp, msg, t);
         };
@@ -189,8 +189,7 @@ fn print_diagnostic(topic: ~str, lvl: level, msg: &str) {
     io::stderr().write_str(fmt!(" %s\n", msg));
 }
 
-fn emit(cmsp: Option<(codemap::codemap, span)>,
-        msg: &str, lvl: level) {
+fn emit(cmsp: Option<(codemap::CodeMap, span)>, msg: &str, lvl: level) {
     match cmsp {
       Some((cm, sp)) => {
         let sp = codemap::adjust_span(cm,sp);
@@ -206,7 +205,7 @@ fn emit(cmsp: Option<(codemap::codemap, span)>,
     }
 }
 
-fn highlight_lines(cm: codemap::codemap, sp: span,
+fn highlight_lines(cm: codemap::CodeMap, sp: span,
                    lines: @codemap::file_lines) {
 
     let fm = lines.file;
@@ -261,12 +260,12 @@ fn highlight_lines(cm: codemap::codemap, sp: span,
     }
 }
 
-fn print_macro_backtrace(cm: codemap::codemap, sp: span) {
+fn print_macro_backtrace(cm: codemap::CodeMap, sp: span) {
     do option::iter(&sp.expn_info) |ei| {
         let ss = option::map_default(&ei.callie.span, @~"",
                                      |span| @codemap::span_to_str(*span, cm));
         print_diagnostic(*ss, note,
-                         fmt!("in expansion of #%s", ei.callie.name));
+                         fmt!("in expansion of %s!", ei.callie.name));
         let ss = codemap::span_to_str(ei.call_site, cm);
         print_diagnostic(ss, note, ~"expansion site");
         print_macro_backtrace(cm, ei.call_site);
diff --git a/src/libsyntax/ext/auto_serialize.rs b/src/libsyntax/ext/auto_serialize.rs
index 64915c60742..47e61c26f38 100644
--- a/src/libsyntax/ext/auto_serialize.rs
+++ b/src/libsyntax/ext/auto_serialize.rs
@@ -1,62 +1,70 @@
 /*
 
-The compiler code necessary to implement the #[auto_serialize]
-extension.  The idea here is that type-defining items may be tagged
-with #[auto_serialize], which will cause us to generate a little
-companion module with the same name as the item.
+The compiler code necessary to implement the #[auto_serialize] and
+#[auto_deserialize] extension.  The idea here is that type-defining items may
+be tagged with #[auto_serialize] and #[auto_deserialize], which will cause
+us to generate a little companion module with the same name as the item.
 
 For example, a type like:
 
-    type node_id = uint;
+    #[auto_serialize]
+    #[auto_deserialize]
+    struct Node {id: uint}
 
-would generate two functions like:
+would generate two implementations like:
 
-    fn serialize_node_id<S: serializer>(s: S, v: node_id) {
-        s.emit_uint(v);
+    impl<S: Serializer> node_id: Serializable<S> {
+        fn serialize(s: &S) {
+            do s.emit_struct("Node") {
+                s.emit_field("id", 0, || s.emit_uint(self))
+            }
+        }
     }
-    fn deserialize_node_id<D: deserializer>(d: D) -> node_id {
-        d.read_uint()
+
+    impl<D: Deserializer> node_id: Deserializable {
+        static fn deserialize(d: &D) -> Node {
+            do d.read_struct("Node") {
+                Node {
+                    id: d.read_field(~"x", 0, || deserialize(d))
+                }
+            }
+        }
     }
 
 Other interesting scenarios are whe the item has type parameters or
 references other non-built-in types.  A type definition like:
 
+    #[auto_serialize]
+    #[auto_deserialize]
     type spanned<T> = {node: T, span: span};
 
 would yield functions like:
 
-    fn serialize_spanned<S: serializer,T>(s: S, v: spanned<T>, t: fn(T)) {
-         s.emit_rec(2u) {||
-             s.emit_rec_field("node", 0u) {||
-                 t(s.node);
-             };
-             s.emit_rec_field("span", 1u) {||
-                 serialize_span(s, s.span);
-             };
-         }
-    }
-    fn deserialize_spanned<D: deserializer>(d: D, t: fn() -> T) -> node_id {
-         d.read_rec(2u) {||
-             {node: d.read_rec_field("node", 0u, t),
-              span: d.read_rec_field("span", 1u) {||deserialize_span(d)}}
-         }
+    impl<
+        S: Serializer,
+        T: Serializable<S>
+    > spanned<T>: Serializable<S> {
+        fn serialize<S: Serializer>(s: &S) {
+            do s.emit_rec {
+                s.emit_field("node", 0, || self.node.serialize(s));
+                s.emit_field("span", 1, || self.span.serialize(s));
+            }
+        }
     }
 
-In general, the code to serialize an instance `v` of a non-built-in
-type a::b::c<T0,...,Tn> looks like:
-
-    a::b::serialize_c(s, {|v| c_T0}, ..., {|v| c_Tn}, v)
-
-where `c_Ti` is the code to serialize an instance `v` of the type
-`Ti`.
-
-Similarly, the code to deserialize an instance of a non-built-in type
-`a::b::c<T0,...,Tn>` using the deserializer `d` looks like:
-
-    a::b::deserialize_c(d, {|| c_T0}, ..., {|| c_Tn})
-
-where `c_Ti` is the code to deserialize an instance of `Ti` using the
-deserializer `d`.
+    impl<
+        D: Deserializer,
+        T: Deserializable<D>
+    > spanned<T>: Deserializable<D> {
+        static fn deserialize(d: &D) -> spanned<T> {
+            do d.read_rec {
+                {
+                    node: d.read_field(~"node", 0, || deserialize(d)),
+                    span: d.read_field(~"span", 1, || deserialize(d)),
+                }
+            }
+        }
+    }
 
 FIXME (#2810)--Hygiene. Search for "__" strings.  We also assume "std" is the
 standard library.
@@ -69,137 +77,167 @@ into the tree.  This is intended to prevent us from inserting the same
 node twice.
 
 */
+
 use base::*;
 use codemap::span;
 use std::map;
 use std::map::HashMap;
 
-export expand;
+export expand_auto_serialize;
+export expand_auto_deserialize;
 
 // Transitional reexports so qquote can find the paths it is looking for
 mod syntax {
-    #[legacy_exports];
     pub use ext;
     pub use parse;
 }
 
-type ser_tps_map = map::HashMap<ast::ident, fn@(@ast::expr) -> ~[@ast::stmt]>;
-type deser_tps_map = map::HashMap<ast::ident, fn@() -> @ast::expr>;
-
-fn expand(cx: ext_ctxt,
-          span: span,
-          _mitem: ast::meta_item,
-          in_items: ~[@ast::item]) -> ~[@ast::item] {
-    fn not_auto_serialize(a: &ast::attribute) -> bool {
-        attr::get_attr_name(*a) != ~"auto_serialize"
+fn expand_auto_serialize(
+    cx: ext_ctxt,
+    span: span,
+    _mitem: ast::meta_item,
+    in_items: ~[@ast::item]
+) -> ~[@ast::item] {
+    fn is_auto_serialize(a: &ast::attribute) -> bool {
+        attr::get_attr_name(*a) == ~"auto_serialize"
     }
 
     fn filter_attrs(item: @ast::item) -> @ast::item {
-        @{attrs: vec::filter(item.attrs, not_auto_serialize),
+        @{attrs: vec::filter(item.attrs, |a| !is_auto_serialize(a)),
           .. *item}
     }
 
-    do vec::flat_map(in_items) |in_item| {
-        match in_item.node {
-          ast::item_ty(ty, tps) => {
-            vec::append(~[filter_attrs(*in_item)],
-                        ty_fns(cx, in_item.ident, ty, tps))
-          }
-
-          ast::item_enum(enum_definition, tps) => {
-            vec::append(~[filter_attrs(*in_item)],
-                        enum_fns(cx, in_item.ident,
-                                 in_item.span, enum_definition.variants, tps))
-          }
-
-          _ => {
-            cx.span_err(span, ~"#[auto_serialize] can only be \
-                               applied to type and enum \
-                               definitions");
-            ~[*in_item]
-          }
+    do vec::flat_map(in_items) |item| {
+        if item.attrs.any(is_auto_serialize) {
+            match item.node {
+                ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => {
+                    let ser_impl = mk_rec_ser_impl(
+                        cx,
+                        item.span,
+                        item.ident,
+                        fields,
+                        tps
+                    );
+
+                    ~[filter_attrs(*item), ser_impl]
+                },
+                ast::item_class(@{ fields, _}, tps) => {
+                    let ser_impl = mk_struct_ser_impl(
+                        cx,
+                        item.span,
+                        item.ident,
+                        fields,
+                        tps
+                    );
+
+                    ~[filter_attrs(*item), ser_impl]
+                },
+                ast::item_enum(enum_def, tps) => {
+                    let ser_impl = mk_enum_ser_impl(
+                        cx,
+                        item.span,
+                        item.ident,
+                        enum_def,
+                        tps
+                    );
+
+                    ~[filter_attrs(*item), ser_impl]
+                },
+                _ => {
+                    cx.span_err(span, ~"#[auto_serialize] can only be \
+                                        applied to structs, record types, \
+                                        and enum definitions");
+                    ~[*item]
+                }
+            }
+        } else {
+            ~[*item]
         }
     }
 }
 
-trait ext_ctxt_helpers {
-    fn helper_path(base_path: @ast::path, helper_name: ~str) -> @ast::path;
-    fn path(span: span, strs: ~[ast::ident]) -> @ast::path;
-    fn path_tps(span: span, strs: ~[ast::ident],
-                tps: ~[@ast::ty]) -> @ast::path;
-    fn ty_path(span: span, strs: ~[ast::ident], tps: ~[@ast::ty]) -> @ast::ty;
-    fn ty_fn(span: span,
-             -input_tys: ~[@ast::ty],
-             -output: @ast::ty) -> @ast::ty;
-    fn ty_nil(span: span) -> @ast::ty;
-    fn expr(span: span, node: ast::expr_) -> @ast::expr;
-    fn var_ref(span: span, name: ast::ident) -> @ast::expr;
-    fn blk(span: span, stmts: ~[@ast::stmt]) -> ast::blk;
-    fn expr_blk(expr: @ast::expr) -> ast::blk;
-    fn binder_pat(span: span, nm: ast::ident) -> @ast::pat;
-    fn stmt(expr: @ast::expr) -> @ast::stmt;
-    fn alt_stmt(arms: ~[ast::arm], span: span, -v: @ast::expr) -> @ast::stmt;
-    fn lit_str(span: span, s: @~str) -> @ast::expr;
-    fn lit_uint(span: span, i: uint) -> @ast::expr;
-    fn lambda(blk: ast::blk) -> @ast::expr;
-    fn clone_folder() -> fold::ast_fold;
-    fn clone(v: @ast::expr) -> @ast::expr;
-    fn clone_ty(v: @ast::ty) -> @ast::ty;
-    fn clone_ty_param(v: ast::ty_param) -> ast::ty_param;
-    fn at(span: span, expr: @ast::expr) -> @ast::expr;
-}
-
-impl ext_ctxt: ext_ctxt_helpers {
-    fn helper_path(base_path: @ast::path,
-                   helper_name: ~str) -> @ast::path {
-        let head = vec::init(base_path.idents);
-        let tail = vec::last(base_path.idents);
-        self.path(base_path.span,
-                  vec::append(head,
-                              ~[self.parse_sess().interner.
-                                intern(@(helper_name + ~"_" +
-                                         *self.parse_sess().interner.get(
-                                             tail)))]))
+fn expand_auto_deserialize(
+    cx: ext_ctxt,
+    span: span,
+    _mitem: ast::meta_item,
+    in_items: ~[@ast::item]
+) -> ~[@ast::item] {
+    fn is_auto_deserialize(a: &ast::attribute) -> bool {
+        attr::get_attr_name(*a) == ~"auto_deserialize"
     }
 
-    fn path(span: span, strs: ~[ast::ident]) -> @ast::path {
-        @{span: span, global: false, idents: strs, rp: None, types: ~[]}
-    }
-
-    fn path_tps(span: span, strs: ~[ast::ident],
-                tps: ~[@ast::ty]) -> @ast::path {
-        @{span: span, global: false, idents: strs, rp: None, types: tps}
+    fn filter_attrs(item: @ast::item) -> @ast::item {
+        @{attrs: vec::filter(item.attrs, |a| !is_auto_deserialize(a)),
+          .. *item}
     }
 
-    fn ty_path(span: span, strs: ~[ast::ident],
-               tps: ~[@ast::ty]) -> @ast::ty {
-        @{id: self.next_id(),
-          node: ast::ty_path(self.path_tps(span, strs, tps), self.next_id()),
-          span: span}
+    do vec::flat_map(in_items) |item| {
+        if item.attrs.any(is_auto_deserialize) {
+            match item.node {
+                ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => {
+                    let deser_impl = mk_rec_deser_impl(
+                        cx,
+                        item.span,
+                        item.ident,
+                        fields,
+                        tps
+                    );
+
+                    ~[filter_attrs(*item), deser_impl]
+                },
+                ast::item_class(@{ fields, _}, tps) => {
+                    let deser_impl = mk_struct_deser_impl(
+                        cx,
+                        item.span,
+                        item.ident,
+                        fields,
+                        tps
+                    );
+
+                    ~[filter_attrs(*item), deser_impl]
+                },
+                ast::item_enum(enum_def, tps) => {
+                    let deser_impl = mk_enum_deser_impl(
+                        cx,
+                        item.span,
+                        item.ident,
+                        enum_def,
+                        tps
+                    );
+
+                    ~[filter_attrs(*item), deser_impl]
+                },
+                _ => {
+                    cx.span_err(span, ~"#[auto_deserialize] can only be \
+                                        applied to structs, record types, \
+                                        and enum definitions");
+                    ~[*item]
+                }
+            }
+        } else {
+            ~[*item]
+        }
     }
+}
 
-    fn ty_fn(span: span,
-             -input_tys: ~[@ast::ty],
-             -output: @ast::ty) -> @ast::ty {
-        let args = do vec::map(input_tys) |ty| {
-            {mode: ast::expl(ast::by_ref),
-             ty: *ty,
-             ident: parse::token::special_idents::invalid,
-             id: self.next_id()}
-        };
-
-        @{id: self.next_id(),
-          node: ast::ty_fn(ast::proto_block,
-                           ast::impure_fn,
-                           @~[],
-                           {inputs: args,
-                            output: output,
-                            cf: ast::return_val}),
-          span: span}
-    }
+priv impl ext_ctxt {
+    fn bind_path(
+        span: span,
+        ident: ast::ident,
+        path: @ast::path,
+        bounds: @~[ast::ty_param_bound]
+    ) -> ast::ty_param {
+        let bound = ast::ty_param_bound(@{
+            id: self.next_id(),
+            node: ast::ty_path(path, self.next_id()),
+            span: span,
+        });
 
-    fn ty_nil(span: span) -> @ast::ty {
-        @{id: self.next_id(), node: ast::ty_nil, span: span}
+        {
+            ident: ident,
+            id: self.next_id(),
+            bounds: @vec::append(~[bound], *bounds)
+        }
     }
 
     fn expr(span: span, node: ast::expr_) -> @ast::expr {
@@ -207,26 +245,20 @@ impl ext_ctxt: ext_ctxt_helpers {
           node: node, span: span}
     }
 
-    fn var_ref(span: span, name: ast::ident) -> @ast::expr {
-        self.expr(span, ast::expr_path(self.path(span, ~[name])))
+    fn path(span: span, strs: ~[ast::ident]) -> @ast::path {
+        @{span: span, global: false, idents: strs, rp: None, types: ~[]}
     }
 
-    fn blk(span: span, stmts: ~[@ast::stmt]) -> ast::blk {
-        {node: {view_items: ~[],
-                stmts: stmts,
-                expr: None,
-                id: self.next_id(),
-                rules: ast::default_blk},
-         span: span}
+    fn path_tps(span: span, strs: ~[ast::ident],
+                tps: ~[@ast::Ty]) -> @ast::path {
+        @{span: span, global: false, idents: strs, rp: None, types: tps}
     }
 
-    fn expr_blk(expr: @ast::expr) -> ast::blk {
-        {node: {view_items: ~[],
-                stmts: ~[],
-                expr: Some(expr),
-                id: self.next_id(),
-                rules: ast::default_blk},
-         span: expr.span}
+    fn ty_path(span: span, strs: ~[ast::ident],
+               tps: ~[@ast::Ty]) -> @ast::Ty {
+        @{id: self.next_id(),
+          node: ast::ty_path(self.path_tps(span, strs, tps), self.next_id()),
+          span: span}
     }
 
     fn binder_pat(span: span, nm: ast::ident) -> @ast::pat {
@@ -244,14 +276,6 @@ impl ext_ctxt: ext_ctxt_helpers {
           span: expr.span}
     }
 
-    fn alt_stmt(arms: ~[ast::arm],
-                span: span, -v: @ast::expr) -> @ast::stmt {
-        self.stmt(
-            self.expr(
-                span,
-                ast::expr_match(v, arms)))
-    }
-
     fn lit_str(span: span, s: @~str) -> @ast::expr {
         self.expr(
             span,
@@ -278,686 +302,835 @@ impl ext_ctxt: ext_ctxt_helpers {
         #ast{ || $(blk_e) }
     }
 
-    fn clone_folder() -> fold::ast_fold {
-        fold::make_fold(@{
-            new_id: |_id| self.next_id(),
-            .. *fold::default_ast_fold()
-        })
+    fn blk(span: span, stmts: ~[@ast::stmt]) -> ast::blk {
+        {node: {view_items: ~[],
+                stmts: stmts,
+                expr: None,
+                id: self.next_id(),
+                rules: ast::default_blk},
+         span: span}
     }
 
-    fn clone(v: @ast::expr) -> @ast::expr {
-        let fld = self.clone_folder();
-        fld.fold_expr(v)
+    fn expr_blk(expr: @ast::expr) -> ast::blk {
+        {node: {view_items: ~[],
+                stmts: ~[],
+                expr: Some(expr),
+                id: self.next_id(),
+                rules: ast::default_blk},
+         span: expr.span}
     }
 
-    fn clone_ty(v: @ast::ty) -> @ast::ty {
-        let fld = self.clone_folder();
-        fld.fold_ty(v)
+    fn expr_path(span: span, strs: ~[ast::ident]) -> @ast::expr {
+        self.expr(span, ast::expr_path(self.path(span, strs)))
     }
 
-    fn clone_ty_param(v: ast::ty_param) -> ast::ty_param {
-        let fld = self.clone_folder();
-        fold::fold_ty_param(v, fld)
+    fn expr_var(span: span, var: ~str) -> @ast::expr {
+        self.expr_path(span, ~[self.ident_of(var)])
     }
 
-    fn at(span: span, expr: @ast::expr) -> @ast::expr {
-        fn repl_sp(old_span: span, repl_span: span, with_span: span) -> span {
-            if old_span == repl_span {
-                with_span
-            } else {
-                old_span
-            }
-        }
-
-        let fld = fold::make_fold(@{
-            new_span: |a| repl_sp(a, ast_util::dummy_sp(), span),
-            .. *fold::default_ast_fold()
-        });
+    fn expr_field(
+        span: span,
+        expr: @ast::expr,
+        ident: ast::ident
+    ) -> @ast::expr {
+        self.expr(span, ast::expr_field(expr, ident, ~[]))
+    }
 
-        fld.fold_expr(expr)
+    fn expr_call(
+        span: span,
+        expr: @ast::expr,
+        args: ~[@ast::expr]
+    ) -> @ast::expr {
+        self.expr(span, ast::expr_call(expr, args, false))
     }
-}
 
-fn ser_path(cx: ext_ctxt, tps: ser_tps_map, path: @ast::path,
-                  -s: @ast::expr, -v: @ast::expr)
-    -> ~[@ast::stmt] {
-    let ext_cx = cx; // required for #ast{}
-
-    // We want to take a path like a::b::c<...> and generate a call
-    // like a::b::c::serialize(s, ...), as described above.
-
-    let callee =
-        cx.expr(
-            path.span,
-            ast::expr_path(
-                cx.helper_path(path, ~"serialize")));
-
-    let ty_args = do vec::map(path.types) |ty| {
-        let sv_stmts = ser_ty(cx, tps, *ty, cx.clone(s), #ast{ __v });
-        let sv = cx.expr(path.span,
-                         ast::expr_block(cx.blk(path.span, sv_stmts)));
-        cx.at(ty.span, #ast{ |__v| $(sv) })
-    };
+    fn lambda_expr(expr: @ast::expr) -> @ast::expr {
+        self.lambda(self.expr_blk(expr))
+    }
 
-    ~[cx.stmt(
-        cx.expr(
-            path.span,
-            ast::expr_call(callee, vec::append(~[s, v], ty_args), false)))]
+    fn lambda_stmts(span: span, stmts: ~[@ast::stmt]) -> @ast::expr {
+        self.lambda(self.blk(span, stmts))
+    }
 }
 
-fn ser_variant(cx: ext_ctxt,
-               tps: ser_tps_map,
-               tys: ~[@ast::ty],
-               span: span,
-               -s: @ast::expr,
-               pfn: fn(~[@ast::pat]) -> ast::pat_,
-               bodyfn: fn(-v: @ast::expr, ast::blk) -> @ast::expr,
-               argfn: fn(-v: @ast::expr, uint, ast::blk) -> @ast::expr)
-    -> ast::arm {
-    let vnames = do vec::from_fn(vec::len(tys)) |i| {
-        cx.parse_sess().interner.intern(@fmt!("__v%u", i))
-    };
-    let pats = do vec::from_fn(vec::len(tys)) |i| {
-        cx.binder_pat(tys[i].span, vnames[i])
-    };
-    let pat: @ast::pat = @{id: cx.next_id(), node: pfn(pats), span: span};
-    let stmts = do vec::from_fn(vec::len(tys)) |i| {
-        let v = cx.var_ref(span, vnames[i]);
-        let arg_blk =
-            cx.blk(
-                span,
-                ser_ty(cx, tps, tys[i], cx.clone(s), move v));
-        cx.stmt(argfn(cx.clone(s), i, arg_blk))
-    };
-
-    let body_blk = cx.blk(span, stmts);
-    let body = cx.blk(span, ~[cx.stmt(bodyfn(move s, body_blk))]);
+fn mk_impl(
+    cx: ext_ctxt,
+    span: span,
+    ident: ast::ident,
+    ty_param: ast::ty_param,
+    path: @ast::path,
+    tps: ~[ast::ty_param],
+    f: fn(@ast::Ty) -> @ast::method
+) -> @ast::item {
+    // All the type parameters need to bound to the trait.
+    let mut trait_tps = vec::append(
+        ~[ty_param],
+         do tps.map |tp| {
+            let t_bound = ast::ty_param_bound(@{
+                id: cx.next_id(),
+                node: ast::ty_path(path, cx.next_id()),
+                span: span,
+            });
 
-    {pats: ~[pat], guard: None, body: body}
+            {
+                ident: tp.ident,
+                id: cx.next_id(),
+                bounds: @vec::append(~[t_bound], *tp.bounds)
+            }
+        }
+    );
+
+    let opt_trait = Some(@{
+        path: path,
+        ref_id: cx.next_id(),
+        impl_id: cx.next_id(),
+    });
+
+    let ty = cx.ty_path(
+        span,
+        ~[ident],
+        tps.map(|tp| cx.ty_path(span, ~[tp.ident], ~[]))
+    );
+
+    @{
+        // This is a new-style impl declaration.
+        // XXX: clownshoes
+        ident: ast::token::special_idents::clownshoes_extensions,
+        attrs: ~[],
+        id: cx.next_id(),
+        node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]),
+        vis: ast::public,
+        span: span,
+    }
 }
 
-fn ser_lambda(cx: ext_ctxt, tps: ser_tps_map, ty: @ast::ty,
-              -s: @ast::expr, -v: @ast::expr) -> @ast::expr {
-    cx.lambda(cx.blk(ty.span, ser_ty(cx, tps, ty, move s, move v)))
+fn mk_ser_impl(
+    cx: ext_ctxt,
+    span: span,
+    ident: ast::ident,
+    tps: ~[ast::ty_param],
+    body: @ast::expr
+) -> @ast::item {
+    // Make a path to the std::serialization::Serializable typaram.
+    let ty_param = cx.bind_path(
+        span,
+        cx.ident_of(~"__S"),
+        cx.path(
+            span,
+            ~[
+                cx.ident_of(~"std"),
+                cx.ident_of(~"serialization"),
+                cx.ident_of(~"Serializer"),
+            ]
+        ),
+        @~[]
+    );
+
+    // Make a path to the std::serialization::Serializable trait.
+    let path = cx.path_tps(
+        span,
+        ~[
+            cx.ident_of(~"std"),
+            cx.ident_of(~"serialization"),
+            cx.ident_of(~"Serializable"),
+        ],
+        ~[cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[])]
+    );
+
+    mk_impl(
+        cx,
+        span,
+        ident,
+        ty_param,
+        path,
+        tps,
+        |_ty| mk_ser_method(cx, span, cx.expr_blk(body))
+    )
 }
 
-fn is_vec_or_str(ty: @ast::ty) -> bool {
-    match ty.node {
-      ast::ty_vec(_) => true,
-      // This may be wrong if the user has shadowed (!) str
-      ast::ty_path(@{span: _, global: _, idents: ids,
-                             rp: None, types: _}, _)
-      if ids == ~[parse::token::special_idents::str] => true,
-      _ => false
-    }
+fn mk_deser_impl(
+    cx: ext_ctxt,
+    span: span,
+    ident: ast::ident,
+    tps: ~[ast::ty_param],
+    body: @ast::expr
+) -> @ast::item {
+    // Make a path to the std::serialization::Deserializable typaram.
+    let ty_param = cx.bind_path(
+        span,
+        cx.ident_of(~"__D"),
+        cx.path(
+            span,
+            ~[
+                cx.ident_of(~"std"),
+                cx.ident_of(~"serialization"),
+                cx.ident_of(~"Deserializer"),
+            ]
+        ),
+        @~[]
+    );
+
+    // Make a path to the std::serialization::Deserializable trait.
+    let path = cx.path_tps(
+        span,
+        ~[
+            cx.ident_of(~"std"),
+            cx.ident_of(~"serialization"),
+            cx.ident_of(~"Deserializable"),
+        ],
+        ~[cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[])]
+    );
+
+    mk_impl(
+        cx,
+        span,
+        ident,
+        ty_param,
+        path,
+        tps,
+        |ty| mk_deser_method(cx, span, ty, cx.expr_blk(body))
+    )
 }
 
-fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
-          ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
-    -> ~[@ast::stmt] {
-
-    let ext_cx = cx; // required for #ast{}
-
-    match ty.node {
-      ast::ty_nil => {
-        ~[#ast[stmt]{$(s).emit_nil()}]
-      }
-
-      ast::ty_bot => {
-        cx.span_err(
-            ty.span, fmt!("Cannot serialize bottom type"));
-        ~[]
-      }
-
-      ast::ty_box(mt) => {
-        let l = ser_lambda(cx, tps, mt.ty, cx.clone(s), #ast{ *$(v) });
-        ~[#ast[stmt]{$(s).emit_box($(l));}]
-      }
-
-      // For unique evecs/estrs, just pass through to underlying vec or str
-      ast::ty_uniq(mt) if is_vec_or_str(mt.ty) => {
-        ser_ty(cx, tps, mt.ty, move s, move v)
-      }
-
-      ast::ty_uniq(mt) => {
-        let l = ser_lambda(cx, tps, mt.ty, cx.clone(s), #ast{ *$(v) });
-        ~[#ast[stmt]{$(s).emit_uniq($(l));}]
-      }
-
-      ast::ty_ptr(_) | ast::ty_rptr(_, _) => {
-        cx.span_err(ty.span, ~"cannot serialize pointer types");
-        ~[]
-      }
-
-      ast::ty_rec(flds) => {
-        let fld_stmts = do vec::from_fn(vec::len(flds)) |fidx| {
-            let fld = flds[fidx];
-            let vf = cx.expr(fld.span,
-                             ast::expr_field(cx.clone(v),
-                                             fld.node.ident,
-                                             ~[]));
-            let s = cx.clone(s);
-            let f = cx.lit_str(fld.span, cx.parse_sess().interner.get(
-                fld.node.ident));
-            let i = cx.lit_uint(fld.span, fidx);
-            let l = ser_lambda(cx, tps, fld.node.mt.ty, cx.clone(s), move vf);
-            #ast[stmt]{$(s).emit_rec_field($(f), $(i), $(l));}
-        };
-        let fld_lambda = cx.lambda(cx.blk(ty.span, fld_stmts));
-        ~[#ast[stmt]{$(s).emit_rec($(fld_lambda));}]
-      }
-
-      ast::ty_fn(*) => {
-        cx.span_err(ty.span, ~"cannot serialize function types");
-        ~[]
-      }
-
-      ast::ty_tup(tys) => {
-        // Generate code like
-        //
-        // match v {
-        //    (v1, v2, v3) {
-        //       .. serialize v1, v2, v3 ..
-        //    }
-        // };
-
-        let arms = ~[
-            ser_variant(
-
-                cx, tps, tys, ty.span, move s,
-
-                // Generate pattern (v1, v2, v3)
-                |pats| ast::pat_tup(pats),
-
-                // Generate body s.emit_tup(3, {|| blk })
-                |-s, blk| {
-                    let sz = cx.lit_uint(ty.span, vec::len(tys));
-                    let body = cx.lambda(blk);
-                    #ast{ $(s).emit_tup($(sz), $(body)) }
-                },
-
-                // Generate s.emit_tup_elt(i, {|| blk })
-                |-s, i, blk| {
-                    let idx = cx.lit_uint(ty.span, i);
-                    let body = cx.lambda(blk);
-                    #ast{ $(s).emit_tup_elt($(idx), $(body)) }
-                })
-        ];
-        ~[cx.alt_stmt(arms, ty.span, move v)]
-      }
-
-      ast::ty_path(path, _) => {
-        if path.idents.len() == 1 && path.types.is_empty() {
-            let ident = path.idents[0];
-
-            match tps.find(ident) {
-              Some(f) => f(v),
-              None => ser_path(cx, tps, path, move s, move v)
+fn mk_ser_method(
+    cx: ext_ctxt,
+    span: span,
+    ser_body: ast::blk
+) -> @ast::method {
+    let ty_s = @{
+        id: cx.next_id(),
+        node: ast::ty_rptr(
+            @{
+                id: cx.next_id(),
+                node: ast::re_anon,
+            },
+            {
+                ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]),
+                mutbl: ast::m_imm
             }
-        } else {
-            ser_path(cx, tps, path, move s, move v)
-        }
-      }
+        ),
+        span: span,
+    };
 
-      ast::ty_mac(_) => {
-        cx.span_err(ty.span, ~"cannot serialize macro types");
-        ~[]
-      }
+    let ser_inputs = ~[{
+        mode: ast::infer(cx.next_id()),
+        ty: ty_s,
+        ident: cx.ident_of(~"__s"),
+        id: cx.next_id(),
+    }];
+
+    let ser_output = @{
+        id: cx.next_id(),
+        node: ast::ty_nil,
+        span: span,
+    };
 
-      ast::ty_infer => {
-        cx.span_err(ty.span, ~"cannot serialize inferred types");
-        ~[]
-      }
+    let ser_decl = {
+        inputs: ser_inputs,
+        output: ser_output,
+        cf: ast::return_val,
+    };
 
-      ast::ty_vec(mt) => {
-        let ser_e =
-            cx.expr(
-                ty.span,
-                ast::expr_block(
-                    cx.blk(
-                        ty.span,
-                        ser_ty(
-                            cx, tps, mt.ty,
-                            cx.clone(s),
-                            cx.at(ty.span, #ast{ __e })))));
-
-        ~[#ast[stmt]{
-            std::serialization::emit_from_vec($(s), $(v), |__e| $(ser_e))
-        }]
-      }
-
-      ast::ty_fixed_length(_, _) => {
-        cx.span_unimpl(ty.span, ~"serialization for fixed length types");
-      }
+    @{
+        ident: cx.ident_of(~"serialize"),
+        attrs: ~[],
+        tps: ~[],
+        self_ty: { node: ast::sty_region(ast::m_imm), span: span },
+        purity: ast::impure_fn,
+        decl: ser_decl,
+        body: ser_body,
+        id: cx.next_id(),
+        span: span,
+        self_id: cx.next_id(),
+        vis: ast::public,
     }
 }
 
-fn mk_ser_fn(cx: ext_ctxt, span: span, name: ast::ident,
-             tps: ~[ast::ty_param],
-             f: fn(ext_ctxt, ser_tps_map,
-                   -v: @ast::expr, -v: @ast::expr) -> ~[@ast::stmt])
-    -> @ast::item {
-    let ext_cx = cx; // required for #ast
-
-    let tp_types = vec::map(tps, |tp| cx.ty_path(span, ~[tp.ident], ~[]));
-    let v_ty = cx.ty_path(span, ~[name], tp_types);
-
-    let tp_inputs =
-        vec::map(tps, |tp|
-            {mode: ast::expl(ast::by_ref),
-             ty: cx.ty_fn(span,
-                          ~[cx.ty_path(span, ~[tp.ident], ~[])],
-                          cx.ty_nil(span)),
-             ident: cx.ident_of(~"__s" + cx.str_of(tp.ident)),
-             id: cx.next_id()});
-
-    debug!("tp_inputs = %?", tp_inputs);
-
-
-    let ser_inputs: ~[ast::arg] =
-        vec::append(~[{mode: ast::expl(ast::by_ref),
-                      ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]),
-                      ident: cx.ident_of(~"__s"),
-                      id: cx.next_id()},
-                     {mode: ast::expl(ast::by_ref),
-                      ty: v_ty,
-                      ident: cx.ident_of(~"__v"),
-                      id: cx.next_id()}],
-                    tp_inputs);
-
-    let tps_map = map::HashMap();
-    for vec::each2(tps, tp_inputs) |tp, arg| {
-        let arg_ident = arg.ident;
-        tps_map.insert(
-            tp.ident,
-            fn@(v: @ast::expr) -> ~[@ast::stmt] {
-                let f = cx.var_ref(span, arg_ident);
-                debug!("serializing type arg %s", cx.str_of(arg_ident));
-                ~[#ast[stmt]{$(f)($(v));}]
-            });
-    }
+fn mk_deser_method(
+    cx: ext_ctxt,
+    span: span,
+    ty: @ast::Ty,
+    deser_body: ast::blk
+) -> @ast::method {
+    let ty_d = @{
+        id: cx.next_id(),
+        node: ast::ty_rptr(
+            @{
+                id: cx.next_id(),
+                node: ast::re_anon,
+            },
+            {
+                ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]),
+                mutbl: ast::m_imm
+            }
+        ),
+        span: span,
+    };
 
-    let ser_bnds = @~[
-        ast::bound_trait(cx.ty_path(span,
-                                    ~[cx.ident_of(~"std"),
-                                      cx.ident_of(~"serialization"),
-                                      cx.ident_of(~"Serializer")],
-                                    ~[]))];
-
-    let ser_tps: ~[ast::ty_param] =
-        vec::append(~[{ident: cx.ident_of(~"__S"),
-                      id: cx.next_id(),
-                      bounds: ser_bnds}],
-                    vec::map(tps, |tp| cx.clone_ty_param(*tp)));
-
-    let ser_output: @ast::ty = @{id: cx.next_id(),
-                                 node: ast::ty_nil,
-                                 span: span};
-
-    let ser_blk = cx.blk(span,
-                         f(cx, tps_map, #ast{ __s }, #ast{ __v }));
-
-    @{ident: cx.ident_of(~"serialize_" + cx.str_of(name)),
-      attrs: ~[],
-      id: cx.next_id(),
-      node: ast::item_fn({inputs: ser_inputs,
-                          output: ser_output,
-                          cf: ast::return_val},
-                         ast::impure_fn,
-                         ser_tps,
-                         ser_blk),
-      vis: ast::public,
-      span: span}
+    let deser_inputs = ~[{
+        mode: ast::infer(cx.next_id()),
+        ty: ty_d,
+        ident: cx.ident_of(~"__d"),
+        id: cx.next_id(),
+    }];
+
+    let deser_decl = {
+        inputs: deser_inputs,
+        output: ty,
+        cf: ast::return_val,
+    };
+
+    @{
+        ident: cx.ident_of(~"deserialize"),
+        attrs: ~[],
+        tps: ~[],
+        self_ty: { node: ast::sty_static, span: span },
+        purity: ast::impure_fn,
+        decl: deser_decl,
+        body: deser_body,
+        id: cx.next_id(),
+        span: span,
+        self_id: cx.next_id(),
+        vis: ast::public,
+    }
 }
 
-// ______________________________________________________________________
+fn mk_rec_ser_impl(
+    cx: ext_ctxt,
+    span: span,
+    ident: ast::ident,
+    fields: ~[ast::ty_field],
+    tps: ~[ast::ty_param]
+) -> @ast::item {
+    let fields = mk_ser_fields(cx, span, mk_rec_fields(fields));
+
+    // ast for `__s.emit_rec(|| $(fields))`
+    let body = cx.expr_call(
+        span,
+        cx.expr_field(
+            span,
+            cx.expr_var(span, ~"__s"),
+            cx.ident_of(~"emit_rec")
+        ),
+        ~[cx.lambda_stmts(span, fields)]
+    );
 
-fn deser_path(cx: ext_ctxt, tps: deser_tps_map, path: @ast::path,
-                    -d: @ast::expr) -> @ast::expr {
-    // We want to take a path like a::b::c<...> and generate a call
-    // like a::b::c::deserialize(d, ...), as described above.
+    mk_ser_impl(cx, span, ident, tps, body)
+}
 
-    let callee =
-        cx.expr(
-            path.span,
-            ast::expr_path(
-                cx.helper_path(path, ~"deserialize")));
+fn mk_rec_deser_impl(
+    cx: ext_ctxt,
+    span: span,
+    ident: ast::ident,
+    fields: ~[ast::ty_field],
+    tps: ~[ast::ty_param]
+) -> @ast::item {
+    let fields = mk_deser_fields(cx, span, mk_rec_fields(fields));
+
+    // ast for `read_rec(|| $(fields))`
+    let body = cx.expr_call(
+        span,
+        cx.expr_field(
+            span,
+            cx.expr_var(span, ~"__d"),
+            cx.ident_of(~"read_rec")
+        ),
+        ~[
+            cx.lambda_expr(
+                cx.expr(
+                    span,
+                    ast::expr_rec(fields, None)
+                )
+            )
+        ]
+    );
 
-    let ty_args = do vec::map(path.types) |ty| {
-        let dv_expr = deser_ty(cx, tps, *ty, cx.clone(d));
-        cx.lambda(cx.expr_blk(dv_expr))
-    };
+    mk_deser_impl(cx, span, ident, tps, body)
+}
 
-    cx.expr(path.span, ast::expr_call(callee, vec::append(~[d], ty_args),
-                                      false))
+fn mk_struct_ser_impl(
+    cx: ext_ctxt,
+    span: span,
+    ident: ast::ident,
+    fields: ~[@ast::struct_field],
+    tps: ~[ast::ty_param]
+) -> @ast::item {
+    let fields = mk_ser_fields(cx, span, mk_struct_fields(fields));
+
+    // ast for `__s.emit_struct($(name), || $(fields))`
+    let ser_body = cx.expr_call(
+        span,
+        cx.expr_field(
+            span,
+            cx.expr_var(span, ~"__s"),
+            cx.ident_of(~"emit_struct")
+        ),
+        ~[
+            cx.lit_str(span, @cx.str_of(ident)),
+            cx.lambda_stmts(span, fields),
+        ]
+    );
+
+    mk_ser_impl(cx, span, ident, tps, ser_body)
 }
 
-fn deser_lambda(cx: ext_ctxt, tps: deser_tps_map, ty: @ast::ty,
-                -d: @ast::expr) -> @ast::expr {
-    cx.lambda(cx.expr_blk(deser_ty(cx, tps, ty, move d)))
+fn mk_struct_deser_impl(
+    cx: ext_ctxt,
+    span: span,
+    ident: ast::ident,
+    fields: ~[@ast::struct_field],
+    tps: ~[ast::ty_param]
+) -> @ast::item {
+    let fields = mk_deser_fields(cx, span, mk_struct_fields(fields));
+
+    // ast for `read_struct($(name), || $(fields))`
+    let body = cx.expr_call(
+        span,
+        cx.expr_field(
+            span,
+            cx.expr_var(span, ~"__d"),
+            cx.ident_of(~"read_struct")
+        ),
+        ~[
+            cx.lit_str(span, @cx.str_of(ident)),
+            cx.lambda_expr(
+                cx.expr(
+                    span,
+                    ast::expr_struct(
+                        cx.path(span, ~[ident]),
+                        fields,
+                        None
+                    )
+                )
+            ),
+        ]
+    );
+
+    mk_deser_impl(cx, span, ident, tps, body)
 }
 
-fn deser_ty(cx: ext_ctxt, tps: deser_tps_map,
-                  ty: @ast::ty, -d: @ast::expr) -> @ast::expr {
-
-    let ext_cx = cx; // required for #ast{}
-
-    match ty.node {
-      ast::ty_nil => {
-        #ast{ $(d).read_nil() }
-      }
-
-      ast::ty_bot => {
-        #ast{ fail }
-      }
-
-      ast::ty_box(mt) => {
-        let l = deser_lambda(cx, tps, mt.ty, cx.clone(d));
-        #ast{ @$(d).read_box($(l)) }
-      }
-
-      // For unique evecs/estrs, just pass through to underlying vec or str
-      ast::ty_uniq(mt) if is_vec_or_str(mt.ty) => {
-        deser_ty(cx, tps, mt.ty, move d)
-      }
-
-      ast::ty_uniq(mt) => {
-        let l = deser_lambda(cx, tps, mt.ty, cx.clone(d));
-        #ast{ ~$(d).read_uniq($(l)) }
-      }
-
-      ast::ty_ptr(_) | ast::ty_rptr(_, _) => {
-        #ast{ fail }
-      }
-
-      ast::ty_rec(flds) => {
-        let fields = do vec::from_fn(vec::len(flds)) |fidx| {
-            let fld = flds[fidx];
-            let d = cx.clone(d);
-            let f = cx.lit_str(fld.span, @cx.str_of(fld.node.ident));
-            let i = cx.lit_uint(fld.span, fidx);
-            let l = deser_lambda(cx, tps, fld.node.mt.ty, cx.clone(d));
-            {node: {mutbl: fld.node.mt.mutbl,
-                    ident: fld.node.ident,
-                    expr: #ast{ $(d).read_rec_field($(f), $(i), $(l))} },
-             span: fld.span}
-        };
-        let fld_expr = cx.expr(ty.span, ast::expr_rec(fields, None));
-        let fld_lambda = cx.lambda(cx.expr_blk(fld_expr));
-        #ast{ $(d).read_rec($(fld_lambda)) }
-      }
-
-      ast::ty_fn(*) => {
-        #ast{ fail }
-      }
-
-      ast::ty_tup(tys) => {
-        // Generate code like
-        //
-        // d.read_tup(3u) {||
-        //   (d.read_tup_elt(0u, {||...}),
-        //    d.read_tup_elt(1u, {||...}),
-        //    d.read_tup_elt(2u, {||...}))
-        // }
-
-        let arg_exprs = do vec::from_fn(vec::len(tys)) |i| {
-            let idx = cx.lit_uint(ty.span, i);
-            let body = deser_lambda(cx, tps, tys[i], cx.clone(d));
-            #ast{ $(d).read_tup_elt($(idx), $(body)) }
-        };
-        let body =
-            cx.lambda(cx.expr_blk(
-                cx.expr(ty.span, ast::expr_tup(arg_exprs))));
-        let sz = cx.lit_uint(ty.span, vec::len(tys));
-        #ast{ $(d).read_tup($(sz), $(body)) }
-      }
-
-      ast::ty_path(path, _) => {
-        if vec::len(path.idents) == 1u &&
-            vec::is_empty(path.types) {
-            let ident = path.idents[0];
-
-            match tps.find(ident) {
-              Some(f) => f(),
-              None => deser_path(cx, tps, path, move d)
-            }
-        } else {
-            deser_path(cx, tps, path, move d)
+// Records and structs don't have the same fields types, but they share enough
+// that if we extract the right subfields out we can share the serialization
+// generator code.
+type field = { span: span, ident: ast::ident, mutbl: ast::mutability };
+
+fn mk_rec_fields(fields: ~[ast::ty_field]) -> ~[field] {
+    do fields.map |field| {
+        {
+            span: field.span,
+            ident: field.node.ident,
+            mutbl: field.node.mt.mutbl,
         }
-      }
-
-      ast::ty_mac(_) => {
-        #ast{ fail }
-      }
-
-      ast::ty_infer => {
-        #ast{ fail }
-      }
+    }
+}
 
-      ast::ty_vec(mt) => {
-        let l = deser_lambda(cx, tps, mt.ty, cx.clone(d));
-        #ast{ std::serialization::read_to_vec($(d), $(l)) }
-      }
+fn mk_struct_fields(fields: ~[@ast::struct_field]) -> ~[field] {
+    do fields.map |field| {
+        let (ident, mutbl) = match field.node.kind {
+            ast::named_field(ident, mutbl, _) => (ident, mutbl),
+            _ => fail ~"[auto_serialize] does not support \
+                        unnamed fields",
+        };
 
-      ast::ty_fixed_length(_, _) => {
-        cx.span_unimpl(ty.span, ~"deserialization for fixed length types");
-      }
+        {
+            span: field.span,
+            ident: ident,
+            mutbl: match mutbl {
+                ast::class_mutable => ast::m_mutbl,
+                ast::class_immutable => ast::m_imm,
+            },
+        }
     }
 }
 
-fn mk_deser_fn(cx: ext_ctxt, span: span,
-               name: ast::ident, tps: ~[ast::ty_param],
-               f: fn(ext_ctxt, deser_tps_map, -v: @ast::expr) -> @ast::expr)
-    -> @ast::item {
-    let ext_cx = cx; // required for #ast
-
-    let tp_types = vec::map(tps, |tp| cx.ty_path(span, ~[tp.ident], ~[]));
-    let v_ty = cx.ty_path(span, ~[name], tp_types);
-
-    let tp_inputs =
-        vec::map(tps, |tp|
-            {mode: ast::expl(ast::by_ref),
-             ty: cx.ty_fn(span,
-                          ~[],
-                          cx.ty_path(span, ~[tp.ident], ~[])),
-             ident: cx.ident_of(~"__d" + cx.str_of(tp.ident)),
-             id: cx.next_id()});
-
-    debug!("tp_inputs = %?", tp_inputs);
-
-    let deser_inputs: ~[ast::arg] =
-        vec::append(~[{mode: ast::expl(ast::by_ref),
-                      ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]),
-                      ident: cx.ident_of(~"__d"),
-                      id: cx.next_id()}],
-                    tp_inputs);
-
-    let tps_map = map::HashMap();
-    for vec::each2(tps, tp_inputs) |tp, arg| {
-        let arg_ident = arg.ident;
-        tps_map.insert(
-            tp.ident,
-            fn@() -> @ast::expr {
-                let f = cx.var_ref(span, arg_ident);
-                #ast{ $(f)() }
-            });
+fn mk_ser_fields(
+    cx: ext_ctxt,
+    span: span,
+    fields: ~[field]
+) -> ~[@ast::stmt] {
+    do fields.mapi |idx, field| {
+        // ast for `|| self.$(name).serialize(__s)`
+        let expr_lambda = cx.lambda_expr(
+            cx.expr_call(
+                span,
+                cx.expr_field(
+                    span,
+                    cx.expr_field(
+                        span,
+                        cx.expr_var(span, ~"self"),
+                        field.ident
+                    ),
+                    cx.ident_of(~"serialize")
+                ),
+                ~[cx.expr_var(span, ~"__s")]
+            )
+        );
+
+        // ast for `__s.emit_field($(name), $(idx), $(expr_lambda))`
+        cx.stmt(
+            cx.expr_call(
+                span,
+                cx.expr_field(
+                    span,
+                    cx.expr_var(span, ~"__s"),
+                    cx.ident_of(~"emit_field")
+                ),
+                ~[
+                    cx.lit_str(span, @cx.str_of(field.ident)),
+                    cx.lit_uint(span, idx),
+                    expr_lambda,
+                ]
+            )
+        )
     }
+}
 
-    let deser_bnds = @~[
-        ast::bound_trait(cx.ty_path(
+fn mk_deser_fields(
+    cx: ext_ctxt,
+    span: span,
+    fields: ~[{ span: span, ident: ast::ident, mutbl: ast::mutability }]
+) -> ~[ast::field] {
+    do fields.mapi |idx, field| {
+        // ast for `|| std::serialization::deserialize(__d)`
+        let expr_lambda = cx.lambda(
+            cx.expr_blk(
+                cx.expr_call(
+                    span,
+                    cx.expr_path(span, ~[
+                        cx.ident_of(~"std"),
+                        cx.ident_of(~"serialization"),
+                        cx.ident_of(~"deserialize"),
+                    ]),
+                    ~[cx.expr_var(span, ~"__d")]
+                )
+            )
+        );
+
+        // ast for `__d.read_field($(name), $(idx), $(expr_lambda))`
+        let expr: @ast::expr = cx.expr_call(
             span,
-            ~[cx.ident_of(~"std"), cx.ident_of(~"serialization"),
-              cx.ident_of(~"Deserializer")],
-            ~[]))];
-
-    let deser_tps: ~[ast::ty_param] =
-        vec::append(~[{ident: cx.ident_of(~"__D"),
-                      id: cx.next_id(),
-                      bounds: deser_bnds}],
-                    vec::map(tps, |tp| {
-                        let cloned = cx.clone_ty_param(*tp);
-                        {bounds: @(vec::append(*cloned.bounds,
-                                               ~[ast::bound_copy])),
-                         .. cloned}
-                    }));
-
-    let deser_blk = cx.expr_blk(f(cx, tps_map, #ast[expr]{__d}));
-
-    @{ident: cx.ident_of(~"deserialize_" + cx.str_of(name)),
-      attrs: ~[],
-      id: cx.next_id(),
-      node: ast::item_fn({inputs: deser_inputs,
-                          output: v_ty,
-                          cf: ast::return_val},
-                         ast::impure_fn,
-                         deser_tps,
-                         deser_blk),
-      vis: ast::public,
-      span: span}
+            cx.expr_field(
+                span,
+                cx.expr_var(span, ~"__d"),
+                cx.ident_of(~"read_field")
+            ),
+            ~[
+                cx.lit_str(span, @cx.str_of(field.ident)),
+                cx.lit_uint(span, idx),
+                expr_lambda,
+            ]
+        );
+
+        {
+            node: { mutbl: field.mutbl, ident: field.ident, expr: expr },
+            span: span,
+        }
+    }
 }
 
-fn ty_fns(cx: ext_ctxt, name: ast::ident,
-          ty: @ast::ty, tps: ~[ast::ty_param])
-    -> ~[@ast::item] {
+fn mk_enum_ser_impl(
+    cx: ext_ctxt,
+    span: span,
+    ident: ast::ident,
+    enum_def: ast::enum_def,
+    tps: ~[ast::ty_param]
+) -> @ast::item {
+    let body = mk_enum_ser_body(
+        cx,
+        span,
+        ident,
+        enum_def.variants
+    );
+
+    mk_ser_impl(cx, span, ident, tps, body)
+}
 
-    let span = ty.span;
-    ~[
-        mk_ser_fn(cx, span, name, tps, |a,b,c,d| ser_ty(a, b, ty, move c,
-                                                        move d)),
-        mk_deser_fn(cx, span, name, tps, |a,b,c| deser_ty(a, b, ty, move c))
-    ]
+fn mk_enum_deser_impl(
+    cx: ext_ctxt,
+    span: span,
+    ident: ast::ident,
+    enum_def: ast::enum_def,
+    tps: ~[ast::ty_param]
+) -> @ast::item {
+    let body = mk_enum_deser_body(
+        cx,
+        span,
+        ident,
+        enum_def.variants
+    );
+
+    mk_deser_impl(cx, span, ident, tps, body)
 }
 
-fn ser_enum(cx: ext_ctxt, tps: ser_tps_map, e_name: ast::ident,
-            e_span: span, variants: ~[ast::variant],
-            -s: @ast::expr, -v: @ast::expr) -> ~[@ast::stmt] {
-    let ext_cx = cx;
-    let arms = do vec::from_fn(vec::len(variants)) |vidx| {
-        let variant = variants[vidx];
-        let v_span = variant.span;
-        let v_name = variant.node.name;
+fn ser_variant(
+    cx: ext_ctxt,
+    span: span,
+    v_name: ast::ident,
+    v_idx: uint,
+    args: ~[ast::variant_arg]
+) -> ast::arm {
+    // Name the variant arguments.
+    let names = args.mapi(|i, _arg| cx.ident_of(fmt!("__v%u", i)));
+
+    // Bind the names to the variant argument type.
+    let pats = args.mapi(|i, arg| cx.binder_pat(arg.ty.span, names[i]));
+
+    let pat_node = if pats.is_empty() {
+        ast::pat_ident(
+            ast::bind_by_implicit_ref,
+            cx.path(span, ~[v_name]),
+            None
+        )
+    } else {
+        ast::pat_enum(
+            cx.path(span, ~[v_name]),
+            Some(pats)
+        )
+    };
 
-        match variant.node.kind {
-            ast::tuple_variant_kind(args) => {
-                let variant_tys = vec::map(args, |a| a.ty);
-
-                ser_variant(
-                    cx, tps, variant_tys, v_span, cx.clone(s),
-
-                    // Generate pattern var(v1, v2, v3)
-                    |pats| {
-                        if vec::is_empty(pats) {
-                            ast::pat_ident(ast::bind_by_implicit_ref,
-                                           cx.path(v_span, ~[v_name]),
-                                           None)
-                        } else {
-                            ast::pat_enum(cx.path(v_span, ~[v_name]),
-                                                  Some(pats))
-                        }
-                    },
+    let pat = @{
+        id: cx.next_id(),
+        node: pat_node,
+        span: span,
+    };
 
-                    // Generate body s.emit_enum_variant("foo", 0u,
-                    //                                   3u, {|| blk })
-                    |-s, blk| {
-                        let v_name = cx.lit_str(v_span, @cx.str_of(v_name));
-                        let v_id = cx.lit_uint(v_span, vidx);
-                        let sz = cx.lit_uint(v_span, vec::len(variant_tys));
-                        let body = cx.lambda(blk);
-                        #ast[expr]{
-                            $(s).emit_enum_variant($(v_name), $(v_id),
-                                                   $(sz), $(body))
-                        }
-                    },
+    let stmts = do args.mapi |a_idx, _arg| {
+        // ast for `__s.emit_enum_variant_arg`
+        let expr_emit = cx.expr_field(
+            span,
+            cx.expr_var(span, ~"__s"),
+            cx.ident_of(~"emit_enum_variant_arg")
+        );
 
-                    // Generate s.emit_enum_variant_arg(i, {|| blk })
-                    |-s, i, blk| {
-                        let idx = cx.lit_uint(v_span, i);
-                        let body = cx.lambda(blk);
-                        #ast[expr]{
-                            $(s).emit_enum_variant_arg($(idx), $(body))
-                        }
-                    })
-            }
-            _ =>
-                fail ~"struct variants unimplemented for auto serialize"
-        }
+        // ast for `|| $(v).serialize(__s)`
+        let expr_serialize = cx.lambda_expr(
+             cx.expr_call(
+                span,
+                cx.expr_field(
+                    span,
+                    cx.expr_path(span, ~[names[a_idx]]),
+                    cx.ident_of(~"serialize")
+                ),
+                ~[cx.expr_var(span, ~"__s")]
+            )
+        );
+
+        // ast for `$(expr_emit)($(a_idx), $(expr_serialize))`
+        cx.stmt(
+            cx.expr_call(
+                span,
+                expr_emit,
+                ~[cx.lit_uint(span, a_idx), expr_serialize]
+            )
+        )
     };
-    let lam = cx.lambda(cx.blk(e_span, ~[cx.alt_stmt(arms, e_span, move v)]));
-    let e_name = cx.lit_str(e_span, @cx.str_of(e_name));
-    ~[#ast[stmt]{ $(s).emit_enum($(e_name), $(lam)) }]
-}
 
-fn deser_enum(cx: ext_ctxt, tps: deser_tps_map, e_name: ast::ident,
-              e_span: span, variants: ~[ast::variant],
-              -d: @ast::expr) -> @ast::expr {
-    let ext_cx = cx;
-    let mut arms: ~[ast::arm] = do vec::from_fn(vec::len(variants)) |vidx| {
-        let variant = variants[vidx];
-        let v_span = variant.span;
-        let v_name = variant.node.name;
+    // ast for `__s.emit_enum_variant($(name), $(idx), $(sz), $(lambda))`
+    let body = cx.expr_call(
+        span,
+        cx.expr_field(
+            span,
+            cx.expr_var(span, ~"__s"),
+            cx.ident_of(~"emit_enum_variant")
+        ),
+        ~[
+            cx.lit_str(span, @cx.str_of(v_name)),
+            cx.lit_uint(span, v_idx),
+            cx.lit_uint(span, stmts.len()),
+            cx.lambda_stmts(span, stmts),
+        ]
+    );
+
+    { pats: ~[pat], guard: None, body: cx.expr_blk(body) }
+}
 
-        let body;
+fn mk_enum_ser_body(
+    cx: ext_ctxt,
+    span: span,
+    name: ast::ident,
+    variants: ~[ast::variant]
+) -> @ast::expr {
+    let arms = do variants.mapi |v_idx, variant| {
         match variant.node.kind {
-            ast::tuple_variant_kind(args) => {
-                let tys = vec::map(args, |a| a.ty);
-
-                let arg_exprs = do vec::from_fn(vec::len(tys)) |i| {
-                    let idx = cx.lit_uint(v_span, i);
-                    let body = deser_lambda(cx, tps, tys[i], cx.clone(d));
-                    #ast{ $(d).read_enum_variant_arg($(idx), $(body)) }
-                };
-
-                body = {
-                    if vec::is_empty(tys) {
-                        // for a nullary variant v, do "v"
-                        cx.var_ref(v_span, v_name)
-                    } else {
-                        // for an n-ary variant v, do "v(a_1, ..., a_n)"
-                        cx.expr(v_span, ast::expr_call(
-                            cx.var_ref(v_span, v_name), arg_exprs, false))
-                    }
-                };
-            }
+            ast::tuple_variant_kind(args) =>
+                ser_variant(cx, span, variant.node.name, v_idx, args),
             ast::struct_variant_kind(*) =>
                 fail ~"struct variants unimplemented",
             ast::enum_variant_kind(*) =>
-                fail ~"enum variants unimplemented"
+                fail ~"enum variants unimplemented",
         }
+    };
 
-        {pats: ~[@{id: cx.next_id(),
-                  node: ast::pat_lit(cx.lit_uint(v_span, vidx)),
-                  span: v_span}],
-         guard: None,
-         body: cx.expr_blk(body)}
+    // ast for `match *self { $(arms) }`
+    let match_expr = cx.expr(
+        span,
+        ast::expr_match(
+            cx.expr(
+                span,
+                ast::expr_unary(ast::deref, cx.expr_var(span, ~"self"))
+            ),
+            arms
+        )
+    );
+
+    // ast for `__s.emit_enum($(name), || $(match_expr))`
+    cx.expr_call(
+        span,
+        cx.expr_field(
+            span,
+            cx.expr_var(span, ~"__s"),
+            cx.ident_of(~"emit_enum")
+        ),
+        ~[
+            cx.lit_str(span, @cx.str_of(name)),
+            cx.lambda_expr(match_expr),
+        ]
+    )
+}
+
+fn mk_enum_deser_variant_nary(
+    cx: ext_ctxt,
+    span: span,
+    name: ast::ident,
+    args: ~[ast::variant_arg]
+) -> @ast::expr {
+    let args = do args.mapi |idx, _arg| {
+        // ast for `|| std::serialization::deserialize(__d)`
+        let expr_lambda = cx.lambda_expr(
+            cx.expr_call(
+                span,
+                cx.expr_path(span, ~[
+                    cx.ident_of(~"std"),
+                    cx.ident_of(~"serialization"),
+                    cx.ident_of(~"deserialize"),
+                ]),
+                ~[cx.expr_var(span, ~"__d")]
+            )
+        );
+
+        // ast for `__d.read_enum_variant_arg($(a_idx), $(expr_lambda))`
+        cx.expr_call(
+            span,
+            cx.expr_field(
+                span,
+                cx.expr_var(span, ~"__d"),
+                cx.ident_of(~"read_enum_variant_arg")
+            ),
+            ~[cx.lit_uint(span, idx), expr_lambda]
+        )
     };
 
-    let impossible_case = {pats: ~[@{id: cx.next_id(),
-                                     node: ast::pat_wild,
-                                     span: e_span}],
-                        guard: None,
-                        // FIXME #3198: proper error message
-                           body: cx.expr_blk(cx.expr(e_span,
-                                                     ast::expr_fail(None)))};
-    arms += ~[impossible_case];
-
-    // Generate code like:
-    let e_name = cx.lit_str(e_span, @cx.str_of(e_name));
-    let alt_expr = cx.expr(e_span,
-                           ast::expr_match(#ast{__i}, arms));
-    let var_lambda = #ast{ |__i| $(alt_expr) };
-    let read_var = #ast{ $(cx.clone(d)).read_enum_variant($(var_lambda)) };
-    let read_lambda = cx.lambda(cx.expr_blk(read_var));
-    #ast{ $(d).read_enum($(e_name), $(read_lambda)) }
+    // ast for `$(name)($(args))`
+    cx.expr_call(span, cx.expr_path(span, ~[name]), args)
 }
 
-fn enum_fns(cx: ext_ctxt, e_name: ast::ident, e_span: span,
-               variants: ~[ast::variant], tps: ~[ast::ty_param])
-    -> ~[@ast::item] {
-    ~[
-        mk_ser_fn(cx, e_span, e_name, tps,
-                  |a,b,c,d| ser_enum(a, b, e_name, e_span, variants, move c,
-                                     move d)),
-        mk_deser_fn(cx, e_span, e_name, tps,
-          |a,b,c| deser_enum(a, b, e_name, e_span, variants, move c))
-    ]
+fn mk_enum_deser_body(
+    cx: ext_ctxt,
+    span: span,
+    name: ast::ident,
+    variants: ~[ast::variant]
+) -> @ast::expr {
+    let mut arms = do variants.mapi |v_idx, variant| {
+        let body = match variant.node.kind {
+            ast::tuple_variant_kind(args) => {
+                if args.is_empty() {
+                    // for a nullary variant v, do "v"
+                    cx.expr_path(span, ~[variant.node.name])
+                } else {
+                    // for an n-ary variant v, do "v(a_1, ..., a_n)"
+                    mk_enum_deser_variant_nary(
+                        cx,
+                        span,
+                        variant.node.name,
+                        args
+                    )
+                }
+            },
+            ast::struct_variant_kind(*) =>
+                fail ~"struct variants unimplemented",
+            ast::enum_variant_kind(*) =>
+                fail ~"enum variants unimplemented",
+        };
+
+        let pat = @{
+            id: cx.next_id(),
+            node: ast::pat_lit(cx.lit_uint(span, v_idx)),
+            span: span,
+        };
+
+        {
+            pats: ~[pat],
+            guard: None,
+            body: cx.expr_blk(body),
+        }
+    };
+
+    let impossible_case = {
+        pats: ~[@{ id: cx.next_id(), node: ast::pat_wild, span: span}],
+        guard: None,
+
+        // FIXME(#3198): proper error message
+        body: cx.expr_blk(cx.expr(span, ast::expr_fail(None))),
+    };
+
+    arms.push(impossible_case);
+
+    // ast for `|i| { match i { $(arms) } }`
+    let expr_lambda = cx.expr(
+        span,
+        ast::expr_fn_block(
+            {
+                inputs: ~[{
+                    mode: ast::infer(cx.next_id()),
+                    ty: @{
+                        id: cx.next_id(),
+                        node: ast::ty_infer,
+                        span: span
+                    },
+                    ident: cx.ident_of(~"i"),
+                    id: cx.next_id(),
+                }],
+                output: @{
+                    id: cx.next_id(),
+                    node: ast::ty_infer,
+                    span: span,
+                },
+                cf: ast::return_val,
+            },
+            cx.expr_blk(
+                cx.expr(
+                    span,
+                    ast::expr_match(cx.expr_var(span, ~"i"), arms)
+                )
+            ),
+            @~[]
+        )
+    );
+
+    // ast for `__d.read_enum_variant($(expr_lambda))`
+    let expr_lambda = cx.lambda_expr(
+        cx.expr_call(
+            span,
+            cx.expr_field(
+                span,
+                cx.expr_var(span, ~"__d"),
+                cx.ident_of(~"read_enum_variant")
+            ),
+            ~[expr_lambda]
+        )
+    );
+
+    // ast for `__d.read_enum($(e_name), $(expr_lambda))`
+    cx.expr_call(
+        span,
+        cx.expr_field(
+            span,
+            cx.expr_var(span, ~"__d"),
+            cx.ident_of(~"read_enum")
+        ),
+        ~[
+            cx.lit_str(span, @cx.str_of(name)),
+            expr_lambda
+        ]
+    )
 }
diff --git a/src/libsyntax/ext/auto_serialize2.rs b/src/libsyntax/ext/auto_serialize2.rs
deleted file mode 100644
index 99f837a4c84..00000000000
--- a/src/libsyntax/ext/auto_serialize2.rs
+++ /dev/null
@@ -1,1025 +0,0 @@
-/*
-
-The compiler code necessary to implement the #[auto_serialize2] and
-#[auto_deserialize2] extension.  The idea here is that type-defining items may
-be tagged with #[auto_serialize2] and #[auto_deserialize2], which will cause
-us to generate a little companion module with the same name as the item.
-
-For example, a type like:
-
-    #[auto_serialize2]
-    #[auto_deserialize2]
-    struct Node {id: uint}
-
-would generate two implementations like:
-
-    impl Node: Serializable {
-        fn serialize<S: Serializer>(s: &S) {
-            do s.emit_struct("Node") {
-                s.emit_field("id", 0, || s.emit_uint(self))
-            }
-        }
-    }
-
-    impl node_id: Deserializable {
-        static fn deserialize<D: Deserializer>(d: &D) -> Node {
-            do d.read_struct("Node") {
-                Node {
-                    id: d.read_field(~"x", 0, || deserialize(d))
-                }
-            }
-        }
-    }
-
-Other interesting scenarios are whe the item has type parameters or
-references other non-built-in types.  A type definition like:
-
-    #[auto_serialize2]
-    #[auto_deserialize2]
-    type spanned<T> = {node: T, span: span};
-
-would yield functions like:
-
-    impl<T: Serializable> spanned<T>: Serializable {
-        fn serialize<S: Serializer>(s: &S) {
-            do s.emit_rec {
-                s.emit_field("node", 0, || self.node.serialize(s));
-                s.emit_field("span", 1, || self.span.serialize(s));
-            }
-        }
-    }
-
-    impl<T: Deserializable> spanned<T>: Deserializable {
-        static fn deserialize<D: Deserializer>(d: &D) -> spanned<T> {
-            do d.read_rec {
-                {
-                    node: d.read_field(~"node", 0, || deserialize(d)),
-                    span: d.read_field(~"span", 1, || deserialize(d)),
-                }
-            }
-        }
-    }
-
-FIXME (#2810)--Hygiene. Search for "__" strings.  We also assume "std" is the
-standard library.
-
-Misc notes:
------------
-
-I use move mode arguments for ast nodes that will get inserted as is
-into the tree.  This is intended to prevent us from inserting the same
-node twice.
-
-*/
-
-use base::*;
-use codemap::span;
-use std::map;
-use std::map::HashMap;
-
-export expand_auto_serialize;
-export expand_auto_deserialize;
-
-// Transitional reexports so qquote can find the paths it is looking for
-mod syntax {
-    pub use ext;
-    pub use parse;
-}
-
-fn expand_auto_serialize(
-    cx: ext_ctxt,
-    span: span,
-    _mitem: ast::meta_item,
-    in_items: ~[@ast::item]
-) -> ~[@ast::item] {
-    fn is_auto_serialize2(a: &ast::attribute) -> bool {
-        attr::get_attr_name(*a) == ~"auto_serialize2"
-    }
-
-    fn filter_attrs(item: @ast::item) -> @ast::item {
-        @{attrs: vec::filter(item.attrs, |a| !is_auto_serialize2(a)),
-          .. *item}
-    }
-
-    do vec::flat_map(in_items) |item| {
-        if item.attrs.any(is_auto_serialize2) {
-            match item.node {
-                ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => {
-                    let ser_impl = mk_rec_ser_impl(
-                        cx,
-                        item.span,
-                        item.ident,
-                        fields,
-                        tps
-                    );
-
-                    ~[filter_attrs(*item), ser_impl]
-                },
-                ast::item_class(@{ fields, _}, tps) => {
-                    let ser_impl = mk_struct_ser_impl(
-                        cx,
-                        item.span,
-                        item.ident,
-                        fields,
-                        tps
-                    );
-
-                    ~[filter_attrs(*item), ser_impl]
-                },
-                ast::item_enum(enum_def, tps) => {
-                    let ser_impl = mk_enum_ser_impl(
-                        cx,
-                        item.span,
-                        item.ident,
-                        enum_def,
-                        tps
-                    );
-
-                    ~[filter_attrs(*item), ser_impl]
-                },
-                _ => {
-                    cx.span_err(span, ~"#[auto_serialize2] can only be \
-                                        applied to structs, record types, \
-                                        and enum definitions");
-                    ~[*item]
-                }
-            }
-        } else {
-            ~[*item]
-        }
-    }
-}
-
-fn expand_auto_deserialize(
-    cx: ext_ctxt,
-    span: span,
-    _mitem: ast::meta_item,
-    in_items: ~[@ast::item]
-) -> ~[@ast::item] {
-    fn is_auto_deserialize2(a: &ast::attribute) -> bool {
-        attr::get_attr_name(*a) == ~"auto_deserialize2"
-    }
-
-    fn filter_attrs(item: @ast::item) -> @ast::item {
-        @{attrs: vec::filter(item.attrs, |a| !is_auto_deserialize2(a)),
-          .. *item}
-    }
-
-    do vec::flat_map(in_items) |item| {
-        if item.attrs.any(is_auto_deserialize2) {
-            match item.node {
-                ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => {
-                    let deser_impl = mk_rec_deser_impl(
-                        cx,
-                        item.span,
-                        item.ident,
-                        fields,
-                        tps
-                    );
-
-                    ~[filter_attrs(*item), deser_impl]
-                },
-                ast::item_class(@{ fields, _}, tps) => {
-                    let deser_impl = mk_struct_deser_impl(
-                        cx,
-                        item.span,
-                        item.ident,
-                        fields,
-                        tps
-                    );
-
-                    ~[filter_attrs(*item), deser_impl]
-                },
-                ast::item_enum(enum_def, tps) => {
-                    let deser_impl = mk_enum_deser_impl(
-                        cx,
-                        item.span,
-                        item.ident,
-                        enum_def,
-                        tps
-                    );
-
-                    ~[filter_attrs(*item), deser_impl]
-                },
-                _ => {
-                    cx.span_err(span, ~"#[auto_deserialize2] can only be \
-                                        applied to structs, record types, \
-                                        and enum definitions");
-                    ~[*item]
-                }
-            }
-        } else {
-            ~[*item]
-        }
-    }
-}
-
-priv impl ext_ctxt {
-    fn expr_path(span: span, strs: ~[ast::ident]) -> @ast::expr {
-        self.expr(span, ast::expr_path(self.path(span, strs)))
-    }
-
-    fn expr_var(span: span, var: ~str) -> @ast::expr {
-        self.expr_path(span, ~[self.ident_of(var)])
-    }
-
-    fn expr_field(
-        span: span,
-        expr: @ast::expr,
-        ident: ast::ident
-    ) -> @ast::expr {
-        self.expr(span, ast::expr_field(expr, ident, ~[]))
-    }
-
-    fn expr_call(
-        span: span,
-        expr: @ast::expr,
-        args: ~[@ast::expr]
-    ) -> @ast::expr {
-        self.expr(span, ast::expr_call(expr, args, false))
-    }
-
-    fn lambda_expr(expr: @ast::expr) -> @ast::expr {
-        self.lambda(self.expr_blk(expr))
-    }
-
-    fn lambda_stmts(span: span, stmts: ~[@ast::stmt]) -> @ast::expr {
-        self.lambda(self.blk(span, stmts))
-    }
-}
-
-fn mk_impl(
-    cx: ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    path: @ast::path,
-    tps: ~[ast::ty_param],
-    f: fn(@ast::ty) -> @ast::method
-) -> @ast::item {
-    // All the type parameters need to bound to the trait.
-    let trait_tps = do tps.map |tp| {
-        let t_bound = ast::bound_trait(@{
-            id: cx.next_id(),
-            node: ast::ty_path(path, cx.next_id()),
-            span: span,
-        });
-
-        {
-            ident: tp.ident,
-            id: cx.next_id(),
-            bounds: @vec::append(~[t_bound], *tp.bounds)
-        }
-    };
-
-    let opt_trait = Some(@{
-        path: path,
-        ref_id: cx.next_id(),
-        impl_id: cx.next_id(),
-    });
-
-    let ty = cx.ty_path(
-        span,
-        ~[ident],
-        tps.map(|tp| cx.ty_path(span, ~[tp.ident], ~[]))
-    );
-
-    @{
-        // This is a new-style impl declaration.
-        // XXX: clownshoes
-        ident: ast::token::special_idents::clownshoes_extensions,
-        attrs: ~[],
-        id: cx.next_id(),
-        node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]),
-        vis: ast::public,
-        span: span,
-    }
-}
-
-fn mk_ser_impl(
-    cx: ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    tps: ~[ast::ty_param],
-    body: @ast::expr
-) -> @ast::item {
-    // Make a path to the std::serialization2::Serializable trait.
-    let path = cx.path(
-        span,
-        ~[
-            cx.ident_of(~"std"),
-            cx.ident_of(~"serialization2"),
-            cx.ident_of(~"Serializable"),
-        ]
-    );
-
-    mk_impl(
-        cx,
-        span,
-        ident,
-        path,
-        tps,
-        |_ty| mk_ser_method(cx, span, cx.expr_blk(body))
-    )
-}
-
-fn mk_deser_impl(
-    cx: ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    tps: ~[ast::ty_param],
-    body: @ast::expr
-) -> @ast::item {
-    // Make a path to the std::serialization2::Deserializable trait.
-    let path = cx.path(
-        span,
-        ~[
-            cx.ident_of(~"std"),
-            cx.ident_of(~"serialization2"),
-            cx.ident_of(~"Deserializable"),
-        ]
-    );
-
-    mk_impl(
-        cx,
-        span,
-        ident,
-        path,
-        tps,
-        |ty| mk_deser_method(cx, span, ty, cx.expr_blk(body))
-    )
-}
-
-fn mk_ser_method(
-    cx: ext_ctxt,
-    span: span,
-    ser_body: ast::blk
-) -> @ast::method {
-    let ser_bound = cx.ty_path(
-        span,
-        ~[
-            cx.ident_of(~"std"),
-            cx.ident_of(~"serialization2"),
-            cx.ident_of(~"Serializer"),
-        ],
-        ~[]
-    );
-
-    let ser_tps = ~[{
-        ident: cx.ident_of(~"__S"),
-        id: cx.next_id(),
-        bounds: @~[ast::bound_trait(ser_bound)],
-    }];
-
-    let ty_s = @{
-        id: cx.next_id(),
-        node: ast::ty_rptr(
-            @{
-                id: cx.next_id(),
-                node: ast::re_anon,
-            },
-            {
-                ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]),
-                mutbl: ast::m_imm
-            }
-        ),
-        span: span,
-    };
-
-    let ser_inputs = ~[{
-        mode: ast::infer(cx.next_id()),
-        ty: ty_s,
-        ident: cx.ident_of(~"__s"),
-        id: cx.next_id(),
-    }];
-
-    let ser_output = @{
-        id: cx.next_id(),
-        node: ast::ty_nil,
-        span: span,
-    };
-
-    let ser_decl = {
-        inputs: ser_inputs,
-        output: ser_output,
-        cf: ast::return_val,
-    };
-
-    @{
-        ident: cx.ident_of(~"serialize"),
-        attrs: ~[],
-        tps: ser_tps,
-        self_ty: { node: ast::sty_region(ast::m_imm), span: span },
-        purity: ast::impure_fn,
-        decl: ser_decl,
-        body: ser_body,
-        id: cx.next_id(),
-        span: span,
-        self_id: cx.next_id(),
-        vis: ast::public,
-    }
-}
-
-fn mk_deser_method(
-    cx: ext_ctxt,
-    span: span,
-    ty: @ast::ty,
-    deser_body: ast::blk
-) -> @ast::method {
-    let deser_bound = cx.ty_path(
-        span,
-        ~[
-            cx.ident_of(~"std"),
-            cx.ident_of(~"serialization2"),
-            cx.ident_of(~"Deserializer"),
-        ],
-        ~[]
-    );
-
-    let deser_tps = ~[{
-        ident: cx.ident_of(~"__D"),
-        id: cx.next_id(),
-        bounds: @~[ast::bound_trait(deser_bound)],
-    }];
-
-    let ty_d = @{
-        id: cx.next_id(),
-        node: ast::ty_rptr(
-            @{
-                id: cx.next_id(),
-                node: ast::re_anon,
-            },
-            {
-                ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]),
-                mutbl: ast::m_imm
-            }
-        ),
-        span: span,
-    };
-
-    let deser_inputs = ~[{
-        mode: ast::infer(cx.next_id()),
-        ty: ty_d,
-        ident: cx.ident_of(~"__d"),
-        id: cx.next_id(),
-    }];
-
-    let deser_decl = {
-        inputs: deser_inputs,
-        output: ty,
-        cf: ast::return_val,
-    };
-
-    @{
-        ident: cx.ident_of(~"deserialize"),
-        attrs: ~[],
-        tps: deser_tps,
-        self_ty: { node: ast::sty_static, span: span },
-        purity: ast::impure_fn,
-        decl: deser_decl,
-        body: deser_body,
-        id: cx.next_id(),
-        span: span,
-        self_id: cx.next_id(),
-        vis: ast::public,
-    }
-}
-
-fn mk_rec_ser_impl(
-    cx: ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    fields: ~[ast::ty_field],
-    tps: ~[ast::ty_param]
-) -> @ast::item {
-    let fields = mk_ser_fields(cx, span, mk_rec_fields(fields));
-
-    // ast for `__s.emit_rec(|| $(fields))`
-    let body = cx.expr_call(
-        span,
-        cx.expr_field(
-            span,
-            cx.expr_var(span, ~"__s"),
-            cx.ident_of(~"emit_rec")
-        ),
-        ~[cx.lambda_stmts(span, fields)]
-    );
-
-    mk_ser_impl(cx, span, ident, tps, body)
-}
-
-fn mk_rec_deser_impl(
-    cx: ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    fields: ~[ast::ty_field],
-    tps: ~[ast::ty_param]
-) -> @ast::item {
-    let fields = mk_deser_fields(cx, span, mk_rec_fields(fields));
-
-    // ast for `read_rec(|| $(fields))`
-    let body = cx.expr_call(
-        span,
-        cx.expr_field(
-            span,
-            cx.expr_var(span, ~"__d"),
-            cx.ident_of(~"read_rec")
-        ),
-        ~[
-            cx.lambda_expr(
-                cx.expr(
-                    span,
-                    ast::expr_rec(fields, None)
-                )
-            )
-        ]
-    );
-
-    mk_deser_impl(cx, span, ident, tps, body)
-}
-
-fn mk_struct_ser_impl(
-    cx: ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    fields: ~[@ast::struct_field],
-    tps: ~[ast::ty_param]
-) -> @ast::item {
-    let fields = mk_ser_fields(cx, span, mk_struct_fields(fields));
-
-    // ast for `__s.emit_struct($(name), || $(fields))`
-    let ser_body = cx.expr_call(
-        span,
-        cx.expr_field(
-            span,
-            cx.expr_var(span, ~"__s"),
-            cx.ident_of(~"emit_struct")
-        ),
-        ~[
-            cx.lit_str(span, @cx.str_of(ident)),
-            cx.lambda_stmts(span, fields),
-        ]
-    );
-
-    mk_ser_impl(cx, span, ident, tps, ser_body)
-}
-
-fn mk_struct_deser_impl(
-    cx: ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    fields: ~[@ast::struct_field],
-    tps: ~[ast::ty_param]
-) -> @ast::item {
-    let fields = mk_deser_fields(cx, span, mk_struct_fields(fields));
-
-    // ast for `read_struct($(name), || $(fields))`
-    let body = cx.expr_call(
-        span,
-        cx.expr_field(
-            span,
-            cx.expr_var(span, ~"__d"),
-            cx.ident_of(~"read_struct")
-        ),
-        ~[
-            cx.lit_str(span, @cx.str_of(ident)),
-            cx.lambda_expr(
-                cx.expr(
-                    span,
-                    ast::expr_struct(
-                        cx.path(span, ~[ident]),
-                        fields,
-                        None
-                    )
-                )
-            ),
-        ]
-    );
-
-    mk_deser_impl(cx, span, ident, tps, body)
-}
-
-// Records and structs don't have the same fields types, but they share enough
-// that if we extract the right subfields out we can share the serialization
-// generator code.
-type field = { span: span, ident: ast::ident, mutbl: ast::mutability };
-
-fn mk_rec_fields(fields: ~[ast::ty_field]) -> ~[field] {
-    do fields.map |field| {
-        {
-            span: field.span,
-            ident: field.node.ident,
-            mutbl: field.node.mt.mutbl,
-        }
-    }
-}
-
-fn mk_struct_fields(fields: ~[@ast::struct_field]) -> ~[field] {
-    do fields.map |field| {
-        let (ident, mutbl) = match field.node.kind {
-            ast::named_field(ident, mutbl, _) => (ident, mutbl),
-            _ => fail ~"[auto_serialize2] does not support \
-                        unnamed fields",
-        };
-
-        {
-            span: field.span,
-            ident: ident,
-            mutbl: match mutbl {
-                ast::class_mutable => ast::m_mutbl,
-                ast::class_immutable => ast::m_imm,
-            },
-        }
-    }
-}
-
-fn mk_ser_fields(
-    cx: ext_ctxt,
-    span: span,
-    fields: ~[field]
-) -> ~[@ast::stmt] {
-    do fields.mapi |idx, field| {
-        // ast for `|| self.$(name).serialize(__s)`
-        let expr_lambda = cx.lambda_expr(
-            cx.expr_call(
-                span,
-                cx.expr_field(
-                    span,
-                    cx.expr_field(
-                        span,
-                        cx.expr_var(span, ~"self"),
-                        field.ident
-                    ),
-                    cx.ident_of(~"serialize")
-                ),
-                ~[cx.expr_var(span, ~"__s")]
-            )
-        );
-
-        // ast for `__s.emit_field($(name), $(idx), $(expr_lambda))`
-        cx.stmt(
-            cx.expr_call(
-                span,
-                cx.expr_field(
-                    span,
-                    cx.expr_var(span, ~"__s"),
-                    cx.ident_of(~"emit_field")
-                ),
-                ~[
-                    cx.lit_str(span, @cx.str_of(field.ident)),
-                    cx.lit_uint(span, idx),
-                    expr_lambda,
-                ]
-            )
-        )
-    }
-}
-
-fn mk_deser_fields(
-    cx: ext_ctxt,
-    span: span,
-    fields: ~[{ span: span, ident: ast::ident, mutbl: ast::mutability }]
-) -> ~[ast::field] {
-    do fields.mapi |idx, field| {
-        // ast for `|| std::serialization2::deserialize(__d)`
-        let expr_lambda = cx.lambda(
-            cx.expr_blk(
-                cx.expr_call(
-                    span,
-                    cx.expr_path(span, ~[
-                        cx.ident_of(~"std"),
-                        cx.ident_of(~"serialization2"),
-                        cx.ident_of(~"deserialize"),
-                    ]),
-                    ~[cx.expr_var(span, ~"__d")]
-                )
-            )
-        );
-
-        // ast for `__d.read_field($(name), $(idx), $(expr_lambda))`
-        let expr: @ast::expr = cx.expr_call(
-            span,
-            cx.expr_field(
-                span,
-                cx.expr_var(span, ~"__d"),
-                cx.ident_of(~"read_field")
-            ),
-            ~[
-                cx.lit_str(span, @cx.str_of(field.ident)),
-                cx.lit_uint(span, idx),
-                expr_lambda,
-            ]
-        );
-
-        {
-            node: { mutbl: field.mutbl, ident: field.ident, expr: expr },
-            span: span,
-        }
-    }
-}
-
-fn mk_enum_ser_impl(
-    cx: ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    enum_def: ast::enum_def,
-    tps: ~[ast::ty_param]
-) -> @ast::item {
-    let body = mk_enum_ser_body(
-        cx,
-        span,
-        ident,
-        enum_def.variants
-    );
-
-    mk_ser_impl(cx, span, ident, tps, body)
-}
-
-fn mk_enum_deser_impl(
-    cx: ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    enum_def: ast::enum_def,
-    tps: ~[ast::ty_param]
-) -> @ast::item {
-    let body = mk_enum_deser_body(
-        cx,
-        span,
-        ident,
-        enum_def.variants
-    );
-
-    mk_deser_impl(cx, span, ident, tps, body)
-}
-
-fn ser_variant(
-    cx: ext_ctxt,
-    span: span,
-    v_name: ast::ident,
-    v_idx: uint,
-    args: ~[ast::variant_arg]
-) -> ast::arm {
-    // Name the variant arguments.
-    let names = args.mapi(|i, _arg| cx.ident_of(fmt!("__v%u", i)));
-
-    // Bind the names to the variant argument type.
-    let pats = args.mapi(|i, arg| cx.binder_pat(arg.ty.span, names[i]));
-
-    let pat_node = if pats.is_empty() {
-        ast::pat_ident(
-            ast::bind_by_implicit_ref,
-            cx.path(span, ~[v_name]),
-            None
-        )
-    } else {
-        ast::pat_enum(
-            cx.path(span, ~[v_name]),
-            Some(pats)
-        )
-    };
-
-    let pat = @{
-        id: cx.next_id(),
-        node: pat_node,
-        span: span,
-    };
-
-    let stmts = do args.mapi |a_idx, _arg| {
-        // ast for `__s.emit_enum_variant_arg`
-        let expr_emit = cx.expr_field(
-            span,
-            cx.expr_var(span, ~"__s"),
-            cx.ident_of(~"emit_enum_variant_arg")
-        );
-
-        // ast for `|| $(v).serialize(__s)`
-        let expr_serialize = cx.lambda_expr(
-             cx.expr_call(
-                span,
-                cx.expr_field(
-                    span,
-                    cx.expr_path(span, ~[names[a_idx]]),
-                    cx.ident_of(~"serialize")
-                ),
-                ~[cx.expr_var(span, ~"__s")]
-            )
-        );
-
-        // ast for `$(expr_emit)($(a_idx), $(expr_serialize))`
-        cx.stmt(
-            cx.expr_call(
-                span,
-                expr_emit,
-                ~[cx.lit_uint(span, a_idx), expr_serialize]
-            )
-        )
-    };
-
-    // ast for `__s.emit_enum_variant($(name), $(idx), $(sz), $(lambda))`
-    let body = cx.expr_call(
-        span,
-        cx.expr_field(
-            span,
-            cx.expr_var(span, ~"__s"),
-            cx.ident_of(~"emit_enum_variant")
-        ),
-        ~[
-            cx.lit_str(span, @cx.str_of(v_name)),
-            cx.lit_uint(span, v_idx),
-            cx.lit_uint(span, stmts.len()),
-            cx.lambda_stmts(span, stmts),
-        ]
-    );
-
-    { pats: ~[pat], guard: None, body: cx.expr_blk(body) }
-}
-
-fn mk_enum_ser_body(
-    cx: ext_ctxt,
-    span: span,
-    name: ast::ident,
-    variants: ~[ast::variant]
-) -> @ast::expr {
-    let arms = do variants.mapi |v_idx, variant| {
-        match variant.node.kind {
-            ast::tuple_variant_kind(args) =>
-                ser_variant(cx, span, variant.node.name, v_idx, args),
-            ast::struct_variant_kind(*) =>
-                fail ~"struct variants unimplemented",
-            ast::enum_variant_kind(*) =>
-                fail ~"enum variants unimplemented",
-        }
-    };
-
-    // ast for `match *self { $(arms) }`
-    let match_expr = cx.expr(
-        span,
-        ast::expr_match(
-            cx.expr(
-                span,
-                ast::expr_unary(ast::deref, cx.expr_var(span, ~"self"))
-            ),
-            arms
-        )
-    );
-
-    // ast for `__s.emit_enum($(name), || $(match_expr))`
-    cx.expr_call(
-        span,
-        cx.expr_field(
-            span,
-            cx.expr_var(span, ~"__s"),
-            cx.ident_of(~"emit_enum")
-        ),
-        ~[
-            cx.lit_str(span, @cx.str_of(name)),
-            cx.lambda_expr(match_expr),
-        ]
-    )
-}
-
-fn mk_enum_deser_variant_nary(
-    cx: ext_ctxt,
-    span: span,
-    name: ast::ident,
-    args: ~[ast::variant_arg]
-) -> @ast::expr {
-    let args = do args.mapi |idx, _arg| {
-        // ast for `|| std::serialization2::deserialize(__d)`
-        let expr_lambda = cx.lambda_expr(
-            cx.expr_call(
-                span,
-                cx.expr_path(span, ~[
-                    cx.ident_of(~"std"),
-                    cx.ident_of(~"serialization2"),
-                    cx.ident_of(~"deserialize"),
-                ]),
-                ~[cx.expr_var(span, ~"__d")]
-            )
-        );
-
-        // ast for `__d.read_enum_variant_arg($(a_idx), $(expr_lambda))`
-        cx.expr_call(
-            span,
-            cx.expr_field(
-                span,
-                cx.expr_var(span, ~"__d"),
-                cx.ident_of(~"read_enum_variant_arg")
-            ),
-            ~[cx.lit_uint(span, idx), expr_lambda]
-        )
-    };
-
-    // ast for `$(name)($(args))`
-    cx.expr_call(span, cx.expr_path(span, ~[name]), args)
-}
-
-fn mk_enum_deser_body(
-    cx: ext_ctxt,
-    span: span,
-    name: ast::ident,
-    variants: ~[ast::variant]
-) -> @ast::expr {
-    let mut arms = do variants.mapi |v_idx, variant| {
-        let body = match variant.node.kind {
-            ast::tuple_variant_kind(args) => {
-                if args.is_empty() {
-                    // for a nullary variant v, do "v"
-                    cx.expr_path(span, ~[variant.node.name])
-                } else {
-                    // for an n-ary variant v, do "v(a_1, ..., a_n)"
-                    mk_enum_deser_variant_nary(
-                        cx,
-                        span,
-                        variant.node.name,
-                        args
-                    )
-                }
-            },
-            ast::struct_variant_kind(*) =>
-                fail ~"struct variants unimplemented",
-            ast::enum_variant_kind(*) =>
-                fail ~"enum variants unimplemented",
-        };
-
-        let pat = @{
-            id: cx.next_id(),
-            node: ast::pat_lit(cx.lit_uint(span, v_idx)),
-            span: span,
-        };
-
-        {
-            pats: ~[pat],
-            guard: None,
-            body: cx.expr_blk(body),
-        }
-    };
-
-    let impossible_case = {
-        pats: ~[@{ id: cx.next_id(), node: ast::pat_wild, span: span}],
-        guard: None,
-
-        // FIXME(#3198): proper error message
-        body: cx.expr_blk(cx.expr(span, ast::expr_fail(None))),
-    };
-
-    arms.push(impossible_case);
-
-    // ast for `|i| { match i { $(arms) } }`
-    let expr_lambda = cx.expr(
-        span,
-        ast::expr_fn_block(
-            {
-                inputs: ~[{
-                    mode: ast::infer(cx.next_id()),
-                    ty: @{
-                        id: cx.next_id(),
-                        node: ast::ty_infer,
-                        span: span
-                    },
-                    ident: cx.ident_of(~"i"),
-                    id: cx.next_id(),
-                }],
-                output: @{
-                    id: cx.next_id(),
-                    node: ast::ty_infer,
-                    span: span,
-                },
-                cf: ast::return_val,
-            },
-            cx.expr_blk(
-                cx.expr(
-                    span,
-                    ast::expr_match(cx.expr_var(span, ~"i"), arms)
-                )
-            ),
-            @~[]
-        )
-    );
-
-    // ast for `__d.read_enum_variant($(expr_lambda))`
-    let expr_lambda = cx.lambda_expr(
-        cx.expr_call(
-            span,
-            cx.expr_field(
-                span,
-                cx.expr_var(span, ~"__d"),
-                cx.ident_of(~"read_enum_variant")
-            ),
-            ~[expr_lambda]
-        )
-    );
-
-    // ast for `__d.read_enum($(e_name), $(expr_lambda))`
-    cx.expr_call(
-        span,
-        cx.expr_field(
-            span,
-            cx.expr_var(span, ~"__d"),
-            cx.ident_of(~"read_enum")
-        ),
-        ~[
-            cx.lit_str(span, @cx.str_of(name)),
-            expr_lambda
-        ]
-    )
-}
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 9a31cc1d8f6..5b4cc23ce09 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -1,7 +1,7 @@
 use std::map::HashMap;
 use parse::parser;
 use diagnostic::span_handler;
-use codemap::{codemap, span, expn_info, expanded_from};
+use codemap::{CodeMap, span, expn_info, expanded_from};
 
 // obsolete old-style #macro code:
 //
@@ -80,14 +80,12 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> {
                             builtin_item_tt(
                                 ext::tt::macro_rules::add_new_extension));
     syntax_expanders.insert(~"fmt", builtin(ext::fmt::expand_syntax_ext));
-    syntax_expanders.insert(~"auto_serialize",
-                            item_decorator(ext::auto_serialize::expand));
     syntax_expanders.insert(
-        ~"auto_serialize2",
-        item_decorator(ext::auto_serialize2::expand_auto_serialize));
+        ~"auto_serialize",
+        item_decorator(ext::auto_serialize::expand_auto_serialize));
     syntax_expanders.insert(
-        ~"auto_deserialize2",
-        item_decorator(ext::auto_serialize2::expand_auto_deserialize));
+        ~"auto_deserialize",
+        item_decorator(ext::auto_serialize::expand_auto_deserialize));
     syntax_expanders.insert(~"env", builtin(ext::env::expand_syntax_ext));
     syntax_expanders.insert(~"concat_idents",
                             builtin(ext::concat_idents::expand_syntax_ext));
@@ -122,12 +120,11 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> {
     return syntax_expanders;
 }
 
-
 // One of these is made during expansion and incrementally updated as we go;
 // when a macro expansion occurs, the resulting nodes have the backtrace()
 // -> expn_info of their expansion context stored into their span.
 trait ext_ctxt {
-    fn codemap() -> codemap;
+    fn codemap() -> CodeMap;
     fn parse_sess() -> parse::parse_sess;
     fn cfg() -> ast::crate_cfg;
     fn print_backtrace();
@@ -159,7 +156,7 @@ fn mk_ctxt(parse_sess: parse::parse_sess,
                       mut mod_path: ~[ast::ident],
                       mut trace_mac: bool};
     impl ctxt_repr: ext_ctxt {
-        fn codemap() -> codemap { self.parse_sess.cm }
+        fn codemap() -> CodeMap { self.parse_sess.cm }
         fn parse_sess() -> parse::parse_sess { self.parse_sess }
         fn cfg() -> ast::crate_cfg { self.cfg }
         fn print_backtrace() { }
@@ -234,7 +231,7 @@ fn mk_ctxt(parse_sess: parse::parse_sess,
         mut mod_path: ~[],
         mut trace_mac: false
     };
-    move (imp as ext_ctxt)
+    move ((move imp) as ext_ctxt)
 }
 
 fn expr_to_str(cx: ext_ctxt, expr: @ast::expr, error: ~str) -> ~str {
@@ -272,21 +269,21 @@ fn get_mac_args(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
               match max {
                 Some(max) if ! (min <= elts_len && elts_len <= max) => {
                   cx.span_fatal(sp,
-                                fmt!("#%s takes between %u and %u arguments.",
+                                fmt!("%s! takes between %u and %u arguments.",
                                      name, min, max));
                 }
                 None if ! (min <= elts_len) => {
-                  cx.span_fatal(sp, fmt!("#%s needs at least %u arguments.",
+                  cx.span_fatal(sp, fmt!("%s! needs at least %u arguments.",
                                          name, min));
                 }
                 _ => return elts /* we are good */
               }
           }
         _ => {
-            cx.span_fatal(sp, fmt!("#%s: malformed invocation", name))
+            cx.span_fatal(sp, fmt!("%s!: malformed invocation", name))
         }
       },
-      None => cx.span_fatal(sp, fmt!("#%s: missing arguments", name))
+      None => cx.span_fatal(sp, fmt!("%s!: missing arguments", name))
     }
 }
 
diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs
index 8cecceb2e55..37fb0f05cbd 100644
--- a/src/libsyntax/ext/env.rs
+++ b/src/libsyntax/ext/env.rs
@@ -1,6 +1,6 @@
 
 /*
- * The compiler code necessary to support the #env extension.  Eventually this
+ * The compiler code necessary to support the env! extension.  Eventually this
  * should all get sucked into either the compiler syntax extension plugin
  * interface.
  */
@@ -15,7 +15,7 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
     // FIXME (#2248): if this was more thorough it would manufacture an
     // Option<str> rather than just an maybe-empty string.
 
-    let var = expr_to_str(cx, args[0], ~"#env requires a string");
+    let var = expr_to_str(cx, args[0], ~"env! requires a string");
     match os::getenv(var) {
       option::None => return mk_uniq_str(cx, sp, ~""),
       option::Some(s) => return mk_uniq_str(cx, sp, s)
diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs
index ea493eab561..e24575f6cd3 100644
--- a/src/libsyntax/ext/fmt.rs
+++ b/src/libsyntax/ext/fmt.rs
@@ -1,7 +1,7 @@
 
 
 /*
- * The compiler code necessary to support the #fmt extension. Eventually this
+ * The compiler code necessary to support the fmt! extension. Eventually this
  * should all get sucked into either the standard library extfmt module or the
  * compiler syntax extension plugin interface.
  */
@@ -16,7 +16,7 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
     let args = get_mac_args_no_max(cx, sp, arg, 1u, ~"fmt");
     let fmt =
         expr_to_str(cx, args[0],
-                    ~"first argument to #fmt must be a string literal.");
+                    ~"first argument to fmt! must be a string literal.");
     let fmtspan = args[0].span;
     debug!("Format string:");
     log(debug, fmt);
@@ -76,7 +76,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span,
                 let count_is_args = ~[count_lit];
                 return mk_call(cx, sp, count_is_path, count_is_args);
               }
-              _ => cx.span_unimpl(sp, ~"unimplemented #fmt conversion")
+              _ => cx.span_unimpl(sp, ~"unimplemented fmt! conversion")
             }
         }
         fn make_ty(cx: ext_ctxt, sp: span, t: Ty) -> @ast::expr {
@@ -133,7 +133,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span,
               _ => return false
             }
         }
-        let unsupported = ~"conversion not supported in #fmt string";
+        let unsupported = ~"conversion not supported in fmt! string";
         match cnv.param {
           option::None => (),
           _ => cx.span_unimpl(sp, unsupported)
@@ -145,14 +145,14 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span,
                 if !is_signed_type(cnv) {
                     cx.span_fatal(sp,
                                   ~"+ flag only valid in " +
-                                      ~"signed #fmt conversion");
+                                      ~"signed fmt! conversion");
                 }
               }
               FlagSpaceForSign => {
                 if !is_signed_type(cnv) {
                     cx.span_fatal(sp,
                                   ~"space flag only valid in " +
-                                      ~"signed #fmt conversions");
+                                      ~"signed fmt! conversions");
                 }
               }
               FlagLeftZeroPad => (),
@@ -252,7 +252,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span,
             n += 1u;
             if n >= nargs {
                 cx.span_fatal(sp,
-                              ~"not enough arguments to #fmt " +
+                              ~"not enough arguments to fmt! " +
                                   ~"for the given format string");
             }
             debug!("Building conversion:");
@@ -267,7 +267,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span,
 
     if expected_nargs < nargs {
         cx.span_fatal
-            (sp, fmt!("too many arguments to #fmt. found %u, expected %u",
+            (sp, fmt!("too many arguments to fmt!. found %u, expected %u",
                            nargs, expected_nargs));
     }
 
diff --git a/src/libsyntax/ext/pipes.rs b/src/libsyntax/ext/pipes.rs
index ad4984c5558..4d04552bfa1 100644
--- a/src/libsyntax/ext/pipes.rs
+++ b/src/libsyntax/ext/pipes.rs
@@ -37,7 +37,7 @@ use codemap::span;
 use ext::base::ext_ctxt;
 use ast::tt_delim;
 use parse::lexer::{new_tt_reader, reader};
-use parse::parser::{parser, SOURCE_FILE};
+use parse::parser::{Parser, SOURCE_FILE};
 use parse::common::parser_common;
 
 use pipes::parse_proto::proto_parser;
@@ -52,7 +52,7 @@ fn expand_proto(cx: ext_ctxt, _sp: span, id: ast::ident,
     let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic,
                                cx.parse_sess().interner, None, tt);
     let rdr = tt_rdr as reader;
-    let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE);
+    let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE);
 
     let proto = rust_parser.parse_proto(cx.str_of(id));
 
diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs
index 4da9992b0dd..f10cbc2a589 100644
--- a/src/libsyntax/ext/pipes/ast_builder.rs
+++ b/src/libsyntax/ext/pipes/ast_builder.rs
@@ -28,17 +28,17 @@ fn empty_span() -> span {
 }
 
 trait append_types {
-    fn add_ty(ty: @ast::ty) -> @ast::path;
-    fn add_tys(+tys: ~[@ast::ty]) -> @ast::path;
+    fn add_ty(ty: @ast::Ty) -> @ast::path;
+    fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path;
 }
 
 impl @ast::path: append_types {
-    fn add_ty(ty: @ast::ty) -> @ast::path {
+    fn add_ty(ty: @ast::Ty) -> @ast::path {
         @{types: vec::append_one(self.types, ty),
           .. *self}
     }
 
-    fn add_tys(+tys: ~[@ast::ty]) -> @ast::path {
+    fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path {
         @{types: vec::append(self.types, tys),
           .. *self}
     }
@@ -47,18 +47,18 @@ impl @ast::path: append_types {
 trait ext_ctxt_ast_builder {
     fn ty_param(id: ast::ident, +bounds: ~[ast::ty_param_bound])
         -> ast::ty_param;
-    fn arg(name: ident, ty: @ast::ty) -> ast::arg;
+    fn arg(name: ident, ty: @ast::Ty) -> ast::arg;
     fn expr_block(e: @ast::expr) -> ast::blk;
-    fn fn_decl(+inputs: ~[ast::arg], output: @ast::ty) -> ast::fn_decl;
+    fn fn_decl(+inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl;
     fn item(name: ident, span: span, +node: ast::item_) -> @ast::item;
     fn item_fn_poly(name: ident,
                     +inputs: ~[ast::arg],
-                    output: @ast::ty,
+                    output: @ast::Ty,
                     +ty_params: ~[ast::ty_param],
                     +body: ast::blk) -> @ast::item;
     fn item_fn(name: ident,
                +inputs: ~[ast::arg],
-               output: @ast::ty,
+               output: @ast::Ty,
                +body: ast::blk) -> @ast::item;
     fn item_enum_poly(name: ident,
                       span: span,
@@ -66,17 +66,17 @@ trait ext_ctxt_ast_builder {
                       +ty_params: ~[ast::ty_param]) -> @ast::item;
     fn item_enum(name: ident, span: span,
                  +enum_definition: ast::enum_def) -> @ast::item;
-    fn variant(name: ident, span: span, +tys: ~[@ast::ty]) -> ast::variant;
+    fn variant(name: ident, span: span, +tys: ~[@ast::Ty]) -> ast::variant;
     fn item_mod(name: ident, span: span, +items: ~[@ast::item]) -> @ast::item;
-    fn ty_path_ast_builder(path: @ast::path) -> @ast::ty;
+    fn ty_path_ast_builder(path: @ast::path) -> @ast::Ty;
     fn item_ty_poly(name: ident,
                     span: span,
-                    ty: @ast::ty,
+                    ty: @ast::Ty,
                     +params: ~[ast::ty_param]) -> @ast::item;
-    fn item_ty(name: ident, span: span, ty: @ast::ty) -> @ast::item;
-    fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::ty];
-    fn ty_field_imm(name: ident, ty: @ast::ty) -> ast::ty_field;
-    fn ty_rec(+v: ~[ast::ty_field]) -> @ast::ty;
+    fn item_ty(name: ident, span: span, ty: @ast::Ty) -> @ast::item;
+    fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::Ty];
+    fn ty_field_imm(name: ident, ty: @ast::Ty) -> ast::ty_field;
+    fn ty_rec(+v: ~[ast::ty_field]) -> @ast::Ty;
     fn field_imm(name: ident, e: @ast::expr) -> ast::field;
     fn rec(+v: ~[ast::field]) -> @ast::expr;
     fn block(+stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk;
@@ -84,11 +84,11 @@ trait ext_ctxt_ast_builder {
     fn stmt_expr(e: @ast::expr) -> @ast::stmt;
     fn block_expr(b: ast::blk) -> @ast::expr;
     fn empty_span() -> span;
-    fn ty_option(ty: @ast::ty) -> @ast::ty;
+    fn ty_option(ty: @ast::Ty) -> @ast::Ty;
 }
 
 impl ext_ctxt: ext_ctxt_ast_builder {
-    fn ty_option(ty: @ast::ty) -> @ast::ty {
+    fn ty_option(ty: @ast::Ty) -> @ast::Ty {
         self.ty_path_ast_builder(path(~[self.ident_of(~"Option")],
                                       self.empty_span())
                                  .add_ty(ty))
@@ -146,18 +146,18 @@ impl ext_ctxt: ext_ctxt_ast_builder {
           span: self.empty_span()}
     }
 
-    fn ty_field_imm(name: ident, ty: @ast::ty) -> ast::ty_field {
+    fn ty_field_imm(name: ident, ty: @ast::Ty) -> ast::ty_field {
         {node: {ident: name, mt: { ty: ty, mutbl: ast::m_imm } },
           span: self.empty_span()}
     }
 
-    fn ty_rec(+fields: ~[ast::ty_field]) -> @ast::ty {
+    fn ty_rec(+fields: ~[ast::ty_field]) -> @ast::Ty {
         @{id: self.next_id(),
           node: ast::ty_rec(fields),
           span: self.empty_span()}
     }
 
-    fn ty_infer() -> @ast::ty {
+    fn ty_infer() -> @ast::Ty {
         @{id: self.next_id(),
           node: ast::ty_infer,
           span: self.empty_span()}
@@ -169,7 +169,7 @@ impl ext_ctxt: ext_ctxt_ast_builder {
         {ident: id, id: self.next_id(), bounds: @bounds}
     }
 
-    fn arg(name: ident, ty: @ast::ty) -> ast::arg {
+    fn arg(name: ident, ty: @ast::Ty) -> ast::arg {
         {mode: ast::infer(self.next_id()),
          ty: ty,
          ident: name,
@@ -192,7 +192,7 @@ impl ext_ctxt: ext_ctxt_ast_builder {
     }
 
     fn fn_decl(+inputs: ~[ast::arg],
-               output: @ast::ty) -> ast::fn_decl {
+               output: @ast::Ty) -> ast::fn_decl {
         {inputs: inputs,
          output: output,
          cf: ast::return_val}
@@ -224,7 +224,7 @@ impl ext_ctxt: ext_ctxt_ast_builder {
 
     fn item_fn_poly(name: ident,
                     +inputs: ~[ast::arg],
-                    output: @ast::ty,
+                    output: @ast::Ty,
                     +ty_params: ~[ast::ty_param],
                     +body: ast::blk) -> @ast::item {
         self.item(name,
@@ -237,7 +237,7 @@ impl ext_ctxt: ext_ctxt_ast_builder {
 
     fn item_fn(name: ident,
                +inputs: ~[ast::arg],
-               output: @ast::ty,
+               output: @ast::Ty,
                +body: ast::blk) -> @ast::item {
         self.item_fn_poly(name, inputs, output, ~[], body)
     }
@@ -256,7 +256,7 @@ impl ext_ctxt: ext_ctxt_ast_builder {
 
     fn variant(name: ident,
                span: span,
-               +tys: ~[@ast::ty]) -> ast::variant {
+               +tys: ~[@ast::Ty]) -> ast::variant {
         let args = tys.map(|ty| {ty: *ty, id: self.next_id()});
 
         {node: {name: name,
@@ -278,13 +278,13 @@ impl ext_ctxt: ext_ctxt_ast_builder {
                       items: items}))
     }
 
-    fn ty_path_ast_builder(path: @ast::path) -> @ast::ty {
+    fn ty_path_ast_builder(path: @ast::path) -> @ast::Ty {
         @{id: self.next_id(),
           node: ast::ty_path(path, self.next_id()),
           span: path.span}
     }
 
-    fn ty_nil_ast_builder() -> @ast::ty {
+    fn ty_nil_ast_builder() -> @ast::Ty {
         @{id: self.next_id(),
           node: ast::ty_nil,
           span: self.empty_span()}
@@ -292,16 +292,16 @@ impl ext_ctxt: ext_ctxt_ast_builder {
 
     fn item_ty_poly(name: ident,
                     span: span,
-                    ty: @ast::ty,
+                    ty: @ast::Ty,
                     +params: ~[ast::ty_param]) -> @ast::item {
         self.item(name, span, ast::item_ty(ty, params))
     }
 
-    fn item_ty(name: ident, span: span, ty: @ast::ty) -> @ast::item {
+    fn item_ty(name: ident, span: span, ty: @ast::Ty) -> @ast::item {
         self.item_ty_poly(name, span, ty, ~[])
     }
 
-    fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::ty] {
+    fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::Ty] {
         ty_params.map(|p| self.ty_path_ast_builder(
             path(~[p.ident], self.empty_span())))
     }
diff --git a/src/libsyntax/ext/pipes/check.rs b/src/libsyntax/ext/pipes/check.rs
index 5fcc00ef012..fcc0c84a4ff 100644
--- a/src/libsyntax/ext/pipes/check.rs
+++ b/src/libsyntax/ext/pipes/check.rs
@@ -38,7 +38,7 @@ impl ext_ctxt: proto::visitor<(), (), ()>  {
         }
     }
 
-    fn visit_message(name: ~str, _span: span, _tys: &[@ast::ty],
+    fn visit_message(name: ~str, _span: span, _tys: &[@ast::Ty],
                      this: state, next: next_state) {
         match next {
           Some({state: next, tys: next_tys}) => {
@@ -68,4 +68,4 @@ impl ext_ctxt: proto::visitor<(), (), ()>  {
           None => ()
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/libsyntax/ext/pipes/parse_proto.rs b/src/libsyntax/ext/pipes/parse_proto.rs
index 5c15b616b4a..8f2b92a720c 100644
--- a/src/libsyntax/ext/pipes/parse_proto.rs
+++ b/src/libsyntax/ext/pipes/parse_proto.rs
@@ -10,7 +10,7 @@ trait proto_parser {
     fn parse_state(proto: protocol);
 }
 
-impl parser: proto_parser {
+impl parser::Parser: proto_parser {
     fn parse_proto(id: ~str) -> protocol {
         let proto = protocol(id, self.span);
 
diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs
index 874ea01e9b0..7e1cbe9ad0d 100644
--- a/src/libsyntax/ext/pipes/pipec.rs
+++ b/src/libsyntax/ext/pipes/pipec.rs
@@ -181,7 +181,7 @@ impl message: gen_send {
           }
         }
 
-    fn to_ty(cx: ext_ctxt) -> @ast::ty {
+    fn to_ty(cx: ext_ctxt) -> @ast::Ty {
         cx.ty_path_ast_builder(path(~[cx.ident_of(self.name())], self.span())
           .add_tys(cx.ty_vars(self.get_params())))
     }
@@ -360,7 +360,7 @@ impl protocol: gen_init {
         }}
     }
 
-    fn buffer_ty_path(cx: ext_ctxt) -> @ast::ty {
+    fn buffer_ty_path(cx: ext_ctxt) -> @ast::Ty {
         let mut params: ~[ast::ty_param] = ~[];
         for (copy self.states).each |s| {
             for s.ty_params.each |tp| {
@@ -444,13 +444,13 @@ impl ~[@ast::item]: to_source {
     }
 }
 
-impl @ast::ty: to_source {
+impl @ast::Ty: to_source {
     fn to_source(cx: ext_ctxt) -> ~str {
         ty_to_str(self, cx.parse_sess().interner)
     }
 }
 
-impl ~[@ast::ty]: to_source {
+impl ~[@ast::Ty]: to_source {
     fn to_source(cx: ext_ctxt) -> ~str {
         str::connect(self.map(|i| i.to_source(cx)), ~", ")
     }
diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs
index 6d58d209fcf..229e55fdfcc 100644
--- a/src/libsyntax/ext/pipes/proto.rs
+++ b/src/libsyntax/ext/pipes/proto.rs
@@ -18,7 +18,7 @@ impl direction : cmp::Eq {
 }
 
 impl direction: ToStr {
-    fn to_str() -> ~str {
+    pure fn to_str() -> ~str {
         match self {
           send => ~"Send",
           recv => ~"Recv"
@@ -35,11 +35,11 @@ impl direction {
     }
 }
 
-type next_state = Option<{state: ~str, tys: ~[@ast::ty]}>;
+type next_state = Option<{state: ~str, tys: ~[@ast::Ty]}>;
 
 enum message {
     // name, span, data, current state, next state
-    message(~str, span, ~[@ast::ty], state, next_state)
+    message(~str, span, ~[@ast::Ty], state, next_state)
 }
 
 impl message {
@@ -78,7 +78,7 @@ enum state {
 
 impl state {
     fn add_message(name: ~str, span: span,
-                   +data: ~[@ast::ty], next: next_state) {
+                   +data: ~[@ast::Ty], next: next_state) {
         self.messages.push(message(name, span, data, self,
                                    next));
     }
@@ -92,7 +92,7 @@ impl state {
     }
 
     /// Returns the type that is used for the messages.
-    fn to_ty(cx: ext_ctxt) -> @ast::ty {
+    fn to_ty(cx: ext_ctxt) -> @ast::Ty {
         cx.ty_path_ast_builder
             (path(~[cx.ident_of(self.name)],self.span).add_tys(
                 cx.ty_vars(self.ty_params)))
@@ -200,7 +200,7 @@ impl protocol {
 trait visitor<Tproto, Tstate, Tmessage> {
     fn visit_proto(proto: protocol, st: &[Tstate]) -> Tproto;
     fn visit_state(state: state, m: &[Tmessage]) -> Tstate;
-    fn visit_message(name: ~str, spane: span, tys: &[@ast::ty],
+    fn visit_message(name: ~str, spane: span, tys: &[@ast::Ty],
                      this: state, next: next_state) -> Tmessage;
 }
 
diff --git a/src/libsyntax/ext/qquote.rs b/src/libsyntax/ext/qquote.rs
index 342743d8c46..af7ffaa73f5 100644
--- a/src/libsyntax/ext/qquote.rs
+++ b/src/libsyntax/ext/qquote.rs
@@ -1,7 +1,7 @@
 use ast::{crate, expr_, mac_invoc,
                      mac_aq, mac_var};
 use parse::parser;
-use parse::parser::parse_from_source_str;
+use parse::parser::{Parser, parse_from_source_str};
 use dvec::DVec;
 use parse::token::ident_interner;
 
@@ -24,7 +24,7 @@ struct gather_item {
 type aq_ctxt = @{lo: uint, gather: DVec<gather_item>};
 enum fragment {
     from_expr(@ast::expr),
-    from_ty(@ast::ty)
+    from_ty(@ast::Ty)
 }
 
 fn ids_ext(cx: ext_ctxt, strs: ~[~str]) -> ~[ast::ident] {
@@ -68,7 +68,7 @@ impl @ast::expr: qq_helper {
     }
     fn get_fold_fn() -> ~str {~"fold_expr"}
 }
-impl @ast::ty: qq_helper {
+impl @ast::Ty: qq_helper {
     fn span() -> span {self.span}
     fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_ty(self, cx, v);}
     fn extract_mac() -> Option<ast::mac_> {
@@ -186,13 +186,13 @@ fn expand_ast(ecx: ext_ctxt, _sp: span,
     };
 }
 
-fn parse_crate(p: parser) -> @ast::crate { p.parse_crate_mod(~[]) }
-fn parse_ty(p: parser) -> @ast::ty { p.parse_ty(false) }
-fn parse_stmt(p: parser) -> @ast::stmt { p.parse_stmt(~[]) }
-fn parse_expr(p: parser) -> @ast::expr { p.parse_expr() }
-fn parse_pat(p: parser) -> @ast::pat { p.parse_pat(true) }
+fn parse_crate(p: Parser) -> @ast::crate { p.parse_crate_mod(~[]) }
+fn parse_ty(p: Parser) -> @ast::Ty { p.parse_ty(false) }
+fn parse_stmt(p: Parser) -> @ast::stmt { p.parse_stmt(~[]) }
+fn parse_expr(p: Parser) -> @ast::expr { p.parse_expr() }
+fn parse_pat(p: Parser) -> @ast::pat { p.parse_pat(true) }
 
-fn parse_item(p: parser) -> @ast::item {
+fn parse_item(p: Parser) -> @ast::item {
     match p.parse_item(~[]) {
       Some(item) => item,
       None       => fail ~"parse_item: parsing an item failed"
@@ -200,7 +200,7 @@ fn parse_item(p: parser) -> @ast::item {
 }
 
 fn finish<T: qq_helper>
-    (ecx: ext_ctxt, body: ast::mac_body_, f: fn (p: parser) -> T)
+    (ecx: ext_ctxt, body: ast::mac_body_, f: fn (p: Parser) -> T)
     -> @ast::expr
 {
     let cm = ecx.codemap();
@@ -309,7 +309,7 @@ fn fold_crate(f: ast_fold, &&n: @ast::crate) -> @ast::crate {
     @f.fold_crate(*n)
 }
 fn fold_expr(f: ast_fold, &&n: @ast::expr) -> @ast::expr {f.fold_expr(n)}
-fn fold_ty(f: ast_fold, &&n: @ast::ty) -> @ast::ty {f.fold_ty(n)}
+fn fold_ty(f: ast_fold, &&n: @ast::Ty) -> @ast::Ty {f.fold_ty(n)}
 fn fold_item(f: ast_fold, &&n: @ast::item) -> @ast::item {
     f.fold_item(n).get() //HACK: we know we don't drop items
 }
diff --git a/src/libsyntax/ext/simplext.rs b/src/libsyntax/ext/simplext.rs
index e16e1c55349..bec29c9a835 100644
--- a/src/libsyntax/ext/simplext.rs
+++ b/src/libsyntax/ext/simplext.rs
@@ -6,7 +6,7 @@ use base::*;
 
 use fold::*;
 use ast_util::respan;
-use ast::{ident, path, ty, blk_, expr, expr_path,
+use ast::{ident, path, Ty, blk_, expr, expr_path,
              expr_vec, expr_mac, mac_invoc, node_id, expr_index};
 
 export add_new_extension;
@@ -29,7 +29,7 @@ enum matchable {
     match_expr(@expr),
     match_path(@path),
     match_ident(ast::spanned<ident>),
-    match_ty(@ty),
+    match_ty(@Ty),
     match_block(ast::blk),
     match_exact, /* don't bind anything, just verify the AST traversal */
 }
diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs
index c2d4de1b423..0c7d408db7c 100644
--- a/src/libsyntax/ext/trace_macros.rs
+++ b/src/libsyntax/ext/trace_macros.rs
@@ -2,7 +2,7 @@ use codemap::span;
 use ext::base::ext_ctxt;
 use ast::tt_delim;
 use parse::lexer::{new_tt_reader, reader};
-use parse::parser::{parser, SOURCE_FILE};
+use parse::parser::{Parser, SOURCE_FILE};
 use parse::common::parser_common;
 
 fn expand_trace_macros(cx: ext_ctxt, sp: span,
@@ -13,7 +13,7 @@ fn expand_trace_macros(cx: ext_ctxt, sp: span,
     let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic,
                                cx.parse_sess().interner, None, tt);
     let rdr = tt_rdr as reader;
-    let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE);
+    let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE);
 
     let arg = cx.str_of(rust_parser.parse_ident());
     match arg {
@@ -21,7 +21,7 @@ fn expand_trace_macros(cx: ext_ctxt, sp: span,
       ~"false" => cx.set_trace_macros(false),
       _ => cx.span_fatal(sp, ~"trace_macros! only accepts `true` or `false`")
     }
-    let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE);
+    let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE);
     let result = rust_parser.parse_expr();
     base::mr_expr(result)
 }
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 16e3454ca2c..17122b85fb3 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -1,9 +1,9 @@
 // Earley-like parser for macros.
 use parse::token;
-use parse::token::{token, EOF, to_str, nonterminal};
+use parse::token::{Token, EOF, to_str, nonterminal};
 use parse::lexer::*; //resolve bug?
 //import parse::lexer::{reader, tt_reader, tt_reader_as_reader};
-use parse::parser::{parser,SOURCE_FILE};
+use parse::parser::{Parser, SOURCE_FILE};
 //import parse::common::parser_common;
 use parse::common::*; //resolve bug?
 use parse::parse_sess;
@@ -97,7 +97,7 @@ fn is_some(&&mpu: matcher_pos_up) -> bool {
 
 type matcher_pos = ~{
     elts: ~[ast::matcher], // maybe should be /&? Need to understand regions.
-    sep: Option<token>,
+    sep: Option<Token>,
     mut idx: uint,
     mut up: matcher_pos_up, // mutable for swapping only
     matches: ~[DVec<@named_match>],
@@ -122,7 +122,7 @@ fn count_names(ms: &[matcher]) -> uint {
 }
 
 #[allow(non_implicitly_copyable_typarams)]
-fn initial_matcher_pos(ms: ~[matcher], sep: Option<token>, lo: uint)
+fn initial_matcher_pos(ms: ~[matcher], sep: Option<Token>, lo: uint)
     -> matcher_pos {
     let mut match_idx_hi = 0u;
     for ms.each() |elt| {
@@ -345,7 +345,7 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher])
                      built-in NTs %s or %u other options.",
                     nts, next_eis.len()));
             } else if (bb_eis.len() == 0u && next_eis.len() == 0u) {
-                return failure(sp, ~"No rules expected the token "
+                return failure(sp, ~"No rules expected the token: "
                             + to_str(rdr.interner(), tok));
             } else if (next_eis.len() > 0u) {
                 /* Now process the next token */
@@ -354,7 +354,7 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher])
                 }
                 rdr.next_token();
             } else /* bb_eis.len() == 1 */ {
-                let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE);
+                let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE);
 
                 let ei = bb_eis.pop();
                 match ei.elts[ei.idx].node {
@@ -381,7 +381,7 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher])
     }
 }
 
-fn parse_nt(p: parser, name: ~str) -> nonterminal {
+fn parse_nt(p: Parser, name: ~str) -> nonterminal {
     match name {
       ~"item" => match p.parse_item(~[]) {
         Some(i) => token::nt_item(i),
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 52369ad7207..31bc375a76d 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -4,7 +4,7 @@ use ast::{ident, matcher_, matcher, match_tok,
              match_nonterminal, match_seq, tt_delim};
 use parse::lexer::{new_tt_reader, reader};
 use parse::token::{FAT_ARROW, SEMI, LBRACE, RBRACE, nt_matchers, nt_tt};
-use parse::parser::{parser, SOURCE_FILE};
+use parse::parser::{Parser, SOURCE_FILE};
 use macro_parser::{parse, parse_or_else, success, failure, named_match,
                       matched_seq, matched_nonterminal, error};
 use std::map::HashMap;
@@ -86,7 +86,7 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident,
                     // rhs has holes ( `$id` and `$(...)` that need filled)
                     let trncbr = new_tt_reader(s_d, itr, Some(named_matches),
                                                ~[rhs]);
-                    let p = parser(cx.parse_sess(), cx.cfg(),
+                    let p = Parser(cx.parse_sess(), cx.cfg(),
                                    trncbr as reader, SOURCE_FILE);
                     let e = p.parse_expr();
                     return mr_expr(e);
@@ -111,4 +111,4 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident,
         name: *cx.parse_sess().interner.get(name),
         ext: expr_tt({expander: exp, span: Some(sp)})
     });
-}
\ No newline at end of file
+}
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index a8a41cca6cb..238f9db6ac5 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -2,8 +2,7 @@ use diagnostic::span_handler;
 use ast::{token_tree, tt_delim, tt_tok, tt_seq, tt_nonterminal,ident};
 use macro_parser::{named_match, matched_seq, matched_nonterminal};
 use codemap::span;
-use parse::token::{EOF, INTERPOLATED, IDENT, token, nt_ident,
-                      ident_interner};
+use parse::token::{EOF, INTERPOLATED, IDENT, Token, nt_ident, ident_interner};
 use std::map::HashMap;
 
 export tt_reader,  new_tt_reader, dup_tt_reader, tt_next_token;
@@ -19,7 +18,7 @@ type tt_frame = @{
     readme: ~[ast::token_tree],
     mut idx: uint,
     dotdotdoted: bool,
-    sep: Option<token>,
+    sep: Option<Token>,
     up: tt_frame_up,
 };
 
@@ -32,7 +31,7 @@ type tt_reader = @{
     mut repeat_idx: ~[uint],
     mut repeat_len: ~[uint],
     /* cached: */
-    mut cur_tok: token,
+    mut cur_tok: Token,
     mut cur_span: span
 };
 
@@ -134,7 +133,7 @@ fn lockstep_iter_size(t: token_tree, r: tt_reader) -> lis {
 }
 
 
-fn tt_next_token(&&r: tt_reader) -> {tok: token, sp: span} {
+fn tt_next_token(&&r: tt_reader) -> {tok: Token, sp: span} {
     let ret_val = { tok: r.cur_tok, sp: r.cur_span };
     while r.cur.idx >= r.cur.readme.len() {
         /* done with this set; pop or repeat? */
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 088df01985e..311928dd4e0 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -33,7 +33,7 @@ trait ast_fold {
     fn fold_pat(&&v: @pat) -> @pat;
     fn fold_decl(&&v: @decl) -> @decl;
     fn fold_expr(&&v: @expr) -> @expr;
-    fn fold_ty(&&v: @ty) -> @ty;
+    fn fold_ty(&&v: @Ty) -> @Ty;
     fn fold_mod(_mod) -> _mod;
     fn fold_foreign_mod(foreign_mod) -> foreign_mod;
     fn fold_variant(variant) -> variant;
@@ -131,10 +131,7 @@ fn fold_fn_decl(decl: ast::fn_decl, fld: ast_fold) -> ast::fn_decl {
 }
 
 fn fold_ty_param_bound(tpb: ty_param_bound, fld: ast_fold) -> ty_param_bound {
-    match tpb {
-      bound_copy | bound_send | bound_const | bound_owned => tpb,
-      bound_trait(ty) => bound_trait(fld.fold_ty(ty))
-    }
+    ty_param_bound(fld.fold_ty(*tpb))
 }
 
 fn fold_ty_param(tp: ty_param, fld: ast_fold) -> ty_param {
@@ -271,23 +268,6 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
 
 fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold)
                 -> @ast::struct_def {
-    let resulting_optional_constructor;
-    match struct_def.ctor {
-        None => {
-            resulting_optional_constructor = None;
-        }
-        Some(constructor) => {
-            resulting_optional_constructor = Some({
-                node: {
-                    body: fld.fold_block(constructor.node.body),
-                    dec: fold_fn_decl(constructor.node.dec, fld),
-                    id: fld.new_id(constructor.node.id),
-                    .. constructor.node
-                },
-                .. constructor
-            });
-        }
-    }
     let dtor = do option::map(&struct_def.dtor) |dtor| {
         let dtor_body = fld.fold_block(dtor.node.body);
         let dtor_id   = fld.new_id(dtor.node.id);
@@ -298,7 +278,6 @@ fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold)
         traits: vec::map(struct_def.traits, |p| fold_trait_ref(*p, fld)),
         fields: vec::map(struct_def.fields, |f| fold_struct_field(*f, fld)),
         methods: vec::map(struct_def.methods, |m| fld.fold_method(*m)),
-        ctor: resulting_optional_constructor,
         dtor: dtor
     };
 }
@@ -585,7 +564,6 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ {
                                  |f| fld.fold_struct_field(*f)),
                 methods: vec::map(struct_def.methods,
                                   |m| fld.fold_method(*m)),
-                ctor: None,
                 dtor: dtor
             })
         }
@@ -747,7 +725,7 @@ impl ast_fold_precursor: ast_fold {
               node: n,
               span: self.new_span(s)};
     }
-    fn fold_ty(&&x: @ty) -> @ty {
+    fn fold_ty(&&x: @Ty) -> @Ty {
         let (n, s) = self.fold_ty(x.node, x.span, self as ast_fold);
         return @{id: self.new_id(x.id), node: n, span: self.new_span(s)};
     }
diff --git a/src/libsyntax/parse.rs b/src/libsyntax/parse.rs
index 2c04b2a1419..e38ee7ff037 100644
--- a/src/libsyntax/parse.rs
+++ b/src/libsyntax/parse.rs
@@ -12,7 +12,7 @@ export parse_expr_from_source_str, parse_item_from_source_str;
 export parse_stmt_from_source_str;
 export parse_from_source_str;
 
-use parser::parser;
+use parser::Parser;
 use attr::parser_attr;
 use common::parser_common;
 use ast::node_id;
@@ -22,7 +22,7 @@ use lexer::{reader, string_reader};
 use parse::token::{ident_interner, mk_ident_interner};
 
 type parse_sess = @{
-    cm: codemap::codemap,
+    cm: codemap::CodeMap,
     mut next_id: node_id,
     span_diagnostic: span_handler,
     interner: @ident_interner,
@@ -40,7 +40,7 @@ fn new_parse_sess(demitter: Option<emitter>) -> parse_sess {
              mut chpos: 0u, mut byte_pos: 0u};
 }
 
-fn new_parse_sess_special_handler(sh: span_handler, cm: codemap::codemap)
+fn new_parse_sess_special_handler(sh: span_handler, cm: codemap::CodeMap)
     -> parse_sess {
     return @{cm: cm,
              mut next_id: 1,
@@ -142,7 +142,7 @@ fn parse_stmt_from_source_str(name: ~str, source: @~str, cfg: ast::crate_cfg,
     return r;
 }
 
-fn parse_from_source_str<T>(f: fn (p: parser) -> T,
+fn parse_from_source_str<T>(f: fn (p: Parser) -> T,
                             name: ~str, ss: codemap::file_substr,
                             source: @~str, cfg: ast::crate_cfg,
                             sess: parse_sess)
@@ -170,19 +170,19 @@ fn next_node_id(sess: parse_sess) -> node_id {
 
 fn new_parser_etc_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
                                   +name: ~str, +ss: codemap::file_substr,
-                                  source: @~str) -> (parser, string_reader) {
+                                  source: @~str) -> (Parser, string_reader) {
     let ftype = parser::SOURCE_FILE;
     let filemap = codemap::new_filemap_w_substr
         (name, ss, source, sess.chpos, sess.byte_pos);
     sess.cm.files.push(filemap);
     let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap,
                                         sess.interner);
-    return (parser(sess, cfg, srdr as reader, ftype), srdr);
+    return (Parser(sess, cfg, srdr as reader, ftype), srdr);
 }
 
 fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
                               +name: ~str, +ss: codemap::file_substr,
-                              source: @~str) -> parser {
+                              source: @~str) -> Parser {
     let (p, _) = new_parser_etc_from_source_str(sess, cfg, name, ss, source);
     move p
 }
@@ -190,7 +190,7 @@ fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
 
 fn new_parser_etc_from_file(sess: parse_sess, cfg: ast::crate_cfg,
                             path: &Path, ftype: parser::file_type) ->
-   (parser, string_reader) {
+   (Parser, string_reader) {
     let res = io::read_whole_file_str(path);
     match res {
       result::Ok(_) => { /* Continue. */ }
@@ -202,18 +202,18 @@ fn new_parser_etc_from_file(sess: parse_sess, cfg: ast::crate_cfg,
     sess.cm.files.push(filemap);
     let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap,
                                         sess.interner);
-    return (parser(sess, cfg, srdr as reader, ftype), srdr);
+    return (Parser(sess, cfg, srdr as reader, ftype), srdr);
 }
 
 fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, path: &Path,
-                        ftype: parser::file_type) -> parser {
+                        ftype: parser::file_type) -> Parser {
     let (p, _) = new_parser_etc_from_file(sess, cfg, path, ftype);
     move p
 }
 
 fn new_parser_from_tt(sess: parse_sess, cfg: ast::crate_cfg,
-                      tt: ~[ast::token_tree]) -> parser {
+                      tt: ~[ast::token_tree]) -> Parser {
     let trdr = lexer::new_tt_reader(sess.span_diagnostic, sess.interner,
                                     None, tt);
-    return parser(sess, cfg, trdr as reader, parser::SOURCE_FILE)
+    return Parser(sess, cfg, trdr as reader, parser::SOURCE_FILE)
 }
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index 9be4909814b..42101a431d6 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -23,7 +23,7 @@ trait parser_attr {
     fn parse_optional_meta() -> ~[@ast::meta_item];
 }
 
-impl parser: parser_attr {
+impl Parser: parser_attr {
 
     fn parse_outer_attrs_or_ext(first_item_attrs: ~[ast::attribute])
         -> attr_or_ext
diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs
index c8c30ee7fa9..50c22c08f4f 100644
--- a/src/libsyntax/parse/common.rs
+++ b/src/libsyntax/parse/common.rs
@@ -1,63 +1,63 @@
 use std::map::{HashMap};
 use ast_util::spanned;
-use parser::parser;
+use parser::Parser;
 use lexer::reader;
 
 type seq_sep = {
-    sep: Option<token::token>,
+    sep: Option<token::Token>,
     trailing_sep_allowed: bool
 };
 
-fn seq_sep_trailing_disallowed(t: token::token) -> seq_sep {
+fn seq_sep_trailing_disallowed(t: token::Token) -> seq_sep {
     return {sep: option::Some(t), trailing_sep_allowed: false};
 }
-fn seq_sep_trailing_allowed(t: token::token) -> seq_sep {
+fn seq_sep_trailing_allowed(t: token::Token) -> seq_sep {
     return {sep: option::Some(t), trailing_sep_allowed: true};
 }
 fn seq_sep_none() -> seq_sep {
     return {sep: option::None, trailing_sep_allowed: false};
 }
 
-fn token_to_str(reader: reader, ++token: token::token) -> ~str {
+fn token_to_str(reader: reader, ++token: token::Token) -> ~str {
     token::to_str(reader.interner(), token)
 }
 
 trait parser_common {
-    fn unexpected_last(t: token::token) -> !;
+    fn unexpected_last(t: token::Token) -> !;
     fn unexpected() -> !;
-    fn expect(t: token::token);
+    fn expect(t: token::Token);
     fn parse_ident() -> ast::ident;
     fn parse_path_list_ident() -> ast::path_list_ident;
     fn parse_value_ident() -> ast::ident;
-    fn eat(tok: token::token) -> bool;
+    fn eat(tok: token::Token) -> bool;
     // A sanity check that the word we are asking for is a known keyword
     fn require_keyword(word: ~str);
-    fn token_is_keyword(word: ~str, ++tok: token::token) -> bool;
+    fn token_is_keyword(word: ~str, ++tok: token::Token) -> bool;
     fn is_keyword(word: ~str) -> bool;
-    fn is_any_keyword(tok: token::token) -> bool;
+    fn is_any_keyword(tok: token::Token) -> bool;
     fn eat_keyword(word: ~str) -> bool;
     fn expect_keyword(word: ~str);
     fn expect_gt();
-    fn parse_seq_to_before_gt<T: Copy>(sep: Option<token::token>,
-                                       f: fn(parser) -> T) -> ~[T];
-    fn parse_seq_to_gt<T: Copy>(sep: Option<token::token>,
-                                f: fn(parser) -> T) -> ~[T];
-    fn parse_seq_lt_gt<T: Copy>(sep: Option<token::token>,
-                                f: fn(parser) -> T) -> spanned<~[T]>;
-    fn parse_seq_to_end<T: Copy>(ket: token::token, sep: seq_sep,
-                                 f: fn(parser) -> T) -> ~[T];
-    fn parse_seq_to_before_end<T: Copy>(ket: token::token, sep: seq_sep,
-                                        f: fn(parser) -> T) -> ~[T];
-    fn parse_unspanned_seq<T: Copy>(bra: token::token,
-                                    ket: token::token,
+    fn parse_seq_to_before_gt<T: Copy>(sep: Option<token::Token>,
+                                       f: fn(Parser) -> T) -> ~[T];
+    fn parse_seq_to_gt<T: Copy>(sep: Option<token::Token>,
+                                f: fn(Parser) -> T) -> ~[T];
+    fn parse_seq_lt_gt<T: Copy>(sep: Option<token::Token>,
+                                f: fn(Parser) -> T) -> spanned<~[T]>;
+    fn parse_seq_to_end<T: Copy>(ket: token::Token, sep: seq_sep,
+                                 f: fn(Parser) -> T) -> ~[T];
+    fn parse_seq_to_before_end<T: Copy>(ket: token::Token, sep: seq_sep,
+                                        f: fn(Parser) -> T) -> ~[T];
+    fn parse_unspanned_seq<T: Copy>(bra: token::Token,
+                                    ket: token::Token,
                                     sep: seq_sep,
-                                    f: fn(parser) -> T) -> ~[T];
-    fn parse_seq<T: Copy>(bra: token::token, ket: token::token, sep: seq_sep,
-                          f: fn(parser) -> T) -> spanned<~[T]>;
+                                    f: fn(Parser) -> T) -> ~[T];
+    fn parse_seq<T: Copy>(bra: token::Token, ket: token::Token, sep: seq_sep,
+                          f: fn(Parser) -> T) -> spanned<~[T]>;
 }
 
-impl parser: parser_common {
-    fn unexpected_last(t: token::token) -> ! {
+impl Parser: parser_common {
+    fn unexpected_last(t: token::Token) -> ! {
         self.span_fatal(
             copy self.last_span,
             ~"unexpected token: `" + token_to_str(self.reader, t) + ~"`");
@@ -68,7 +68,7 @@ impl parser: parser_common {
                    + token_to_str(self.reader, self.token) + ~"`");
     }
 
-    fn expect(t: token::token) {
+    fn expect(t: token::Token) {
         if self.token == t {
             self.bump();
         } else {
@@ -104,7 +104,7 @@ impl parser: parser_common {
         return self.parse_ident();
     }
 
-    fn eat(tok: token::token) -> bool {
+    fn eat(tok: token::Token) -> bool {
         return if self.token == tok { self.bump(); true } else { false };
     }
 
@@ -117,14 +117,14 @@ impl parser: parser_common {
         }
     }
 
-    fn token_is_word(word: ~str, ++tok: token::token) -> bool {
+    fn token_is_word(word: ~str, ++tok: token::Token) -> bool {
         match tok {
           token::IDENT(sid, false) => { *self.id_to_str(sid) == word }
           _ => { false }
         }
     }
 
-    fn token_is_keyword(word: ~str, ++tok: token::token) -> bool {
+    fn token_is_keyword(word: ~str, ++tok: token::Token) -> bool {
         self.require_keyword(word);
         self.token_is_word(word, tok)
     }
@@ -133,7 +133,7 @@ impl parser: parser_common {
         self.token_is_keyword(word, self.token)
     }
 
-    fn is_any_keyword(tok: token::token) -> bool {
+    fn is_any_keyword(tok: token::Token) -> bool {
         match tok {
           token::IDENT(sid, false) => {
             self.keywords.contains_key_ref(self.id_to_str(sid))
@@ -216,8 +216,8 @@ impl parser: parser_common {
         }
     }
 
-    fn parse_seq_to_before_gt<T: Copy>(sep: Option<token::token>,
-                                       f: fn(parser) -> T) -> ~[T] {
+    fn parse_seq_to_before_gt<T: Copy>(sep: Option<token::Token>,
+                                       f: fn(Parser) -> T) -> ~[T] {
         let mut first = true;
         let mut v = ~[];
         while self.token != token::GT
@@ -235,16 +235,16 @@ impl parser: parser_common {
         return v;
     }
 
-    fn parse_seq_to_gt<T: Copy>(sep: Option<token::token>,
-                                f: fn(parser) -> T) -> ~[T] {
+    fn parse_seq_to_gt<T: Copy>(sep: Option<token::Token>,
+                                f: fn(Parser) -> T) -> ~[T] {
         let v = self.parse_seq_to_before_gt(sep, f);
         self.expect_gt();
 
         return v;
     }
 
-    fn parse_seq_lt_gt<T: Copy>(sep: Option<token::token>,
-                                f: fn(parser) -> T) -> spanned<~[T]> {
+    fn parse_seq_lt_gt<T: Copy>(sep: Option<token::Token>,
+                                f: fn(Parser) -> T) -> spanned<~[T]> {
         let lo = self.span.lo;
         self.expect(token::LT);
         let result = self.parse_seq_to_before_gt::<T>(sep, f);
@@ -253,16 +253,16 @@ impl parser: parser_common {
         return spanned(lo, hi, result);
     }
 
-    fn parse_seq_to_end<T: Copy>(ket: token::token, sep: seq_sep,
-                                 f: fn(parser) -> T) -> ~[T] {
+    fn parse_seq_to_end<T: Copy>(ket: token::Token, sep: seq_sep,
+                                 f: fn(Parser) -> T) -> ~[T] {
         let val = self.parse_seq_to_before_end(ket, sep, f);
         self.bump();
         return val;
     }
 
 
-    fn parse_seq_to_before_end<T: Copy>(ket: token::token, sep: seq_sep,
-                                        f: fn(parser) -> T) -> ~[T] {
+    fn parse_seq_to_before_end<T: Copy>(ket: token::Token, sep: seq_sep,
+                                        f: fn(Parser) -> T) -> ~[T] {
         let mut first: bool = true;
         let mut v: ~[T] = ~[];
         while self.token != ket {
@@ -279,10 +279,10 @@ impl parser: parser_common {
         return v;
     }
 
-    fn parse_unspanned_seq<T: Copy>(bra: token::token,
-                                    ket: token::token,
+    fn parse_unspanned_seq<T: Copy>(bra: token::Token,
+                                    ket: token::Token,
                                     sep: seq_sep,
-                                    f: fn(parser) -> T) -> ~[T] {
+                                    f: fn(Parser) -> T) -> ~[T] {
         self.expect(bra);
         let result = self.parse_seq_to_before_end::<T>(ket, sep, f);
         self.bump();
@@ -291,8 +291,8 @@ impl parser: parser_common {
 
     // NB: Do not use this function unless you actually plan to place the
     // spanned list in the AST.
-    fn parse_seq<T: Copy>(bra: token::token, ket: token::token, sep: seq_sep,
-                          f: fn(parser) -> T) -> spanned<~[T]> {
+    fn parse_seq<T: Copy>(bra: token::Token, ket: token::Token, sep: seq_sep,
+                          f: fn(Parser) -> T) -> spanned<~[T]> {
         let lo = self.span.lo;
         self.expect(bra);
         let result = self.parse_seq_to_before_end::<T>(ket, sep, f);
diff --git a/src/libsyntax/parse/eval.rs b/src/libsyntax/parse/eval.rs
index c9106028491..56c9d4de9f3 100644
--- a/src/libsyntax/parse/eval.rs
+++ b/src/libsyntax/parse/eval.rs
@@ -1,4 +1,4 @@
-use parser::{parser, SOURCE_FILE};
+use parser::{Parser, SOURCE_FILE};
 use attr::parser_attr;
 
 export eval_crate_directives_to_mod;
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index 06fcc1cf958..8f57d733eb5 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -10,11 +10,11 @@ export string_reader_as_reader, tt_reader_as_reader;
 
 trait reader {
     fn is_eof() -> bool;
-    fn next_token() -> {tok: token::token, sp: span};
+    fn next_token() -> {tok: token::Token, sp: span};
     fn fatal(~str) -> !;
     fn span_diag() -> span_handler;
     pure fn interner() -> @token::ident_interner;
-    fn peek() -> {tok: token::token, sp: span};
+    fn peek() -> {tok: token::Token, sp: span};
     fn dup() -> reader;
 }
 
@@ -28,7 +28,7 @@ type string_reader = @{
     filemap: codemap::filemap,
     interner: @token::ident_interner,
     /* cached: */
-    mut peek_tok: token::token,
+    mut peek_tok: token::Token,
     mut peek_span: span
 };
 
@@ -69,7 +69,7 @@ fn dup_string_reader(&&r: string_reader) -> string_reader {
 
 impl string_reader: reader {
     fn is_eof() -> bool { is_eof(self) }
-    fn next_token() -> {tok: token::token, sp: span} {
+    fn next_token() -> {tok: token::Token, sp: span} {
         let ret_val = {tok: self.peek_tok, sp: self.peek_span};
         string_advance_token(self);
         return ret_val;
@@ -79,7 +79,7 @@ impl string_reader: reader {
     }
     fn span_diag() -> span_handler { self.span_diagnostic }
     pure fn interner() -> @token::ident_interner { self.interner }
-    fn peek() -> {tok: token::token, sp: span} {
+    fn peek() -> {tok: token::Token, sp: span} {
         {tok: self.peek_tok, sp: self.peek_span}
     }
     fn dup() -> reader { dup_string_reader(self) as reader }
@@ -87,7 +87,7 @@ impl string_reader: reader {
 
 impl tt_reader: reader {
     fn is_eof() -> bool { self.cur_tok == token::EOF }
-    fn next_token() -> {tok: token::token, sp: span} {
+    fn next_token() -> {tok: token::Token, sp: span} {
         /* weird resolve bug: if the following `if`, or any of its
         statements are removed, we get resolution errors */
         if false {
@@ -101,7 +101,7 @@ impl tt_reader: reader {
     }
     fn span_diag() -> span_handler { self.sp_diag }
     pure fn interner() -> @token::ident_interner { self.interner }
-    fn peek() -> {tok: token::token, sp: span} {
+    fn peek() -> {tok: token::Token, sp: span} {
         { tok: self.cur_tok, sp: self.cur_span }
     }
     fn dup() -> reader { dup_tt_reader(self) as reader }
@@ -196,14 +196,14 @@ fn is_bin_digit(c: char) -> bool { return c == '0' || c == '1'; }
 
 // might return a sugared-doc-attr
 fn consume_whitespace_and_comments(rdr: string_reader)
-                                -> Option<{tok: token::token, sp: span}> {
+                                -> Option<{tok: token::Token, sp: span}> {
     while is_whitespace(rdr.curr) { bump(rdr); }
     return consume_any_line_comment(rdr);
 }
 
 // might return a sugared-doc-attr
 fn consume_any_line_comment(rdr: string_reader)
-                                -> Option<{tok: token::token, sp: span}> {
+                                -> Option<{tok: token::Token, sp: span}> {
     if rdr.curr == '/' {
         match nextch(rdr) {
           '/' => {
@@ -246,7 +246,7 @@ fn consume_any_line_comment(rdr: string_reader)
 
 // might return a sugared-doc-attr
 fn consume_block_comment(rdr: string_reader)
-                                -> Option<{tok: token::token, sp: span}> {
+                                -> Option<{tok: token::Token, sp: span}> {
 
     // block comments starting with "/**" or "/*!" are doc-comments
     if rdr.curr == '*' || rdr.curr == '!' {
@@ -317,7 +317,7 @@ fn scan_digits(rdr: string_reader, radix: uint) -> ~str {
     };
 }
 
-fn scan_number(c: char, rdr: string_reader) -> token::token {
+fn scan_number(c: char, rdr: string_reader) -> token::Token {
     let mut num_str, base = 10u, c = c, n = nextch(rdr);
     if c == '0' && n == 'x' {
         bump(rdr);
@@ -435,7 +435,7 @@ fn scan_numeric_escape(rdr: string_reader, n_hex_digits: uint) -> char {
     return accum_int as char;
 }
 
-fn next_token_inner(rdr: string_reader) -> token::token {
+fn next_token_inner(rdr: string_reader) -> token::Token {
     let mut accum_str = ~"";
     let mut c = rdr.curr;
     if (c >= 'a' && c <= 'z')
@@ -460,7 +460,7 @@ fn next_token_inner(rdr: string_reader) -> token::token {
     if is_dec_digit(c) {
         return scan_number(c, rdr);
     }
-    fn binop(rdr: string_reader, op: token::binop) -> token::token {
+    fn binop(rdr: string_reader, op: token::binop) -> token::Token {
         bump(rdr);
         if rdr.curr == '=' {
             bump(rdr);
diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs
index 828d498ca3c..1f607d849d9 100644
--- a/src/libsyntax/parse/obsolete.rs
+++ b/src/libsyntax/parse/obsolete.rs
@@ -10,7 +10,7 @@ removed.
 use codemap::span;
 use ast::{expr, expr_lit, lit_nil};
 use ast_util::{respan};
-use token::token;
+use token::Token;
 
 /// The specific types of unsupported syntax
 pub enum ObsoleteSyntax {
@@ -23,7 +23,8 @@ pub enum ObsoleteSyntax {
     ObsoleteClassTraits,
     ObsoletePrivSection,
     ObsoleteModeInFnType,
-    ObsoleteByMutRefMode
+    ObsoleteByMutRefMode,
+    ObsoleteFixedLengthVec,
 }
 
 impl ObsoleteSyntax : cmp::Eq {
@@ -47,7 +48,7 @@ pub trait ObsoleteReporter {
     fn obsolete_expr(sp: span, kind: ObsoleteSyntax) -> @expr;
 }
 
-impl parser : ObsoleteReporter {
+impl Parser : ObsoleteReporter {
     /// Reports an obsolete syntax non-fatal error.
     fn obsolete(sp: span, kind: ObsoleteSyntax) {
         let (kind_str, desc) = match kind {
@@ -99,6 +100,11 @@ impl parser : ObsoleteReporter {
                 "by-mutable-reference mode",
                 "Declare an argument of type &mut T instead"
             ),
+            ObsoleteFixedLengthVec => (
+                "fixed-length vector",
+                "Fixed-length types are now written `[T * N]`, and instances \
+                 are type-inferred"
+            )
         };
 
         self.report(sp, kind, kind_str, desc);
@@ -121,7 +127,7 @@ impl parser : ObsoleteReporter {
         }
     }
 
-    fn token_is_obsolete_ident(ident: &str, token: token) -> bool {
+    fn token_is_obsolete_ident(ident: &str, token: Token) -> bool {
         match token {
             token::IDENT(copy sid, _) => {
                 str::eq_slice(*self.id_to_str(sid), ident)
@@ -183,5 +189,66 @@ impl parser : ObsoleteReporter {
             false
         }
     }
+
+    fn try_parse_obsolete_fixed_vstore() -> Option<Option<uint>> {
+        if self.token == token::BINOP(token::SLASH) {
+            self.bump();
+            match copy self.token {
+                token::UNDERSCORE => {
+                    self.obsolete(copy self.last_span,
+                                  ObsoleteFixedLengthVec);
+                    self.bump(); Some(None)
+                }
+                token::LIT_INT_UNSUFFIXED(i) if i >= 0i64 => {
+                    self.obsolete(copy self.last_span,
+                                  ObsoleteFixedLengthVec);
+                    self.bump(); Some(Some(i as uint))
+                }
+                _ => None
+            }
+        } else {
+            None
+        }
+    }
+
+    fn try_convert_ty_to_obsolete_fixed_length_vstore(sp: span, t: ast::ty_)
+        -> ast::ty_ {
+        match self.try_parse_obsolete_fixed_vstore() {
+            // Consider a fixed length vstore suffix (/N or /_)
+            None => t,
+            Some(v) => {
+                ast::ty_fixed_length(
+                    @{id: self.get_id(), node: t, span: sp}, v)
+            }
+        }
+    }
+
+    fn try_convert_expr_to_obsolete_fixed_length_vstore(
+        lo: uint, hi: uint, ex: ast::expr_
+    ) -> (uint, ast::expr_) {
+
+        let mut hi = hi;
+        let mut ex = ex;
+
+        // Vstore is legal following expr_lit(lit_str(...)) and expr_vec(...)
+        // only.
+        match ex {
+            ast::expr_lit(@{node: ast::lit_str(_), span: _}) |
+            ast::expr_vec(_, _)  => {
+                match self.try_parse_obsolete_fixed_vstore() {
+                    None => (),
+                    Some(v) => {
+                        hi = self.span.hi;
+                        ex = ast::expr_vstore(self.mk_expr(lo, hi, ex),
+                                              ast::expr_vstore_fixed(v));
+                    }
+                }
+            }
+            _ => ()
+        }
+
+        return (hi, ex);
+    }
+
 }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 22c25186c91..925da063ca6 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -6,7 +6,7 @@ use std::map::HashMap;
 use token::{can_begin_expr, is_ident, is_ident_or_path, is_plain_ident,
             INTERPOLATED, special_idents};
 use codemap::{span,fss_none};
-use util::interner::interner;
+use util::interner::Interner;
 use ast_util::{spanned, respan, mk_sp, ident_to_path, operator_prec};
 use lexer::reader;
 use prec::{as_prec, token_to_binop};
@@ -22,10 +22,9 @@ use obsolete::{
     ObsoleteWith, ObsoleteClassMethod, ObsoleteClassTraits,
     ObsoleteModeInFnType, ObsoleteByMutRefMode
 };
-use ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
+use ast::{_mod, add, arg, arm, attribute,
              bind_by_ref, bind_by_implicit_ref, bind_by_value, bind_by_move,
-             bitand, bitor, bitxor, blk, blk_check_mode, bound_const,
-             bound_copy, bound_send, bound_trait, bound_owned, box, by_copy,
+             bitand, bitor, bitxor, blk, blk_check_mode, box, by_copy,
              by_move, by_ref, by_val, capture_clause,
              capture_item, cdir_dir_mod, cdir_src_mod, cdir_view_item,
              class_immutable, class_mutable,
@@ -58,7 +57,7 @@ use ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
              stmt_semi, struct_def, struct_field, struct_variant_kind,
              subtract, sty_box, sty_by_ref, sty_region, sty_static, sty_uniq,
              sty_value, token_tree, trait_method, trait_ref, tt_delim, tt_seq,
-             tt_tok, tt_nonterminal, tuple_variant_kind, ty, ty_, ty_bot,
+             tt_tok, tt_nonterminal, tuple_variant_kind, Ty, ty_, ty_bot,
              ty_box, ty_field, ty_fn, ty_infer, ty_mac, ty_method, ty_nil,
              ty_param, ty_param_bound, ty_path, ty_ptr, ty_rec, ty_rptr,
              ty_tup, ty_u32, ty_uniq, ty_vec, ty_fixed_length, type_value_ns,
@@ -71,11 +70,11 @@ use ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
              expr_vstore_uniq};
 
 export file_type;
-export parser;
+export Parser;
 export CRATE_FILE;
 export SOURCE_FILE;
 
-// FIXME (#1893): #ast expects to find this here but it's actually
+// FIXME (#3726): #ast expects to find this here but it's actually
 // defined in `parse` Fixing this will be easier when we have export
 // decls on individual items -- then parse can export this publicly, and
 // everything else crate-visibly.
@@ -115,8 +114,7 @@ enum class_member {
   So that we can distinguish a class ctor or dtor
   from other class members
  */
-enum class_contents { ctor_decl(fn_decl, ~[attribute], blk, codemap::span),
-                      dtor_decl(blk, ~[attribute], codemap::span),
+enum class_contents { dtor_decl(blk, ~[attribute], codemap::span),
                       members(~[@class_member]) }
 
 type arg_or_capture_item = Either<arg, capture_item>;
@@ -125,12 +123,13 @@ type item_info = (ident, item_, Option<~[attribute]>);
 enum item_or_view_item {
     iovi_none,
     iovi_item(@item),
+    iovi_foreign_item(@foreign_item),
     iovi_view_item(@view_item)
 }
 
 enum view_item_parse_mode {
     VIEW_ITEMS_AND_ITEMS_ALLOWED,
-    VIEW_ITEMS_ALLOWED,
+    VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED,
     IMPORTS_AND_ITEMS_ALLOWED
 }
 
@@ -191,14 +190,14 @@ pure fn maybe_append(+lhs: ~[attribute], rhs: Option<~[attribute]>)
 
 /* ident is handled by common.rs */
 
-fn parser(sess: parse_sess, cfg: ast::crate_cfg,
-          +rdr: reader, ftype: file_type) -> parser {
+fn Parser(sess: parse_sess, cfg: ast::crate_cfg,
+          +rdr: reader, ftype: file_type) -> Parser {
 
     let tok0 = rdr.next_token();
     let span0 = tok0.sp;
     let interner = rdr.interner();
 
-    parser {
+    Parser {
         reader: move rdr,
         interner: move interner,
         sess: sess,
@@ -207,12 +206,7 @@ fn parser(sess: parse_sess, cfg: ast::crate_cfg,
         token: tok0.tok,
         span: span0,
         last_span: span0,
-        buffer: [mut
-            {tok: tok0.tok, sp: span0},
-            {tok: tok0.tok, sp: span0},
-            {tok: tok0.tok, sp: span0},
-            {tok: tok0.tok, sp: span0}
-        ]/4,
+        buffer: [mut {tok: tok0.tok, sp: span0}, ..4],
         buffer_start: 0,
         buffer_end: 0,
         restriction: UNRESTRICTED,
@@ -224,14 +218,14 @@ fn parser(sess: parse_sess, cfg: ast::crate_cfg,
     }
 }
 
-struct parser {
+struct Parser {
     sess: parse_sess,
     cfg: crate_cfg,
     file_type: file_type,
-    mut token: token::token,
+    mut token: token::Token,
     mut span: span,
     mut last_span: span,
-    mut buffer: [mut {tok: token::token, sp: span}]/4,
+    mut buffer: [mut {tok: token::Token, sp: span} * 4],
     mut buffer_start: int,
     mut buffer_end: int,
     mut restriction: restriction,
@@ -248,7 +242,7 @@ struct parser {
     drop {} /* do not copy the parser; its state is tied to outside state */
 }
 
-impl parser {
+impl Parser {
     fn bump() {
         self.last_span = self.span;
         let next = if self.buffer_start == self.buffer_end {
@@ -261,7 +255,7 @@ impl parser {
         self.token = next.tok;
         self.span = next.sp;
     }
-    fn swap(next: token::token, lo: uint, hi: uint) {
+    fn swap(next: token::Token, lo: uint, hi: uint) {
         self.token = next;
         self.span = mk_sp(lo, hi);
     }
@@ -271,7 +265,7 @@ impl parser {
         }
         return (4 - self.buffer_start) + self.buffer_end;
     }
-    fn look_ahead(distance: uint) -> token::token {
+    fn look_ahead(distance: uint) -> token::Token {
         let dist = distance as int;
         while self.buffer_length() < dist {
             self.buffer[self.buffer_end] = self.reader.next_token();
@@ -412,7 +406,7 @@ impl parser {
         });
     }
 
-    fn parse_ret_ty() -> (ret_style, @ty) {
+    fn parse_ret_ty() -> (ret_style, @Ty) {
         return if self.eat(token::RARROW) {
             let lo = self.span.lo;
             if self.eat(token::NOT) {
@@ -473,7 +467,7 @@ impl parser {
         self.region_from_name(name)
     }
 
-    fn parse_ty(colons_before_params: bool) -> @ty {
+    fn parse_ty(colons_before_params: bool) -> @Ty {
         maybe_whole!(self, nt_ty);
 
         let lo = self.span.lo;
@@ -558,14 +552,13 @@ impl parser {
         } else { self.fatal(~"expected type"); };
 
         let sp = mk_sp(lo, self.last_span.hi);
-        return @{id: self.get_id(),
-              node: match self.maybe_parse_fixed_vstore() {
-                // Consider a fixed vstore suffix (/N or /_)
-                None => t,
-                Some(v) => {
-                  ty_fixed_length(@{id: self.get_id(), node:t, span: sp}, v)
-                } },
+        return {
+            let node =
+                self.try_convert_ty_to_obsolete_fixed_length_vstore(sp, t);
+            @{id: self.get_id(),
+              node: node,
               span: sp}
+        };
     }
 
     fn parse_arg_mode() -> mode {
@@ -610,10 +603,10 @@ impl parser {
         }
     }
 
-    fn parse_capture_item_or(parse_arg_fn: fn(parser) -> arg_or_capture_item)
+    fn parse_capture_item_or(parse_arg_fn: fn(Parser) -> arg_or_capture_item)
         -> arg_or_capture_item {
 
-        fn parse_capture_item(p:parser, is_move: bool) -> capture_item {
+        fn parse_capture_item(p:Parser, is_move: bool) -> capture_item {
             let sp = mk_sp(p.span.lo, p.span.hi);
             let ident = p.parse_ident();
             @{id: p.get_id(), is_move: is_move, name: ident, span: sp}
@@ -696,23 +689,6 @@ impl parser {
         }
     }
 
-    fn maybe_parse_fixed_vstore() -> Option<Option<uint>> {
-        if self.token == token::BINOP(token::SLASH) {
-            self.bump();
-            match copy self.token {
-              token::UNDERSCORE => {
-                self.bump(); Some(None)
-              }
-              token::LIT_INT_UNSUFFIXED(i) if i >= 0i64 => {
-                self.bump(); Some(Some(i as uint))
-              }
-              _ => None
-            }
-        } else {
-            None
-        }
-    }
-
     fn maybe_parse_fixed_vstore_with_star() -> Option<Option<uint>> {
         if self.eat(token::BINOP(token::STAR)) {
             match copy self.token {
@@ -729,7 +705,7 @@ impl parser {
         }
     }
 
-    fn lit_from_token(tok: token::token) -> lit_ {
+    fn lit_from_token(tok: token::Token) -> lit_ {
         match tok {
           token::LIT_INT(i, it) => lit_int(i, it),
           token::LIT_UINT(u, ut) => lit_uint(u, ut),
@@ -761,8 +737,8 @@ impl parser {
     }
 
     fn parse_path_without_tps_(
-        parse_ident: fn(parser) -> ident,
-        parse_last_ident: fn(parser) -> ident) -> @path {
+        parse_ident: fn(Parser) -> ident,
+        parse_last_ident: fn(Parser) -> ident) -> @path {
 
         maybe_whole!(self, nt_path);
         let lo = self.span.lo;
@@ -843,7 +819,7 @@ impl parser {
         }
     }
 
-    fn parse_field(sep: token::token) -> field {
+    fn parse_field(sep: token::Token) -> field {
         let lo = self.span.lo;
         let m = self.parse_mutability();
         let i = self.parse_ident();
@@ -1088,20 +1064,8 @@ impl parser {
             ex = expr_lit(@lit);
         }
 
-        // Vstore is legal following expr_lit(lit_str(...)) and expr_vec(...)
-        // only.
-        match ex {
-          expr_lit(@{node: lit_str(_), span: _}) |
-          expr_vec(_, _)  => match self.maybe_parse_fixed_vstore() {
-            None => (),
-            Some(v) => {
-                hi = self.span.hi;
-                ex = expr_vstore(self.mk_expr(lo, hi, ex),
-                                 expr_vstore_fixed(v));
-            }
-          },
-          _ => ()
-        }
+        let (hi, ex) =
+            self.try_convert_expr_to_obsolete_fixed_length_vstore(lo, hi, ex);
 
         return self.mk_pexpr(lo, hi, ex);
     }
@@ -1221,7 +1185,7 @@ impl parser {
         return e;
     }
 
-    fn parse_sep_and_zerok() -> (Option<token::token>, bool) {
+    fn parse_sep_and_zerok() -> (Option<token::Token>, bool) {
         if self.token == token::BINOP(token::STAR)
             || self.token == token::BINOP(token::PLUS) {
             let zerok = self.token == token::BINOP(token::STAR);
@@ -1244,7 +1208,7 @@ impl parser {
     fn parse_token_tree() -> token_tree {
         maybe_whole!(deref self, nt_tt);
 
-        fn parse_tt_tok(p: parser, delim_ok: bool) -> token_tree {
+        fn parse_tt_tok(p: Parser, delim_ok: bool) -> token_tree {
             match p.token {
               token::RPAREN | token::RBRACE | token::RBRACKET
               if !delim_ok => {
@@ -1311,8 +1275,8 @@ impl parser {
     // This goofy function is necessary to correctly match parens in matchers.
     // Otherwise, `$( ( )` would be a valid matcher, and `$( () )` would be
     // invalid. It's similar to common::parse_seq.
-    fn parse_matcher_subseq(name_idx: @mut uint, bra: token::token,
-                            ket: token::token) -> ~[matcher] {
+    fn parse_matcher_subseq(name_idx: @mut uint, bra: token::Token,
+                            ket: token::Token) -> ~[matcher] {
         let mut ret_val = ~[];
         let mut lparens = 0u;
 
@@ -2159,7 +2123,7 @@ impl parser {
     fn parse_stmt(+first_item_attrs: ~[attribute]) -> @stmt {
         maybe_whole!(self, nt_stmt);
 
-        fn check_expected_item(p: parser, current_attrs: ~[attribute]) {
+        fn check_expected_item(p: Parser, current_attrs: ~[attribute]) {
             // If we have attributes then we should have an item
             if vec::is_not_empty(current_attrs) {
                 p.fatal(~"expected item");
@@ -2185,7 +2149,7 @@ impl parser {
 
             let item_attrs = vec::append(first_item_attrs, item_attrs);
 
-            match self.parse_item_or_view_item(item_attrs, true) {
+            match self.parse_item_or_view_item(item_attrs, true, false) {
               iovi_item(i) => {
                 let mut hi = i.span.hi;
                 let decl = @spanned(lo, hi, decl_item(i));
@@ -2195,6 +2159,9 @@ impl parser {
                 self.span_fatal(vi.span, ~"view items must be declared at \
                                            the top of the block");
               }
+              iovi_foreign_item(_) => {
+                  self.fatal(~"foreign items are not allowed here");
+              }
               iovi_none() => { /* fallthrough */ }
             }
 
@@ -2222,7 +2189,7 @@ impl parser {
 
         maybe_whole!(pair_empty self, nt_block);
 
-        fn maybe_parse_inner_attrs_and_next(p: parser, parse_attrs: bool) ->
+        fn maybe_parse_inner_attrs_and_next(p: Parser, parse_attrs: bool) ->
             {inner: ~[attribute], next: ~[attribute]} {
             if parse_attrs {
                 p.parse_inner_attrs_and_next()
@@ -2260,7 +2227,7 @@ impl parser {
         let mut stmts = ~[];
         let mut expr = None;
 
-        let {attrs_remaining, view_items, items: items} =
+        let {attrs_remaining, view_items, items: items, _} =
             self.parse_items_and_view_items(first_item_attrs,
                                             IMPORTS_AND_ITEMS_ALLOWED);
 
@@ -2327,19 +2294,20 @@ impl parser {
         return spanned(lo, hi, bloc);
     }
 
+    fn mk_ty_path(i: ident) -> @Ty {
+        @{id: self.get_id(), node: ty_path(
+            ident_to_path(copy self.last_span, i),
+            self.get_id()), span: self.last_span}
+    }
+
     fn parse_optional_ty_param_bounds() -> @~[ty_param_bound] {
         let mut bounds = ~[];
         if self.eat(token::COLON) {
             while is_ident(self.token) {
                 if is_ident(self.token) {
-                    // XXX: temporary until kinds become traits
                     let maybe_bound = match self.token {
                       token::IDENT(copy sid, _) => {
                         match *self.id_to_str(sid) {
-                          ~"Send" => Some(bound_send),
-                          ~"Copy" => Some(bound_copy),
-                          ~"Const" => Some(bound_const),
-                          ~"Owned" => Some(bound_owned),
 
                           ~"send"
                           | ~"copy"
@@ -2349,7 +2317,7 @@ impl parser {
                                           ObsoleteLowerCaseKindBounds);
                             // Bogus value, but doesn't matter, since
                             // is an error
-                            Some(bound_send)
+                            Some(ty_param_bound(self.mk_ty_path(sid)))
                           }
 
                           _ => None
@@ -2364,11 +2332,11 @@ impl parser {
                             bounds.push(bound);
                         }
                         None => {
-                            bounds.push(bound_trait(self.parse_ty(false)));
+                            bounds.push(ty_param_bound(self.parse_ty(false)));
                         }
                     }
                 } else {
-                    bounds.push(bound_trait(self.parse_ty(false)));
+                    bounds.push(ty_param_bound(self.parse_ty(false)));
                 }
             }
         }
@@ -2387,7 +2355,7 @@ impl parser {
         } else { ~[] }
     }
 
-    fn parse_fn_decl(parse_arg_fn: fn(parser) -> arg_or_capture_item)
+    fn parse_fn_decl(parse_arg_fn: fn(Parser) -> arg_or_capture_item)
         -> (fn_decl, capture_clause) {
 
         let args_or_capture_items: ~[arg_or_capture_item] =
@@ -2414,18 +2382,18 @@ impl parser {
 
     fn expect_self_ident() {
         if !self.is_self_ident() {
-            self.fatal(#fmt("expected `self` but found `%s`",
+            self.fatal(fmt!("expected `self` but found `%s`",
                             token_to_str(self.reader, self.token)));
         }
         self.bump();
     }
 
     fn parse_fn_decl_with_self(parse_arg_fn:
-                                    fn(parser) -> arg_or_capture_item)
+                                    fn(Parser) -> arg_or_capture_item)
                             -> (self_ty, fn_decl, capture_clause) {
 
         fn maybe_parse_self_ty(cnstr: fn(+v: mutability) -> ast::self_ty_,
-                               p: parser) -> ast::self_ty_ {
+                               p: Parser) -> ast::self_ty_ {
             // We need to make sure it isn't a mode or a type
             if p.token_is_keyword(~"self", p.look_ahead(1)) ||
                 ((p.token_is_keyword(~"const", p.look_ahead(1)) ||
@@ -2605,7 +2573,7 @@ impl parser {
     // Parses four variants (with the region/type params always optional):
     //    impl<T> ~[T] : to_str { ... }
     fn parse_item_impl() -> item_info {
-        fn wrap_path(p: parser, pt: @path) -> @ty {
+        fn wrap_path(p: Parser, pt: @path) -> @Ty {
             @{id: p.get_id(), node: ty_path(pt, p.get_id()), span: pt.span}
         }
 
@@ -2665,7 +2633,7 @@ impl parser {
           ref_id: self.get_id(), impl_id: self.get_id()}
     }
 
-    fn parse_trait_ref_list(ket: token::token) -> ~[@trait_ref] {
+    fn parse_trait_ref_list(ket: token::Token) -> ~[@trait_ref] {
         self.parse_seq_to_before_end(
             ket, seq_sep_trailing_disallowed(token::COMMA),
             |p| p.parse_trait_ref())
@@ -2683,34 +2651,17 @@ impl parser {
 
         let mut fields: ~[@struct_field];
         let mut methods: ~[@method] = ~[];
-        let mut the_ctor: Option<(fn_decl, ~[attribute], blk, codemap::span)>
-            = None;
         let mut the_dtor: Option<(blk, ~[attribute], codemap::span)> = None;
-        let ctor_id = self.get_id();
 
         if self.eat(token::LBRACE) {
             // It's a record-like struct.
             fields = ~[];
             while self.token != token::RBRACE {
                 match self.parse_class_item() {
-                  ctor_decl(a_fn_decl, attrs, blk, s) => {
-                      match the_ctor {
-                        Some((_, _, _, s_first)) => {
-                          self.span_note(s, #fmt("Duplicate constructor \
-                                     declaration for class %s",
-                                     *self.interner.get(class_name)));
-                           self.span_fatal(copy s_first, ~"First constructor \
-                                                          declared here");
-                        }
-                        None    => {
-                          the_ctor = Some((a_fn_decl, attrs, blk, s));
-                        }
-                      }
-                  }
                   dtor_decl(blk, attrs, s) => {
                       match the_dtor {
                         Some((_, _, s_first)) => {
-                          self.span_note(s, #fmt("Duplicate destructor \
+                          self.span_note(s, fmt!("Duplicate destructor \
                                      declaration for class %s",
                                      *self.interner.get(class_name)));
                           self.span_fatal(copy s_first, ~"First destructor \
@@ -2764,39 +2715,17 @@ impl parser {
                     self_id: self.get_id(),
                     body: d_body},
              span: d_s}};
-        match the_ctor {
-          Some((ct_d, ct_attrs, ct_b, ct_s)) => {
-            (class_name,
-             item_class(@{
-                traits: traits,
-                fields: move fields,
-                methods: move methods,
-                ctor: Some({
-                 node: {id: ctor_id,
-                        attrs: ct_attrs,
-                        self_id: self.get_id(),
-                        dec: ct_d,
-                        body: ct_b},
-                 span: ct_s}),
-                dtor: actual_dtor
-             }, ty_params),
-             None)
-          }
-          None => {
-            (class_name,
-             item_class(@{
-                    traits: traits,
-                    fields: move fields,
-                    methods: move methods,
-                    ctor: None,
-                    dtor: actual_dtor
-             }, ty_params),
-             None)
-          }
-        }
+        (class_name,
+         item_class(@{
+             traits: traits,
+             fields: move fields,
+             methods: move methods,
+             dtor: actual_dtor
+         }, ty_params),
+         None)
     }
 
-    fn token_is_pound_or_doc_comment(++tok: token::token) -> bool {
+    fn token_is_pound_or_doc_comment(++tok: token::Token) -> bool {
         match tok {
             token::POUND | token::DOC_COMMENT(_) => true,
             _ => false
@@ -2881,10 +2810,10 @@ impl parser {
         self.eat_keyword(~"static")
     }
 
-    fn parse_mod_items(term: token::token,
+    fn parse_mod_items(term: token::Token,
                        +first_item_attrs: ~[attribute]) -> _mod {
         // Shouldn't be any view items since we've already parsed an item attr
-        let {attrs_remaining, view_items, items: starting_items} =
+        let {attrs_remaining, view_items, items: starting_items, _} =
             self.parse_items_and_view_items(first_item_attrs,
                                             VIEW_ITEMS_AND_ITEMS_ALLOWED);
         let mut items: ~[@item] = move starting_items;
@@ -2898,7 +2827,7 @@ impl parser {
             }
             debug!("parse_mod_items: parse_item_or_view_item(attrs=%?)",
                    attrs);
-            match self.parse_item_or_view_item(attrs, true) {
+            match self.parse_item_or_view_item(attrs, true, false) {
               iovi_item(item) => items.push(item),
               iovi_view_item(view_item) => {
                 self.span_fatal(view_item.span, ~"view items must be \
@@ -2998,11 +2927,11 @@ impl parser {
                                +first_item_attrs: ~[attribute]) ->
         foreign_mod {
         // Shouldn't be any view items since we've already parsed an item attr
-        let {attrs_remaining, view_items, items: _} =
+        let {attrs_remaining, view_items, items: _, foreign_items} =
             self.parse_items_and_view_items(first_item_attrs,
-                                            VIEW_ITEMS_ALLOWED);
+                                        VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED);
 
-        let mut items: ~[@foreign_item] = ~[];
+        let mut items: ~[@foreign_item] = move foreign_items;
         let mut initial_attrs = attrs_remaining;
         while self.token != token::RBRACE {
             let attrs = vec::append(initial_attrs,
@@ -3011,7 +2940,7 @@ impl parser {
             items.push(self.parse_foreign_item(attrs));
         }
         return {sort: sort, view_items: view_items,
-             items: items};
+            items: items};
     }
 
     fn parse_item_foreign_mod(lo: uint,
@@ -3097,12 +3026,6 @@ impl parser {
         let mut methods: ~[@method] = ~[];
         while self.token != token::RBRACE {
             match self.parse_class_item() {
-                ctor_decl(*) => {
-                    self.span_fatal(copy self.span,
-                                    ~"deprecated explicit \
-                                      constructors are not allowed \
-                                      here");
-                }
                 dtor_decl(blk, attrs, s) => {
                     match the_dtor {
                         Some((_, _, s_first)) => {
@@ -3143,7 +3066,6 @@ impl parser {
             traits: ~[],
             fields: move fields,
             methods: move methods,
-            ctor: None,
             dtor: actual_dtor
         };
     }
@@ -3269,15 +3191,18 @@ impl parser {
         }
     }
 
-    fn fn_expr_lookahead(tok: token::token) -> bool {
+    fn fn_expr_lookahead(tok: token::Token) -> bool {
         match tok {
           token::LPAREN | token::AT | token::TILDE | token::BINOP(_) => true,
           _ => false
         }
     }
 
-    fn parse_item_or_view_item(+attrs: ~[attribute], items_allowed: bool)
+    fn parse_item_or_view_item(+attrs: ~[attribute], items_allowed: bool,
+                               foreign_items_allowed: bool)
                             -> item_or_view_item {
+        assert items_allowed != foreign_items_allowed;
+
         maybe_whole!(iovi self,nt_item);
         let lo = self.span.lo;
 
@@ -3295,6 +3220,9 @@ impl parser {
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
+        } else if foreign_items_allowed && self.is_keyword(~"const") {
+            let item = self.parse_item_foreign_const(visibility, attrs);
+            return iovi_foreign_item(item);
         } else if items_allowed &&
             self.is_keyword(~"fn") &&
             !self.fn_expr_lookahead(self.look_ahead(1u)) {
@@ -3309,6 +3237,10 @@ impl parser {
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
+        } else if foreign_items_allowed &&
+            (self.is_keyword(~"fn") || self.is_keyword(~"pure")) {
+                let item = self.parse_item_foreign_fn(visibility, attrs);
+                return iovi_foreign_item(item);
         } else if items_allowed && self.is_keyword(~"unsafe")
             && self.look_ahead(1u) != token::LBRACE {
             self.bump();
@@ -3395,16 +3327,24 @@ impl parser {
             return iovi_item(self.mk_item(lo, self.last_span.hi, id, item_,
                                           visibility, attrs));
         } else {
+            if visibility != inherited {
+                let mut s = ~"unmatched visibility `";
+                s += if visibility == public { ~"pub" } else { ~"priv" };
+                s += ~"`";
+                self.span_fatal(copy self.last_span, s);
+            }
             return iovi_none;
         };
     }
 
     fn parse_item(+attrs: ~[attribute]) -> Option<@ast::item> {
-        match self.parse_item_or_view_item(attrs, true) {
+        match self.parse_item_or_view_item(attrs, true, false) {
             iovi_none =>
                 None,
             iovi_view_item(_) =>
                 self.fatal(~"view items are not allowed here"),
+            iovi_foreign_item(_) =>
+                self.fatal(~"foreign items are not allowed here"),
             iovi_item(item) =>
                 Some(item)
         }
@@ -3539,28 +3479,35 @@ impl parser {
                                   mode: view_item_parse_mode)
                                -> {attrs_remaining: ~[attribute],
                                    view_items: ~[@view_item],
-                                   items: ~[@item]} {
+                                   items: ~[@item],
+                                   foreign_items: ~[@foreign_item]} {
         let mut attrs = vec::append(first_item_attrs,
                                     self.parse_outer_attributes());
 
-        let items_allowed;
-        match mode {
-            VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED =>
-                items_allowed = true,
-            VIEW_ITEMS_ALLOWED =>
-                items_allowed = false
-        }
+        let items_allowed = match mode {
+            VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => true,
+            VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED => false
+        };
 
-        let (view_items, items) = (DVec(), DVec());
+        let restricted_to_imports = match mode {
+            IMPORTS_AND_ITEMS_ALLOWED => true,
+            VIEW_ITEMS_AND_ITEMS_ALLOWED |
+            VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED => false
+        };
+
+        let foreign_items_allowed = match mode {
+            VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED => true,
+            VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => false
+        };
+
+        let (view_items, items, foreign_items) = (DVec(), DVec(), DVec());
         loop {
-            match self.parse_item_or_view_item(attrs, items_allowed) {
+            match self.parse_item_or_view_item(attrs, items_allowed,
+                                               foreign_items_allowed) {
                 iovi_none =>
                     break,
                 iovi_view_item(view_item) => {
-                    match mode {
-                        VIEW_ITEMS_AND_ITEMS_ALLOWED |
-                        VIEW_ITEMS_ALLOWED => {}
-                        IMPORTS_AND_ITEMS_ALLOWED =>
+                    if restricted_to_imports {
                             match view_item.node {
                                 view_item_import(_) => {}
                                 view_item_export(_) | view_item_use(*) =>
@@ -3575,13 +3522,18 @@ impl parser {
                     assert items_allowed;
                     items.push(item)
                 }
+                iovi_foreign_item(foreign_item) => {
+                    assert foreign_items_allowed;
+                    foreign_items.push(foreign_item);
+                }
             }
             attrs = self.parse_outer_attributes();
         }
 
         {attrs_remaining: attrs,
          view_items: dvec::unwrap(move view_items),
-         items: dvec::unwrap(move items)}
+         items: dvec::unwrap(move items),
+         foreign_items: dvec::unwrap(move foreign_items)}
     }
 
     // Parses a source module as a crate
@@ -3655,7 +3607,7 @@ impl parser {
         return self.fatal(~"expected crate directive");
     }
 
-    fn parse_crate_directives(term: token::token,
+    fn parse_crate_directives(term: token::Token,
                               first_outer_attr: ~[attribute]) ->
         ~[@crate_directive] {
 
diff --git a/src/libsyntax/parse/prec.rs b/src/libsyntax/parse/prec.rs
index 668301db620..3fd905cb8ec 100644
--- a/src/libsyntax/parse/prec.rs
+++ b/src/libsyntax/parse/prec.rs
@@ -3,7 +3,7 @@ export unop_prec;
 export token_to_binop;
 
 use token::*;
-use token::token;
+use token::Token;
 use ast::*;
 
 /// Unary operators have higher precedence than binary
@@ -19,7 +19,7 @@ const as_prec: uint = 11u;
  * Maps a token to a record specifying the corresponding binary
  * operator and its precedence
  */
-fn token_to_binop(tok: token) -> Option<ast::binop> {
+fn token_to_binop(tok: Token) -> Option<ast::binop> {
   match tok {
       BINOP(STAR)    => Some(mul),
       BINOP(SLASH)   => Some(div),
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 99b789cf63f..5151fd1bac8 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -1,18 +1,9 @@
 use util::interner;
-use util::interner::interner;
+use util::interner::Interner;
 use std::map::HashMap;
-use std::serialization::{Serializer,
-                            Deserializer,
-                            serialize_uint,
-                            deserialize_uint,
-                            serialize_i64,
-                            deserialize_i64,
-                            serialize_u64,
-                            deserialize_u64,
-                            serialize_bool,
-                            deserialize_bool};
 
 #[auto_serialize]
+#[auto_deserialize]
 enum binop {
     PLUS,
     MINUS,
@@ -27,7 +18,8 @@ enum binop {
 }
 
 #[auto_serialize]
-enum token {
+#[auto_deserialize]
+enum Token {
     /* Expression-operator symbols. */
     EQ,
     LT,
@@ -84,6 +76,7 @@ enum token {
 }
 
 #[auto_serialize]
+#[auto_deserialize]
 /// For interpolation during macro expansion.
 enum nonterminal {
     nt_item(@ast::item),
@@ -91,7 +84,7 @@ enum nonterminal {
     nt_stmt(@ast::stmt),
     nt_pat( @ast::pat),
     nt_expr(@ast::expr),
-    nt_ty(  @ast::ty),
+    nt_ty(  @ast::Ty),
     nt_ident(ast::ident, bool),
     nt_path(@ast::path),
     nt_tt(  @ast::token_tree), //needs @ed to break a circularity
@@ -113,7 +106,7 @@ fn binop_to_str(o: binop) -> ~str {
     }
 }
 
-fn to_str(in: @ident_interner, t: token) -> ~str {
+fn to_str(in: @ident_interner, t: Token) -> ~str {
     match t {
       EQ => ~"=",
       LT => ~"<",
@@ -199,7 +192,7 @@ fn to_str(in: @ident_interner, t: token) -> ~str {
     }
 }
 
-pure fn can_begin_expr(t: token) -> bool {
+pure fn can_begin_expr(t: Token) -> bool {
     match t {
       LPAREN => true,
       LBRACE => true,
@@ -230,7 +223,7 @@ pure fn can_begin_expr(t: token) -> bool {
 }
 
 /// what's the opposite delimiter?
-fn flip_delimiter(t: token::token) -> token::token {
+fn flip_delimiter(t: token::Token) -> token::Token {
     match t {
       token::LPAREN => token::RPAREN,
       token::LBRACE => token::RBRACE,
@@ -244,7 +237,7 @@ fn flip_delimiter(t: token::token) -> token::token {
 
 
 
-fn is_lit(t: token) -> bool {
+fn is_lit(t: Token) -> bool {
     match t {
       LIT_INT(_, _) => true,
       LIT_UINT(_, _) => true,
@@ -255,22 +248,22 @@ fn is_lit(t: token) -> bool {
     }
 }
 
-pure fn is_ident(t: token) -> bool {
+pure fn is_ident(t: Token) -> bool {
     match t { IDENT(_, _) => true, _ => false }
 }
 
-pure fn is_ident_or_path(t: token) -> bool {
+pure fn is_ident_or_path(t: Token) -> bool {
     match t {
       IDENT(_, _) | INTERPOLATED(nt_path(*)) => true,
       _ => false
     }
 }
 
-pure fn is_plain_ident(t: token) -> bool {
+pure fn is_plain_ident(t: Token) -> bool {
     match t { IDENT(_, false) => true, _ => false }
 }
 
-pure fn is_bar(t: token) -> bool {
+pure fn is_bar(t: Token) -> bool {
     match t { BINOP(OR) | OROR => true, _ => false }
 }
 
@@ -321,7 +314,7 @@ mod special_idents {
 }
 
 struct ident_interner {
-    priv interner: util::interner::interner<@~str>,
+    priv interner: util::interner::Interner<@~str>,
 }
 
 impl ident_interner {
@@ -350,28 +343,33 @@ macro_rules! interner_key (
 )
 
 fn mk_ident_interner() -> @ident_interner {
-    /* the indices here must correspond to the numbers in special_idents */
-    let init_vec = ~[@~"_", @~"anon", @~"drop", @~"", @~"unary", @~"!",
-                     @~"[]", @~"unary-", @~"__extensions__", @~"self",
-                     @~"item", @~"block", @~"stmt", @~"pat", @~"expr",
-                     @~"ty", @~"ident", @~"path", @~"tt", @~"matchers",
-                     @~"str", @~"TyVisitor", @~"arg", @~"descrim",
-                     @~"__rust_abi", @~"__rust_stack_shim", @~"TyDesc",
-                     @~"dtor", @~"main", @~"<opaque>", @~"blk", @~"static",
-                     @~"intrinsic", @~"__foreign_mod__"];
-
-    let rv = @ident_interner {
-        interner: interner::mk_prefill::<@~str>(init_vec)
-    };
-
-    /* having multiple interners will just confuse the serializer */
     unsafe {
-        assert task::local_data::local_data_get(interner_key!()).is_none()
-    };
-    unsafe {
-        task::local_data::local_data_set(interner_key!(), @rv)
-    };
-    rv
+        match task::local_data::local_data_get(interner_key!()) {
+            Some(interner) => *interner,
+            None => {
+                // the indices here must correspond to the numbers in
+                // special_idents.
+                let init_vec = ~[
+                    @~"_", @~"anon", @~"drop", @~"", @~"unary", @~"!",
+                    @~"[]", @~"unary-", @~"__extensions__", @~"self",
+                    @~"item", @~"block", @~"stmt", @~"pat", @~"expr",
+                    @~"ty", @~"ident", @~"path", @~"tt", @~"matchers",
+                    @~"str", @~"TyVisitor", @~"arg", @~"descrim",
+                    @~"__rust_abi", @~"__rust_stack_shim", @~"TyDesc",
+                    @~"dtor", @~"main", @~"<opaque>", @~"blk", @~"static",
+                    @~"intrinsic", @~"__foreign_mod__"
+                ];
+
+                let rv = @ident_interner {
+                    interner: interner::mk_prefill(init_vec)
+                };
+
+                task::local_data::local_data_set(interner_key!(), @rv);
+
+                rv
+            }
+        }
+    }
 }
 
 /* for when we don't care about the contents; doesn't interact with TLD or
@@ -459,8 +457,8 @@ impl binop : cmp::Eq {
     pure fn ne(other: &binop) -> bool { !self.eq(other) }
 }
 
-impl token : cmp::Eq {
-    pure fn eq(other: &token) -> bool {
+impl Token : cmp::Eq {
+    pure fn eq(other: &Token) -> bool {
         match self {
             EQ => {
                 match (*other) {
@@ -722,7 +720,7 @@ impl token : cmp::Eq {
             }
         }
     }
-    pure fn ne(other: &token) -> bool { !self.eq(other) }
+    pure fn ne(other: &Token) -> bool { !self.eq(other) }
 }
 
 // Local Variables:
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index bff356e5cb7..33915c8c0c9 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1,5 +1,5 @@
 use parse::{comments, lexer, token};
-use codemap::codemap;
+use codemap::CodeMap;
 use pp::{break_offset, word, printer, space, zerobreak, hardbreak, breaks};
 use pp::{consistent, inconsistent, eof};
 use ast::{required, provided};
@@ -24,7 +24,7 @@ fn no_ann() -> pp_ann {
 
 type ps =
     @{s: pp::printer,
-      cm: Option<codemap>,
+      cm: Option<CodeMap>,
       intr: @token::ident_interner,
       comments: Option<~[comments::cmnt]>,
       literals: Option<~[comments::lit]>,
@@ -45,7 +45,7 @@ fn end(s: ps) {
 
 fn rust_printer(writer: io::Writer, intr: @ident_interner) -> ps {
     return @{s: pp::mk_printer(writer, default_columns),
-             cm: None::<codemap>,
+             cm: None::<CodeMap>,
              intr: intr,
              comments: None::<~[comments::cmnt]>,
              literals: None::<~[comments::lit]>,
@@ -63,7 +63,7 @@ const default_columns: uint = 78u;
 // Requires you to pass an input filename and reader so that
 // it can scan the input text for comments and literals to
 // copy forward.
-fn print_crate(cm: codemap, intr: @ident_interner,
+fn print_crate(cm: CodeMap, intr: @ident_interner,
                span_diagnostic: diagnostic::span_handler,
                crate: @ast::crate, filename: ~str, in: io::Reader,
                out: io::Writer, ann: pp_ann, is_expanded: bool) {
@@ -91,7 +91,7 @@ fn print_crate_(s: ps, &&crate: @ast::crate) {
     eof(s.s);
 }
 
-fn ty_to_str(ty: @ast::ty, intr: @ident_interner) -> ~str {
+fn ty_to_str(ty: @ast::Ty, intr: @ident_interner) -> ~str {
     to_str(ty, print_type, intr)
 }
 
@@ -348,11 +348,11 @@ fn print_region(s: ps, region: @ast::region, sep: ~str) {
     word(s.s, sep);
 }
 
-fn print_type(s: ps, &&ty: @ast::ty) {
+fn print_type(s: ps, &&ty: @ast::Ty) {
     print_type_ex(s, ty, false);
 }
 
-fn print_type_ex(s: ps, &&ty: @ast::ty, print_colons: bool) {
+fn print_type_ex(s: ps, &&ty: @ast::Ty, print_colons: bool) {
     maybe_print_comment(s, ty.span.lo);
     ibox(s, 0u);
     match ty.node {
@@ -399,9 +399,21 @@ fn print_type_ex(s: ps, &&ty: @ast::ty, print_colons: bool) {
       }
       ast::ty_path(path, _) => print_path(s, path, print_colons),
       ast::ty_fixed_length(t, v) => {
-        print_type(s, t);
-        word(s.s, ~"/");
+        word(s.s, ~"[");
+        match t.node {
+          ast::ty_vec(mt) => {
+            match mt.mutbl {
+              ast::m_mutbl => word_space(s, ~"mut"),
+              ast::m_const => word_space(s, ~"const"),
+              ast::m_imm => ()
+            }
+            print_type(s, mt.ty);
+          }
+          _ => fail ~"ty_fixed_length can only contain ty_vec as type"
+        }
+        word(s.s, ~" * ");
         print_vstore(s, ast::vstore_fixed(v));
+        word(s.s, ~"]");
       }
       ast::ty_mac(_) => {
           fail ~"print_type doesn't know how to print a ty_mac";
@@ -433,6 +445,7 @@ fn print_foreign_item(s: ps, item: @ast::foreign_item) {
         print_type(s, t);
         word(s.s, ~";");
         end(s); // end the head-ibox
+        end(s); // end the outer cbox
       }
     }
 }
@@ -443,7 +456,6 @@ fn print_item(s: ps, &&item: @ast::item) {
     print_outer_attributes(s, item.attrs);
     let ann_node = node_item(s, item);
     s.ann.pre(ann_node);
-    print_visibility(s, item.vis);
     match item.node {
       ast::item_const(ty, expr) => {
         head(s, visibility_qualified(item.vis, ~"const"));
@@ -479,10 +491,10 @@ fn print_item(s: ps, &&item: @ast::item) {
             ast::named => {
                 word_nbsp(s, ~"mod");
                 print_ident(s, item.ident);
+                nbsp(s);
             }
             ast::anonymous => {}
         }
-        nbsp(s);
         bopen(s);
         print_foreign_mod(s, nmod, item.attrs);
         bclose(s, item.span);
@@ -490,7 +502,7 @@ fn print_item(s: ps, &&item: @ast::item) {
       ast::item_ty(ty, params) => {
         ibox(s, indent_unit);
         ibox(s, 0u);
-        word_nbsp(s, ~"type");
+        word_nbsp(s, visibility_qualified(item.vis, ~"type"));
         print_ident(s, item.ident);
         print_type_params(s, params);
         end(s); // end the inner ibox
@@ -502,15 +514,16 @@ fn print_item(s: ps, &&item: @ast::item) {
         end(s); // end the outer ibox
       }
       ast::item_enum(enum_definition, params) => {
-        print_enum_def(s, enum_definition, params, item.ident, item.span);
+        print_enum_def(s, enum_definition, params, item.ident,
+                       item.span, item.vis);
       }
       ast::item_class(struct_def, tps) => {
-          head(s, ~"struct");
+          head(s, visibility_qualified(item.vis, ~"struct"));
           print_struct(s, struct_def, tps, item.ident, item.span);
       }
 
       ast::item_impl(tps, opt_trait, ty, methods) => {
-        head(s, ~"impl");
+        head(s, visibility_qualified(item.vis, ~"impl"));
         if tps.is_not_empty() {
             print_type_params(s, tps);
             space(s.s);
@@ -533,7 +546,7 @@ fn print_item(s: ps, &&item: @ast::item) {
         bclose(s, item.span);
       }
       ast::item_trait(tps, traits, methods) => {
-        head(s, ~"trait");
+        head(s, visibility_qualified(item.vis, ~"trait"));
         print_ident(s, item.ident);
         print_type_params(s, tps);
         if vec::len(traits) != 0u {
@@ -549,6 +562,7 @@ fn print_item(s: ps, &&item: @ast::item) {
         bclose(s, item.span);
       }
       ast::item_mac({node: ast::mac_invoc_tt(pth, tts), _}) => {
+        print_visibility(s, item.vis);
         print_path(s, pth, false);
         word(s.s, ~"! ");
         print_ident(s, item.ident);
@@ -569,7 +583,7 @@ fn print_item(s: ps, &&item: @ast::item) {
 
 fn print_enum_def(s: ps, enum_definition: ast::enum_def,
                   params: ~[ast::ty_param], ident: ast::ident,
-                  span: ast::span) {
+                  span: ast::span, visibility: ast::visibility) {
     let mut newtype =
         vec::len(enum_definition.variants) == 1u &&
         ident == enum_definition.variants[0].node.name;
@@ -581,9 +595,9 @@ fn print_enum_def(s: ps, enum_definition: ast::enum_def,
     }
     if newtype {
         ibox(s, indent_unit);
-        word_space(s, ~"enum");
+        word_space(s, visibility_qualified(visibility, ~"enum"));
     } else {
-        head(s, ~"enum");
+        head(s, visibility_qualified(visibility, ~"enum"));
     }
 
     print_ident(s, ident);
@@ -653,18 +667,6 @@ fn print_struct(s: ps, struct_def: @ast::struct_def, tps: ~[ast::ty_param],
     }
     bopen(s);
     hardbreak_if_not_bol(s);
-    do struct_def.ctor.iter |ctor| {
-      maybe_print_comment(s, ctor.span.lo);
-      print_outer_attributes(s, ctor.node.attrs);
-      // Doesn't call head because there shouldn't be a space after new.
-      cbox(s, indent_unit);
-      ibox(s, 4);
-      word(s.s, ~"new(");
-      print_fn_args(s, ctor.node.dec, ~[], None);
-      word(s.s, ~")");
-      space(s.s);
-      print_block(s, ctor.node.body);
-    }
     do struct_def.dtor.iter |dtor| {
       hardbreak_if_not_bol(s);
       maybe_print_comment(s, dtor.span.lo);
@@ -888,7 +890,7 @@ fn print_possibly_embedded_block_(s: ps, blk: ast::blk, embedded: embed_type,
                                   indented: uint, attrs: ~[ast::attribute],
                                   close_box: bool) {
     match blk.node.rules {
-      ast::unsafe_blk => word(s.s, ~"unsafe"),
+      ast::unsafe_blk => word_space(s, ~"unsafe"),
       ast::default_blk => ()
     }
     maybe_print_comment(s, blk.span.lo);
@@ -1178,7 +1180,10 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
       ast::expr_loop(blk, opt_ident) => {
         head(s, ~"loop");
         space(s.s);
-        opt_ident.iter(|ident| {print_ident(s, *ident); space(s.s)});
+        opt_ident.iter(|ident| {
+            print_ident(s, *ident);
+            word_space(s, ~":");
+        });
         print_block(s, blk);
       }
       ast::expr_match(expr, arms) => {
@@ -1702,17 +1707,11 @@ fn print_arg_mode(s: ps, m: ast::mode) {
 }
 
 fn print_bounds(s: ps, bounds: @~[ast::ty_param_bound]) {
-    if vec::len(*bounds) > 0u {
+    if bounds.is_not_empty() {
         word(s.s, ~":");
         for vec::each(*bounds) |bound| {
             nbsp(s);
-            match *bound {
-              ast::bound_copy => word(s.s, ~"Copy"),
-              ast::bound_send => word(s.s, ~"Send"),
-              ast::bound_const => word(s.s, ~"Const"),
-              ast::bound_owned => word(s.s, ~"Owned"),
-              ast::bound_trait(t) => print_type(s, t)
-            }
+            print_type(s, **bound);
         }
     }
 }
diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc
index 38abf5f445c..7c73deed1a9 100644
--- a/src/libsyntax/syntax.rc
+++ b/src/libsyntax/syntax.rc
@@ -1,5 +1,5 @@
 #[link(name = "syntax",
-       vers = "0.4",
+       vers = "0.5",
        uuid = "9311401b-d6ea-4cd9-a1d9-61f89499c645")];
 
 
@@ -16,8 +16,8 @@
 #[allow(deprecated_mode)];
 #[allow(deprecated_pattern)];
 
-extern mod core(vers = "0.4");
-extern mod std(vers = "0.4");
+extern mod core(vers = "0.5");
+extern mod std(vers = "0.5");
 
 use core::*;
 
@@ -131,8 +131,6 @@ mod ext {
     #[legacy_exports]
     mod auto_serialize;
     #[legacy_exports]
-    mod auto_serialize2;
-    #[legacy_exports]
     mod source_util;
 
     mod pipes {
diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs
index 021c25e3dd7..f564589cbe0 100644
--- a/src/libsyntax/util/interner.rs
+++ b/src/libsyntax/util/interner.rs
@@ -12,14 +12,14 @@ type hash_interner<T: Const> =
     {map: HashMap<T, uint>,
      vect: DVec<T>};
 
-fn mk<T:Eq IterBytes Hash Const Copy>() -> interner<T> {
+fn mk<T:Eq IterBytes Hash Const Copy>() -> Interner<T> {
     let m = map::HashMap::<T, uint>();
     let hi: hash_interner<T> =
         {map: m, vect: DVec()};
-    move (hi as interner::<T>)
+    move ((move hi) as Interner::<T>)
 }
 
-fn mk_prefill<T:Eq IterBytes Hash Const Copy>(init: ~[T]) -> interner<T> {
+fn mk_prefill<T:Eq IterBytes Hash Const Copy>(init: ~[T]) -> Interner<T> {
     let rv = mk();
     for init.each() |v| { rv.intern(*v); }
     return rv;
@@ -27,14 +27,14 @@ fn mk_prefill<T:Eq IterBytes Hash Const Copy>(init: ~[T]) -> interner<T> {
 
 
 /* when traits can extend traits, we should extend index<uint,T> to get [] */
-trait interner<T:Eq IterBytes Hash Const Copy> {
+trait Interner<T:Eq IterBytes Hash Const Copy> {
     fn intern(T) -> uint;
     fn gensym(T) -> uint;
     pure fn get(uint) -> T;
     fn len() -> uint;
 }
 
-impl <T:Eq IterBytes Hash Const Copy> hash_interner<T>: interner<T> {
+impl <T:Eq IterBytes Hash Const Copy> hash_interner<T>: Interner<T> {
     fn intern(val: T) -> uint {
         match self.map.find(val) {
           Some(idx) => return idx,
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index e6fd65eb458..b45af2d4ae8 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -17,8 +17,6 @@ enum fn_kind {
     fk_method(ident, ~[ty_param], @method),
     fk_anon(proto, capture_clause),  //< an anonymous function like fn@(...)
     fk_fn_block(capture_clause),     //< a block {||...}
-    fk_ctor(ident, ~[attribute], ~[ty_param], node_id /* self id */,
-            def_id /* parent class id */), // class constructor
     fk_dtor(~[ty_param], ~[attribute], node_id /* self id */,
             def_id /* parent class id */) // class destructor
 
@@ -26,8 +24,9 @@ enum fn_kind {
 
 fn name_of_fn(fk: fn_kind) -> ident {
     match fk {
-      fk_item_fn(name, _, _) | fk_method(name, _, _)
-          | fk_ctor(name, _, _, _, _) =>  /* FIXME (#2543) */ copy name,
+      fk_item_fn(name, _, _) | fk_method(name, _, _) => {
+          /* FIXME (#2543) */ copy name
+      }
       fk_anon(*) | fk_fn_block(*) => parse::token::special_idents::anon,
       fk_dtor(*)                  => parse::token::special_idents::dtor
     }
@@ -35,11 +34,11 @@ fn name_of_fn(fk: fn_kind) -> ident {
 
 fn tps_of_fn(fk: fn_kind) -> ~[ty_param] {
     match fk {
-      fk_item_fn(_, tps, _) | fk_method(_, tps, _)
-          | fk_ctor(_, _, tps, _, _) | fk_dtor(tps, _, _, _) => {
-          /* FIXME (#2543) */ copy tps
-      }
-      fk_anon(*) | fk_fn_block(*) => ~[]
+        fk_item_fn(_, tps, _) | fk_method(_, tps, _) |
+        fk_dtor(tps, _, _, _) => {
+            /* FIXME (#2543) */ copy tps
+        }
+        fk_anon(*) | fk_fn_block(*) => ~[]
     }
 }
 
@@ -56,7 +55,7 @@ type visitor<E> =
       visit_decl: fn@(@decl, E, vt<E>),
       visit_expr: fn@(@expr, E, vt<E>),
       visit_expr_post: fn@(@expr, E, vt<E>),
-      visit_ty: fn@(@ty, E, vt<E>),
+      visit_ty: fn@(@Ty, E, vt<E>),
       visit_ty_params: fn@(~[ty_param], E, vt<E>),
       visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>),
       visit_ty_method: fn@(ty_method, E, vt<E>),
@@ -183,12 +182,14 @@ fn visit_enum_def<E>(enum_definition: ast::enum_def, tps: ~[ast::ty_param],
                 visit_enum_def(enum_definition, tps, e, v);
             }
         }
+        // Visit the disr expr if it exists
+        vr.node.disr_expr.iter(|ex| v.visit_expr(*ex, e, v));
     }
 }
 
-fn skip_ty<E>(_t: @ty, _e: E, _v: vt<E>) {}
+fn skip_ty<E>(_t: @Ty, _e: E, _v: vt<E>) {}
 
-fn visit_ty<E>(t: @ty, e: E, v: vt<E>) {
+fn visit_ty<E>(t: @Ty, e: E, v: vt<E>) {
     match t.node {
       ty_box(mt) | ty_uniq(mt) |
       ty_vec(mt) | ty_ptr(mt) | ty_rptr(_, mt) => {
@@ -263,10 +264,7 @@ fn visit_foreign_item<E>(ni: @foreign_item, e: E, v: vt<E>) {
 
 fn visit_ty_param_bounds<E>(bounds: @~[ty_param_bound], e: E, v: vt<E>) {
     for vec::each(*bounds) |bound| {
-        match *bound {
-          bound_trait(t) => v.visit_ty(t, e, v),
-          bound_copy | bound_send | bound_const | bound_owned => ()
-        }
+        v.visit_ty(**bound, e, v)
     }
 }
 
@@ -291,17 +289,6 @@ fn visit_method_helper<E>(m: @method, e: E, v: vt<E>) {
                m.decl, m.body, m.span, m.id, e, v);
 }
 
-// Similar logic to the comment on visit_method_helper - Tim
-fn visit_class_ctor_helper<E>(ctor: class_ctor, nm: ident, tps: ~[ty_param],
-                              parent_id: def_id, e: E, v: vt<E>) {
-    v.visit_fn(fk_ctor(/* FIXME (#2543) */ copy nm,
-                       ctor.node.attrs,
-                       /* FIXME (#2543) */ copy tps,
-                       ctor.node.self_id, parent_id),
-        ctor.node.dec, ctor.node.body, ctor.span, ctor.node.id, e, v)
-
-}
-
 fn visit_class_dtor_helper<E>(dtor: class_dtor, tps: ~[ty_param],
                               parent_id: def_id, e: E, v: vt<E>) {
     v.visit_fn(fk_dtor(/* FIXME (#2543) */ copy tps, dtor.node.attrs,
@@ -330,7 +317,7 @@ fn visit_trait_method<E>(m: trait_method, e: E, v: vt<E>) {
     }
 }
 
-fn visit_struct_def<E>(sd: @struct_def, nm: ast::ident, tps: ~[ty_param],
+fn visit_struct_def<E>(sd: @struct_def, _nm: ast::ident, tps: ~[ty_param],
                        id: node_id, e: E, v: vt<E>) {
     for sd.fields.each |f| {
         v.visit_struct_field(*f, e, v);
@@ -341,9 +328,6 @@ fn visit_struct_def<E>(sd: @struct_def, nm: ast::ident, tps: ~[ty_param],
     for sd.traits.each |p| {
         visit_path(p.path, e, v);
     }
-    do option::iter(&sd.ctor) |ctor| {
-      visit_class_ctor_helper(*ctor, nm, tps, ast_util::local_def(id), e, v);
-    };
     do option::iter(&sd.dtor) |dtor| {
       visit_class_dtor_helper(*dtor, tps, ast_util::local_def(id), e, v)
     };
@@ -503,7 +487,7 @@ type simple_visitor =
       visit_decl: fn@(@decl),
       visit_expr: fn@(@expr),
       visit_expr_post: fn@(@expr),
-      visit_ty: fn@(@ty),
+      visit_ty: fn@(@Ty),
       visit_ty_params: fn@(~[ty_param]),
       visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id),
       visit_ty_method: fn@(ty_method),
@@ -512,7 +496,7 @@ type simple_visitor =
       visit_struct_field: fn@(@struct_field),
       visit_struct_method: fn@(@method)};
 
-fn simple_ignore_ty(_t: @ty) {}
+fn simple_ignore_ty(_t: @Ty) {}
 
 fn default_simple_visitor() -> simple_visitor {
     return @{visit_mod: fn@(_m: _mod, _sp: span, _id: node_id) { },
@@ -590,7 +574,7 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
     fn v_expr_post(f: fn@(@expr), ex: @expr, &&_e: (), _v: vt<()>) {
         f(ex);
     }
-    fn v_ty(f: fn@(@ty), ty: @ty, &&e: (), v: vt<()>) {
+    fn v_ty(f: fn@(@Ty), ty: @Ty, &&e: (), v: vt<()>) {
         f(ty);
         visit_ty(ty, e, v);
     }