about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTim Chevalier <chevalier@alum.wellesley.edu>2012-10-08 11:54:09 -0700
committerTim Chevalier <chevalier@alum.wellesley.edu>2012-10-08 11:58:54 -0700
commita33535e441dc5461fec0489069a1491367ad1c91 (patch)
tree6d8ea75744e7e14f5ceeace358869e0af1b67732
parent73ec5f09b072734f68b7f784f2343568bd4c3bd9 (diff)
downloadrust-a33535e441dc5461fec0489069a1491367ad1c91.tar.gz
rust-a33535e441dc5461fec0489069a1491367ad1c91.zip
Revert "Remove old auto_serialize2 code (needs snapshot)"
This reverts commit 0bd6da8a8c93143325cb45e8a074ccf7121ca168.
-rw-r--r--src/libsyntax/ast.rs170
-rw-r--r--src/libsyntax/ast_util.rs2
-rw-r--r--src/libsyntax/ext/auto_serialize2.rs991
-rw-r--r--src/libsyntax/ext/base.rs61
-rw-r--r--src/libsyntax/ext/expand.rs2
-rw-r--r--src/libsyntax/parse/token.rs6
-rw-r--r--src/libsyntax/syntax.rc3
-rw-r--r--src/rustc/middle/freevars.rs2
-rw-r--r--src/rustc/middle/ty.rs16
-rw-r--r--src/rustc/middle/typeck.rs4
10 files changed, 1255 insertions, 2 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index a27336097d0..f3e118461e6 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -20,6 +20,8 @@ impl span: Deserializable {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type spanned<T> = {node: T, span: span};
 
 
@@ -76,6 +78,8 @@ type fn_ident = Option<ident>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type path = {span: span,
              global: bool,
              idents: ~[ident],
@@ -88,6 +92,8 @@ type node_id = int;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type def_id = {crate: crate_num, node: node_id};
 
 impl def_id : cmp::Eq {
@@ -102,6 +108,8 @@ const crate_node_id: node_id = 0;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum ty_param_bound {
     bound_copy,
     bound_send,
@@ -112,10 +120,14 @@ enum ty_param_bound {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type ty_param = {ident: ident, id: node_id, bounds: @~[ty_param_bound]};
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum def {
     def_fn(def_id, purity),
     def_static_method(def_id, purity),
@@ -296,6 +308,8 @@ type meta_item = spanned<meta_item_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum meta_item_ {
     meta_word(~str),
     meta_list(~str, ~[@meta_item]),
@@ -306,6 +320,8 @@ type blk = spanned<blk_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type blk_ = {view_items: ~[@view_item],
              stmts: ~[@stmt],
              expr: Option<@expr>,
@@ -314,14 +330,20 @@ type blk_ = {view_items: ~[@view_item],
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type pat = {id: node_id, node: pat_, span: span};
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type field_pat = {ident: ident, pat: @pat};
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum binding_mode {
     bind_by_value,
     bind_by_move,
@@ -379,6 +401,8 @@ impl binding_mode : cmp::Eq {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum pat_ {
     pat_wild,
     // A pat_ident may either be a new bound variable,
@@ -403,6 +427,8 @@ enum pat_ {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum mutability { m_mutbl, m_imm, m_const, }
 
 impl mutability : to_bytes::IterBytes {
@@ -420,6 +446,8 @@ impl mutability : cmp::Eq {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum proto {
     proto_bare,    // foreign fn
     proto_uniq,    // fn~
@@ -436,6 +464,8 @@ impl proto : cmp::Eq {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum vstore {
     // FIXME (#2112): Change uint to @expr (actually only constant exprs)
     vstore_fixed(Option<uint>),   // [1,2,3,4]/_ or 4
@@ -446,6 +476,8 @@ enum vstore {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum expr_vstore {
     // FIXME (#2112): Change uint to @expr (actually only constant exprs)
     expr_vstore_fixed(Option<uint>),   // [1,2,3,4]/_ or 4
@@ -463,6 +495,8 @@ pure fn is_blockish(p: ast::proto) -> bool {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum binop {
     add,
     subtract,
@@ -493,6 +527,8 @@ impl binop : cmp::Eq {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum unop {
     box(mutability),
     uniq(mutability),
@@ -545,6 +581,8 @@ impl unop : cmp::Eq {
 // using ty::resolved_T(...).
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum inferable<T> {
     expl(T),
     infer(node_id)
@@ -585,6 +623,8 @@ impl<T:cmp::Eq> inferable<T> : cmp::Eq {
 // "resolved" mode: the real modes.
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum rmode { by_ref, by_val, by_move, by_copy }
 
 impl rmode : to_bytes::IterBytes {
@@ -608,6 +648,8 @@ type stmt = spanned<stmt_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum stmt_ {
     stmt_decl(@decl, node_id),
 
@@ -620,6 +662,8 @@ enum stmt_ {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum init_op { init_assign, init_move, }
 
 impl init_op : cmp::Eq {
@@ -644,12 +688,16 @@ impl init_op : cmp::Eq {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type initializer = {op: init_op, expr: @expr};
 
 // FIXME (pending discussion of #1697, #2178...): local should really be
 // a refinement on pat.
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type local_ =  {is_mutbl: bool, ty: @ty, pat: @pat,
                 init: Option<initializer>, id: node_id};
 
@@ -659,20 +707,28 @@ type decl = spanned<decl_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum decl_ { decl_local(~[@local]), decl_item(@item), }
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type arm = {pats: ~[@pat], guard: Option<@expr>, body: blk};
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type field_ = {mutbl: mutability, ident: ident, expr: @expr};
 
 type field = spanned<field_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum blk_check_mode { default_blk, unsafe_blk, }
 
 impl blk_check_mode : cmp::Eq {
@@ -689,20 +745,28 @@ impl blk_check_mode : cmp::Eq {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 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]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum log_level { error, debug, other }
 // 0 = error, 1 = debug, 2 = other
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum alt_mode { alt_check, alt_exhaustive, }
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum expr_ {
     expr_vstore(@expr, expr_vstore),
     expr_vec(~[@expr], mutability),
@@ -760,6 +824,8 @@ enum expr_ {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type capture_item_ = {
     id: int,
     is_move: bool,
@@ -789,6 +855,8 @@ type capture_clause = @~[capture_item];
 //
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 #[doc="For macro invocations; parsing is delegated to the macro"]
 enum token_tree {
     tt_tok(span, token::token),
@@ -854,6 +922,8 @@ type matcher = spanned<matcher_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum matcher_ {
     // match one token
     match_tok(token::token),
@@ -870,12 +940,16 @@ type mac_arg = Option<@expr>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type mac_body_ = {span: span};
 
 type mac_body = Option<mac_body_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum mac_ {
     mac_invoc(@path, mac_arg, mac_body), // old macro-invocation
     mac_invoc_tt(@path,~[token_tree]),   // new macro-invocation
@@ -890,6 +964,8 @@ type lit = spanned<lit_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum lit_ {
     lit_str(@~str),
     lit_int(i64, int_ty),
@@ -932,22 +1008,30 @@ impl ast::lit_: cmp::Eq {
 // type structure in middle/ty.rs as well.
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type mt = {ty: @ty, mutbl: mutability};
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type ty_field_ = {ident: ident, mt: mt};
 
 type ty_field = spanned<ty_field_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 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]
+#[auto_serialize2]
+#[auto_deserialize2]
 // A trait method is either required (meaning it doesn't have an
 // implementation, just a signature) or provided (meaning it has a default
 // implementation).
@@ -958,6 +1042,8 @@ enum trait_method {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, }
 
 impl int_ty : to_bytes::IterBytes {
@@ -988,6 +1074,8 @@ impl int_ty : cmp::Eq {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, }
 
 impl uint_ty : to_bytes::IterBytes {
@@ -1016,6 +1104,8 @@ impl uint_ty : cmp::Eq {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum float_ty { ty_f, ty_f32, ty_f64, }
 
 impl float_ty : to_bytes::IterBytes {
@@ -1035,11 +1125,15 @@ impl float_ty : cmp::Eq {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 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]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum prim_ty {
     ty_int(int_ty),
     ty_uint(uint_ty),
@@ -1088,10 +1182,14 @@ impl prim_ty : cmp::Eq {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type region = {id: node_id, node: region_};
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum region_ {
     re_anon,
     re_static,
@@ -1101,6 +1199,8 @@ enum region_ {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum ty_ {
     ty_nil,
     ty_bot, /* bottom type */
@@ -1141,10 +1241,14 @@ impl ty : to_bytes::IterBytes {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type arg = {mode: mode, ty: @ty, ident: ident, id: node_id};
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type fn_decl =
     {inputs: ~[arg],
      output: @ty,
@@ -1152,6 +1256,8 @@ type fn_decl =
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum purity {
     pure_fn, // declared with "pure fn"
     unsafe_fn, // declared with "unsafe fn"
@@ -1174,6 +1280,8 @@ impl purity : cmp::Eq {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum ret_style {
     noreturn, // functions with return type _|_ that always
               // raise an error or exit (i.e. never return to the caller)
@@ -1200,6 +1308,8 @@ impl ret_style : cmp::Eq {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum self_ty_ {
     sty_static,                         // no self: static method
     sty_by_ref,                         // old by-reference self: ``
@@ -1257,6 +1367,8 @@ type self_ty = spanned<self_ty_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type method = {ident: ident, attrs: ~[attribute],
                tps: ~[ty_param], self_ty: self_ty,
                purity: purity, decl: fn_decl, body: blk,
@@ -1265,10 +1377,14 @@ type method = {ident: ident, attrs: ~[attribute],
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type _mod = {view_items: ~[@view_item], items: ~[@item]};
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum foreign_abi {
     foreign_abi_rust_intrinsic,
     foreign_abi_cdecl,
@@ -1278,6 +1394,8 @@ enum foreign_abi {
 // Foreign mods can be named or anonymous
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum foreign_mod_sort { named, anonymous }
 
 impl foreign_mod_sort : cmp::Eq {
@@ -1303,6 +1421,8 @@ impl foreign_abi : cmp::Eq {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type foreign_mod =
     {sort: foreign_mod_sort,
      view_items: ~[@view_item],
@@ -1310,10 +1430,14 @@ type foreign_mod =
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type variant_arg = {ty: @ty, id: node_id};
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum variant_kind {
     tuple_variant_kind(~[variant_arg]),
     struct_variant_kind(@struct_def),
@@ -1322,14 +1446,20 @@ enum variant_kind {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type enum_def_ = { variants: ~[variant], common: Option<@struct_def> };
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum enum_def = enum_def_;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type variant_ = {name: ident, attrs: ~[attribute], kind: variant_kind,
                  id: node_id, disr_expr: Option<@expr>, vis: visibility};
 
@@ -1337,12 +1467,16 @@ type variant = spanned<variant_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type path_list_ident_ = {name: ident, id: node_id};
 
 type path_list_ident = spanned<path_list_ident_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum namespace { module_ns, type_value_ns }
 
 impl namespace : cmp::Eq {
@@ -1356,6 +1490,8 @@ type view_path = spanned<view_path_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum view_path_ {
 
     // quux = foo::bar::baz
@@ -1374,11 +1510,15 @@ enum view_path_ {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type view_item = {node: view_item_, attrs: ~[attribute],
                   vis: visibility, span: span};
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum view_item_ {
     view_item_use(ident, ~[@meta_item], node_id),
     view_item_import(~[@view_path]),
@@ -1393,6 +1533,8 @@ type attribute = spanned<attribute_>;
 // distinguished for pretty-printing.
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum attr_style { attr_outer, attr_inner, }
 
 impl attr_style : cmp::Eq {
@@ -1405,6 +1547,8 @@ impl attr_style : cmp::Eq {
 // doc-comments are promoted to attributes that have is_sugared_doc = true
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool};
 
 /*
@@ -1418,10 +1562,14 @@ type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool};
  */
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type trait_ref = {path: @path, ref_id: node_id, impl_id: node_id};
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum visibility { public, private, inherited }
 
 impl visibility : cmp::Eq {
@@ -1440,6 +1588,8 @@ impl visibility : cmp::Eq {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type struct_field_ = {
     kind: struct_field_kind,
     id: node_id,
@@ -1450,6 +1600,8 @@ type struct_field = spanned<struct_field_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum struct_field_kind {
     named_field(ident, class_mutability, visibility),
     unnamed_field   // element of a tuple-like struct
@@ -1457,6 +1609,8 @@ enum struct_field_kind {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type struct_def = {
     traits: ~[@trait_ref],   /* traits this struct implements */
     fields: ~[@struct_field], /* fields */
@@ -1474,12 +1628,16 @@ type struct_def = {
  */
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type item = {ident: ident, attrs: ~[attribute],
              id: node_id, node: item_,
              vis: visibility, span: span};
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum item_ {
     item_const(@ty, @expr),
     item_fn(fn_decl, purity, ~[ty_param], blk),
@@ -1498,6 +1656,8 @@ enum item_ {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum class_mutability { class_mutable, class_immutable }
 
 impl class_mutability : to_bytes::IterBytes {
@@ -1522,6 +1682,8 @@ type class_ctor = spanned<class_ctor_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type class_ctor_ = {id: node_id,
                     attrs: ~[attribute],
                     self_id: node_id,
@@ -1532,6 +1694,8 @@ type class_dtor = spanned<class_dtor_>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type class_dtor_ = {id: node_id,
                     attrs: ~[attribute],
                     self_id: node_id,
@@ -1539,6 +1703,8 @@ type class_dtor_ = {id: node_id,
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type foreign_item =
     {ident: ident,
      attrs: ~[attribute],
@@ -1549,6 +1715,8 @@ type foreign_item =
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum foreign_item_ {
     foreign_item_fn(fn_decl, purity, ~[ty_param]),
     foreign_item_const(@ty)
@@ -1559,6 +1727,8 @@ enum foreign_item_ {
 // that we trans.
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum inlined_item {
     ii_item(@item),
     ii_method(def_id /* impl id */, @method),
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index ab24d7a5316..897a51f710c 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -408,6 +408,8 @@ fn dtor_dec() -> fn_decl {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type id_range = {min: node_id, max: node_id};
 
 fn empty(range: id_range) -> bool {
diff --git a/src/libsyntax/ext/auto_serialize2.rs b/src/libsyntax/ext/auto_serialize2.rs
new file mode 100644
index 00000000000..b3102f8b4f7
--- /dev/null
+++ b/src/libsyntax/ext/auto_serialize2.rs
@@ -0,0 +1,991 @@
+/*
+
+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]
+        }
+    }
+}
+
+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 c106042b9a3..ab56b6bb322 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -54,7 +54,7 @@ enum syntax_extension {
     // macro_defining() is obsolete, remove when #old_macros go away.
     macro_defining(macro_definer),
 
-    // #[auto_serialize] and such. will probably survive death of #old_macros
+    // #[auto_serialize2] and such. will probably survive death of #old_macros
     item_decorator(item_decorator),
 
     // Token-tree expanders
@@ -64,6 +64,65 @@ enum syntax_extension {
 
 // A temporary hard-coded map of methods for expanding syntax extension
 // AST nodes into full ASTs
+#[cfg(stage0)]
+fn syntax_expander_table() -> HashMap<~str, syntax_extension> {
+    fn builtin(f: syntax_expander_) -> syntax_extension
+        {normal({expander: f, span: None})}
+    fn builtin_expr_tt(f: syntax_expander_tt_) -> syntax_extension {
+        expr_tt({expander: f, span: None})
+    }
+    fn builtin_item_tt(f: syntax_expander_tt_item_) -> syntax_extension {
+        item_tt({expander: f, span: None})
+    }
+    let syntax_expanders = HashMap();
+    syntax_expanders.insert(~"macro",
+                            macro_defining(ext::simplext::add_new_extension));
+    syntax_expanders.insert(~"macro_rules",
+                            builtin_item_tt(
+                                ext::tt::macro_rules::add_new_extension));
+    syntax_expanders.insert(~"fmt", builtin(ext::fmt::expand_syntax_ext));
+    syntax_expanders.insert(
+        ~"auto_serialize2",
+        item_decorator(ext::auto_serialize2::expand_auto_serialize));
+    syntax_expanders.insert(
+        ~"auto_deserialize2",
+        item_decorator(ext::auto_serialize2::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));
+    syntax_expanders.insert(~"ident_to_str",
+                            builtin(ext::ident_to_str::expand_syntax_ext));
+    syntax_expanders.insert(~"log_syntax",
+                            builtin_expr_tt(
+                                ext::log_syntax::expand_syntax_ext));
+    syntax_expanders.insert(~"ast",
+                            builtin(ext::qquote::expand_ast));
+    syntax_expanders.insert(~"line",
+                            builtin(ext::source_util::expand_line));
+    syntax_expanders.insert(~"col",
+                            builtin(ext::source_util::expand_col));
+    syntax_expanders.insert(~"file",
+                            builtin(ext::source_util::expand_file));
+    syntax_expanders.insert(~"stringify",
+                            builtin(ext::source_util::expand_stringify));
+    syntax_expanders.insert(~"include",
+                            builtin(ext::source_util::expand_include));
+    syntax_expanders.insert(~"include_str",
+                            builtin(ext::source_util::expand_include_str));
+    syntax_expanders.insert(~"include_bin",
+                            builtin(ext::source_util::expand_include_bin));
+    syntax_expanders.insert(~"module_path",
+                            builtin(ext::source_util::expand_mod));
+    syntax_expanders.insert(~"proto",
+                            builtin_item_tt(ext::pipes::expand_proto));
+    syntax_expanders.insert(
+        ~"trace_macros",
+        builtin_expr_tt(ext::trace_macros::expand_trace_macros));
+    return syntax_expanders;
+}
+
+#[cfg(stage1)]
+#[cfg(stage2)]
 fn syntax_expander_table() -> HashMap<~str, syntax_extension> {
     fn builtin(f: syntax_expander_) -> syntax_extension
         {normal({expander: f, span: None})}
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 22e2cfcde6b..2d0b2f4c80a 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -124,7 +124,7 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
 }
 
 // This is a secondary mechanism for invoking syntax extensions on items:
-// "decorator" attributes, such as #[auto_serialize]. These are invoked by an
+// "decorator" attributes, such as #[auto_serialize2]. These are invoked by an
 // attribute prefixing an item, and are interpreted by feeding the item
 // through the named attribute _as a syntax extension_ and splicing in the
 // resulting item vec into place in favour of the decorator. Note that
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index dce4dc3bbc7..b63260997f7 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -4,6 +4,8 @@ use std::map::HashMap;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum binop {
     PLUS,
     MINUS,
@@ -19,6 +21,8 @@ enum binop {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum token {
     /* Expression-operator symbols. */
     EQ,
@@ -77,6 +81,8 @@ enum token {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 /// For interpolation during macro expansion.
 enum nonterminal {
     nt_item(@ast::item),
diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc
index 93ed5bd471b..4c29fc5512a 100644
--- a/src/libsyntax/syntax.rc
+++ b/src/libsyntax/syntax.rc
@@ -130,6 +130,9 @@ mod ext {
     mod log_syntax;
     #[legacy_exports]
     mod auto_serialize;
+    #[cfg(stage0)]
+    #[legacy_exports]
+    mod auto_serialize2;
     #[legacy_exports]
     mod source_util;
 
diff --git a/src/rustc/middle/freevars.rs b/src/rustc/middle/freevars.rs
index 1b42c9bb4b6..28400b5455d 100644
--- a/src/rustc/middle/freevars.rs
+++ b/src/rustc/middle/freevars.rs
@@ -18,6 +18,8 @@ export has_freevars;
 // (The def_upvar will already have been stripped).
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type freevar_entry = {
     def: ast::def, //< The variable being accessed free.
     span: span     //< First span where it is accessed (there can be multiple)
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index ca41be6f9d0..85f03e1f0b3 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -213,6 +213,8 @@ type mt = {ty: t, mutbl: ast::mutability};
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum vstore {
     vstore_fixed(uint),
     vstore_uniq,
@@ -273,6 +275,8 @@ type opt_region_variance = Option<region_variance>;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum region_variance { rv_covariant, rv_invariant, rv_contravariant }
 
 impl region_variance : cmp::Eq {
@@ -291,6 +295,8 @@ impl region_variance : cmp::Eq {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type AutoAdjustment = {
     autoderefs: uint,
     autoref: Option<AutoRef>
@@ -298,6 +304,8 @@ type AutoAdjustment = {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type AutoRef = {
     kind: AutoRefKind,
     region: region,
@@ -306,6 +314,8 @@ type AutoRef = {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum AutoRefKind {
     /// Convert from @[]/~[] to &[] (or str)
     AutoSlice,
@@ -511,6 +521,8 @@ impl param_ty : to_bytes::IterBytes {
 /// Representation of regions:
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum region {
     /// Bound regions are found (primarily) in function types.  They indicate
     /// region parameters that have yet to be replaced with actual regions
@@ -540,6 +552,8 @@ enum region {
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum bound_region {
     /// The self region for classes, impls (&T in a type defn or &self/T)
     br_self,
@@ -671,6 +685,8 @@ enum IntVid = uint;
 enum FnVid = uint;
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum RegionVid = uint;
 
 enum InferTy {
diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs
index 7cb04bc0ea3..027a1d06742 100644
--- a/src/rustc/middle/typeck.rs
+++ b/src/rustc/middle/typeck.rs
@@ -77,6 +77,8 @@ export provided_methods_map;
 
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 enum method_origin {
     // fully statically resolved method
     method_static(ast::def_id),
@@ -95,6 +97,8 @@ enum method_origin {
 // with a bounded trait.
 #[auto_serialize]
 #[auto_deserialize]
+#[auto_serialize2]
+#[auto_deserialize2]
 type method_param = {
     // the trait containing the method to be invoked
     trait_id: ast::def_id,