diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 4c876669f47..c1163fda844 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -54,43 +54,52 @@ pub fn mk_binary(cx: @ext_ctxt, sp: span, op: ast::binop,
     cx.next_id(); // see ast_util::op_expr_callee_id
     mk_expr(cx, sp, ast::expr_binary(op, lhs, rhs))
 }
+
+pub fn mk_deref(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr {
+    mk_unary(cx, sp, ast::deref, e)
+}
 pub fn mk_unary(cx: @ext_ctxt, sp: span, op: ast::unop, e: @ast::expr)
              -> @ast::expr {
     cx.next_id(); // see ast_util::op_expr_callee_id
     mk_expr(cx, sp, ast::expr_unary(op, e))
 }
 pub fn mk_raw_path(sp: span, idents: ~[ast::ident]) -> @ast::Path {
-    mk_raw_path_(sp, idents, ~[])
+    mk_raw_path_(sp, idents, None, ~[])
 }
 pub fn mk_raw_path_(sp: span,
                     idents: ~[ast::ident],
+                    rp: Option<@ast::Lifetime>,
                     types: ~[@ast::Ty])
                  -> @ast::Path {
     @ast::Path { span: sp,
                  global: false,
                  idents: idents,
-                 rp: None,
+                 rp: rp,
                  types: types }
 }
 pub fn mk_raw_path_global(sp: span, idents: ~[ast::ident]) -> @ast::Path {
-    mk_raw_path_global_(sp, idents, ~[])
+    mk_raw_path_global_(sp, idents, None, ~[])
 }
 pub fn mk_raw_path_global_(sp: span,
                            idents: ~[ast::ident],
+                           rp: Option<@ast::Lifetime>,
                            types: ~[@ast::Ty]) -> @ast::Path {
     @ast::Path { span: sp,
                  global: true,
                  idents: idents,
-                 rp: None,
+                 rp: rp,
                  types: types }
 }
+pub fn mk_path_raw(cx: @ext_ctxt, sp: span, path: @ast::Path)-> @ast::expr {
+    mk_expr(cx, sp, ast::expr_path(path))
+}
 pub fn mk_path(cx: @ext_ctxt, sp: span, idents: ~[ast::ident])
             -> @ast::expr {
-    mk_expr(cx, sp, ast::expr_path(mk_raw_path(sp, idents)))
+    mk_path_raw(cx, sp, mk_raw_path(sp, idents))
 }
 pub fn mk_path_global(cx: @ext_ctxt, sp: span, idents: ~[ast::ident])
                    -> @ast::expr {
-    mk_expr(cx, sp, ast::expr_path(mk_raw_path_global(sp, idents)))
+    mk_path_raw(cx, sp, mk_raw_path_global(sp, idents))
 }
 pub fn mk_access_(cx: @ext_ctxt, sp: span, p: @ast::expr, m: ast::ident)
                -> @ast::expr {
@@ -354,44 +363,69 @@ pub fn mk_stmt(cx: @ext_ctxt, span: span, expr: @ast::expr) -> @ast::stmt {
     let stmt_ = ast::stmt_semi(expr, cx.next_id());
     @codemap::spanned { node: stmt_, span: span }
 }
+
+pub fn mk_ty_mt(ty: @ast::Ty, mutbl: ast::mutability) -> ast::mt {
+    ast::mt {
+        ty: ty,
+        mutbl: mutbl
+    }
+}
+
+pub fn mk_ty(cx: @ext_ctxt,
+             span: span,
+             ty: ast::ty_) -> @ast::Ty {
+    @ast::Ty {
+        id: cx.next_id(),
+        span: span,
+        node: ty
+    }
+}
+
 pub fn mk_ty_path(cx: @ext_ctxt,
                   span: span,
                   idents: ~[ ast::ident ])
                -> @ast::Ty {
     let ty = build::mk_raw_path(span, idents);
-    let ty = ast::ty_path(ty, cx.next_id());
-    let ty = @ast::Ty { id: cx.next_id(), node: ty, span: span };
-    ty
+    mk_ty_path_path(cx, span, ty)
 }
+
 pub fn mk_ty_path_global(cx: @ext_ctxt,
                          span: span,
                          idents: ~[ ast::ident ])
                       -> @ast::Ty {
     let ty = build::mk_raw_path_global(span, idents);
-    let ty = ast::ty_path(ty, cx.next_id());
-    let ty = @ast::Ty { id: cx.next_id(), node: ty, span: span };
-    ty
+    mk_ty_path_path(cx, span, ty)
 }
+
+pub fn mk_ty_path_path(cx: @ext_ctxt,
+                       span: span,
+                       path: @ast::Path)
+                      -> @ast::Ty {
+    let ty = ast::ty_path(path, cx.next_id());
+    mk_ty(cx, span, ty)
+}
+
 pub fn mk_ty_rptr(cx: @ext_ctxt,
                   span: span,
                   ty: @ast::Ty,
+                  lifetime: Option<@ast::Lifetime>,
                   mutbl: ast::mutability)
                -> @ast::Ty {
-    @ast::Ty {
-        id: cx.next_id(),
-        span: span,
-        node: ast::ty_rptr(
-            None,
-            ast::mt { ty: ty, mutbl: mutbl }
-        ),
-    }
+    mk_ty(cx, span,
+          ast::ty_rptr(lifetime, mk_ty_mt(ty, mutbl)))
 }
+pub fn mk_ty_uniq(cx: @ext_ctxt, span: span, ty: @ast::Ty) -> @ast::Ty {
+    mk_ty(cx, span, ast::ty_uniq(mk_ty_mt(ty, ast::m_imm)))
+}
+pub fn mk_ty_box(cx: @ext_ctxt, span: span,
+                 ty: @ast::Ty, mutbl: ast::mutability) -> @ast::Ty {
+    mk_ty(cx, span, ast::ty_box(mk_ty_mt(ty, mutbl)))
+}
+
+
+
 pub fn mk_ty_infer(cx: @ext_ctxt, span: span) -> @ast::Ty {
-    @ast::Ty {
-        id: cx.next_id(),
-        node: ast::ty_infer,
-        span: span,
-    }
+    mk_ty(cx, span, ast::ty_infer)
 }
 pub fn mk_trait_ref_global(cx: @ext_ctxt,
                            span: span,
diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs
index d996bca60a3..1c33fe35070 100644
--- a/src/libsyntax/ext/deriving/clone.rs
+++ b/src/libsyntax/ext/deriving/clone.rs
@@ -13,7 +13,6 @@ use codemap::span;
 use ext::base::ext_ctxt;
 use ext::build;
 use ext::deriving::generic::*;
-use core::option::{None,Some};
 
 
 pub fn expand_deriving_clone(cx: @ext_ctxt,
@@ -22,13 +21,16 @@ pub fn expand_deriving_clone(cx: @ext_ctxt,
                              in_items: ~[@item])
                           -> ~[@item] {
     let trait_def = TraitDef {
-        path: ~[~"core", ~"clone", ~"Clone"],
+        path: Path::new(~[~"core", ~"clone", ~"Clone"]),
         additional_bounds: ~[],
+        generics: LifetimeBounds::empty(),
         methods: ~[
             MethodDef {
                 name: ~"clone",
-                nargs: 0,
-                output_type: None, // return Self
+                generics: LifetimeBounds::empty(),
+                self_ty: borrowed_explicit_self(),
+                args: ~[],
+                ret_ty: Self,
                 const_nonmatching: false,
                 combine_substructure: cs_clone
             }
@@ -66,7 +68,8 @@ fn cs_clone(cx: @ext_ctxt, span: span,
             ctor_ident = ~[ variant.node.name ];
             all_fields = af;
         },
-        EnumNonMatching(*) => cx.bug("Non-matching enum variants in `deriving(Clone)`")
+        EnumNonMatching(*) => cx.span_bug(span, "Non-matching enum variants in `deriving(Clone)`"),
+        StaticEnum(*) | StaticStruct(*) => cx.span_bug(span, "Static method in `deriving(Clone)`")
     }
 
     match all_fields {
diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs
index c0060cc67dc..e431e1f78bf 100644
--- a/src/libsyntax/ext/deriving/cmp/eq.rs
+++ b/src/libsyntax/ext/deriving/cmp/eq.rs
@@ -8,15 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 use ast::{meta_item, item, expr};
 use codemap::span;
 use ext::base::ext_ctxt;
 use ext::build;
 use ext::deriving::generic::*;
 
-use core::option::Some;
-
 pub fn expand_deriving_eq(cx: @ext_ctxt,
                           span: span,
                           mitem: @meta_item,
@@ -24,28 +21,32 @@ pub fn expand_deriving_eq(cx: @ext_ctxt,
     // structures are equal if all fields are equal, and non equal, if
     // any fields are not equal or if the enum variants are different
     fn cs_eq(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr {
-        cs_and(|cx, span, _| build::mk_bool(cx, span, false),
+        cs_and(|cx, span, _, _| build::mk_bool(cx, span, false),
                                  cx, span, substr)
     }
     fn cs_ne(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr {
-        cs_or(|cx, span, _| build::mk_bool(cx, span, true),
+        cs_or(|cx, span, _, _| build::mk_bool(cx, span, true),
               cx, span, substr)
     }
+
     macro_rules! md (
         ($name:expr, $f:ident) => {
             MethodDef {
                 name: $name,
-                output_type: Some(~[~"bool"]),
-                nargs: 1,
+                generics: LifetimeBounds::empty(),
+                self_ty: borrowed_explicit_self(),
+                args: ~[borrowed_self()],
+                ret_ty: Literal(Path::new(~[~"bool"])),
                 const_nonmatching: true,
                 combine_substructure: $f
             },
         }
-    )
+    );
 
     let trait_def = TraitDef {
-        path: ~[~"core", ~"cmp", ~"Eq"],
+        path: Path::new(~[~"core", ~"cmp", ~"Eq"]),
         additional_bounds: ~[],
+        generics: LifetimeBounds::empty(),
         methods: ~[
             md!(~"eq", cs_eq),
             md!(~"ne", cs_ne)
diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs
index 398e27eb3e3..5998fc7145d 100644
--- a/src/libsyntax/ext/deriving/cmp/ord.rs
+++ b/src/libsyntax/ext/deriving/cmp/ord.rs
@@ -14,29 +14,33 @@ use codemap::span;
 use ext::base::ext_ctxt;
 use ext::build;
 use ext::deriving::generic::*;
-use core::option::Some;
-
-macro_rules! md {
-    ($name:expr, $less:expr, $equal:expr) => {
-        MethodDef {
-            name: $name,
-            output_type: Some(~[~"bool"]),
-            nargs: 1,
-            const_nonmatching: false,
-            combine_substructure: |cx, span, substr|
-                    cs_ord($less, $equal, cx, span, substr)
-        }
-    }
-}
 
 pub fn expand_deriving_ord(cx: @ext_ctxt,
                            span: span,
                            mitem: @meta_item,
                            in_items: ~[@item]) -> ~[@item] {
+    macro_rules! md (
+        ($name:expr, $less:expr, $equal:expr) => {
+            MethodDef {
+                name: $name,
+                generics: LifetimeBounds::empty(),
+                self_ty: borrowed_explicit_self(),
+                args: ~[borrowed_self()],
+                ret_ty: Literal(Path::new(~[~"bool"])),
+                const_nonmatching: false,
+                combine_substructure: |cx, span, substr|
+                    cs_ord($less, $equal, cx, span, substr)
+            }
+        }
+    );
+
+
+
     let trait_def = TraitDef {
-        path: ~[~"core", ~"cmp", ~"Ord"],
+        path: Path::new(~[~"core", ~"cmp", ~"Ord"]),
         // XXX: Ord doesn't imply Eq yet
-        additional_bounds: ~[~[~"core", ~"cmp", ~"Eq"]],
+        additional_bounds: ~[Literal(Path::new(~[~"core", ~"cmp", ~"Eq"]))],
+        generics: LifetimeBounds::empty(),
         methods: ~[
             md!(~"lt", true,  false),
             md!(~"le", true,  true),
@@ -97,19 +101,19 @@ fn cs_ord(less: bool, equal: bool,
             }
 
             let cmp = build::mk_method_call(cx, span,
-                                            self_f, cx.ident_of(~"eq"), other_fs);
+                                            self_f, cx.ident_of(~"eq"), other_fs.to_owned());
             let subexpr = build::mk_simple_block(cx, span, subexpr);
             let elseif = expr_if(cmp, subexpr, Some(false_blk_expr));
             let elseif = build::mk_expr(cx, span, elseif);
 
             let cmp = build::mk_method_call(cx, span,
-                                            self_f, binop, other_fs);
+                                            self_f, binop, other_fs.to_owned());
             let if_ = expr_if(cmp, true_blk, Some(elseif));
 
             build::mk_expr(cx, span, if_)
         },
         base,
-        |cx, span, args| {
+        |cx, span, args, _| {
             // nonmatching enums, order by the order the variants are
             // written
             match args {
diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs
index fc8ec103a60..068a7bc06b1 100644
--- a/src/libsyntax/ext/deriving/cmp/totaleq.rs
+++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs
@@ -15,26 +15,27 @@ use ext::base::ext_ctxt;
 use ext::build;
 use ext::deriving::generic::*;
 
-use core::option::Some;
-
 pub fn expand_deriving_totaleq(cx: @ext_ctxt,
                           span: span,
                           mitem: @meta_item,
                           in_items: ~[@item]) -> ~[@item] {
 
     fn cs_equals(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr {
-        cs_and(|cx, span, _| build::mk_bool(cx, span, false),
+        cs_and(|cx, span, _, _| build::mk_bool(cx, span, false),
                cx, span, substr)
     }
 
     let trait_def = TraitDef {
-        path: ~[~"core", ~"cmp", ~"TotalEq"],
+        path: Path::new(~[~"core", ~"cmp", ~"TotalEq"]),
         additional_bounds: ~[],
+        generics: LifetimeBounds::empty(),
         methods: ~[
             MethodDef {
                 name: ~"equals",
-                output_type: Some(~[~"bool"]),
-                nargs: 1,
+                generics: LifetimeBounds::empty(),
+                self_ty: borrowed_explicit_self(),
+                args: ~[borrowed_self()],
+                ret_ty: Literal(Path::new(~[~"bool"])),
                 const_nonmatching: true,
                 combine_substructure: cs_equals
             }
diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs
index a098a7463d3..ac873c5bd12 100644
--- a/src/libsyntax/ext/deriving/cmp/totalord.rs
+++ b/src/libsyntax/ext/deriving/cmp/totalord.rs
@@ -14,20 +14,22 @@ use ext::base::ext_ctxt;
 use ext::build;
 use ext::deriving::generic::*;
 use core::cmp::{Ordering, Equal, Less, Greater};
-use core::option::Some;
 
 pub fn expand_deriving_totalord(cx: @ext_ctxt,
                                 span: span,
                                 mitem: @meta_item,
                                 in_items: ~[@item]) -> ~[@item] {
     let trait_def = TraitDef {
-        path: ~[~"core", ~"cmp", ~"TotalOrd"],
+        path: Path::new(~[~"core", ~"cmp", ~"TotalOrd"]),
         additional_bounds: ~[],
+        generics: LifetimeBounds::empty(),
         methods: ~[
             MethodDef {
                 name: ~"cmp",
-                output_type: Some(~[~"core", ~"cmp", ~"Ordering"]),
-                nargs: 1,
+                generics: LifetimeBounds::empty(),
+                self_ty: borrowed_explicit_self(),
+                args: ~[borrowed_self()],
+                ret_ty: Literal(Path::new(~[~"core", ~"cmp", ~"Ordering"])),
                 const_nonmatching: false,
                 combine_substructure: cs_cmp
             }
@@ -64,7 +66,7 @@ pub fn cs_cmp(cx: @ext_ctxt, span: span,
             build::mk_call_global(cx, span, lexical_ord, ~[old, new])
         },
         ordering_const(cx, span, Equal),
-        |cx, span, list| {
+        |cx, span, list, _| {
             match list {
                 // an earlier nonmatching variant is Less than a
                 // later one
diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs
index fe270abc2e4..79cc4a3bda8 100644
--- a/src/libsyntax/ext/deriving/decodable.rs
+++ b/src/libsyntax/ext/deriving/decodable.rs
@@ -66,6 +66,7 @@ fn create_derived_decodable_impl(
             cx.ident_of(~"serialize"),
             cx.ident_of(~"Decodable")
         ],
+        None,
         ~[
             build::mk_simple_ty_path(cx, span, cx.ident_of(~"__D"))
         ]
@@ -77,7 +78,7 @@ fn create_derived_decodable_impl(
         generics,
         methods,
         trait_path,
-        generic_ty_params,
+        Generics { ty_params: generic_ty_params, lifetimes: opt_vec::Empty },
         opt_vec::Empty
     )
 }
@@ -96,6 +97,7 @@ fn create_decode_method(
         cx,
         span,
         build::mk_simple_ty_path(cx, span, cx.ident_of(~"__D")),
+        None,
         ast::m_mutbl
     );
     let d_ident = cx.ident_of(~"__d");
diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs
index 8f8139790ad..8b86173dc24 100644
--- a/src/libsyntax/ext/deriving/encodable.rs
+++ b/src/libsyntax/ext/deriving/encodable.rs
@@ -66,6 +66,7 @@ fn create_derived_encodable_impl(
             cx.ident_of(~"serialize"),
             cx.ident_of(~"Encodable")
         ],
+        None,
         ~[
             build::mk_simple_ty_path(cx, span, cx.ident_of(~"__E"))
         ]
@@ -77,7 +78,7 @@ fn create_derived_encodable_impl(
         generics,
         methods,
         trait_path,
-        generic_ty_params,
+        Generics { ty_params: generic_ty_params, lifetimes: opt_vec::Empty },
         opt_vec::Empty
     )
 }
@@ -94,6 +95,7 @@ fn create_encode_method(
         cx,
         span,
         build::mk_simple_ty_path(cx, span, cx.ident_of(~"__E")),
+        None,
         ast::m_mutbl
     );
     let e_arg = build::mk_arg(cx, span, cx.ident_of(~"__e"), e_arg_type);
@@ -303,7 +305,7 @@ fn expand_deriving_encodable_enum_method(
     // Create the arms of the match in the method body.
     let arms = do enum_definition.variants.mapi |i, variant| {
         // Create the matching pattern.
-        let pat = create_enum_variant_pattern(cx, span, variant, ~"__self");
+        let (pat, fields) = create_enum_variant_pattern(cx, span, variant, ~"__self", ast::m_imm);
 
         // Feed the discriminant to the encode function.
         let mut stmts = ~[];
@@ -311,11 +313,7 @@ fn expand_deriving_encodable_enum_method(
         // Feed each argument in this variant to the encode function
         // as well.
         let variant_arg_len = variant_arg_count(cx, span, variant);
-        for uint::range(0, variant_arg_len) |j| {
-            // Create the expression for this field.
-            let field_ident = cx.ident_of(~"__self_" + j.to_str());
-            let field = build::mk_path(cx, span, ~[ field_ident ]);
-
+        for fields.eachi |j, &(_, field)| {
             // Call the substructure method.
             let expr = call_substructure_encode_method(cx, span, field);
 
diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs
index 05941f4cbd6..565d6dd59ba 100644
--- a/src/libsyntax/ext/deriving/generic.rs
+++ b/src/libsyntax/ext/deriving/generic.rs
@@ -16,23 +16,22 @@ access to the fields of the 4 different sorts of structs and enum
 variants, as well as creating the method and impl ast instances.
 
 Supported features (fairly exhaustive):
-- Methods taking any number of parameters of type `&Self`, including
-  none other than `self`. (`MethodDef.nargs`)
-- Methods returning `Self` or a non-parameterised type
-  (e.g. `bool` or `core::cmp::Ordering`). (`MethodDef.output_type`)
-- Generating `impl`s for types with type parameters
+- Methods taking any number of parameters of any type, and returning
+  any type, other than vectors, bottom and closures.
+- Generating `impl`s for types with type parameters and lifetimes
   (e.g. `Option<T>`), the parameters are automatically given the
-  current trait as a bound.
+  current trait as a bound. (This includes separate type parameters
+  and lifetimes for methods.)
 - Additional bounds on the type parameters, e.g. the `Ord` instance
   requires an explicit `Eq` bound at the
   moment. (`TraitDef.additional_bounds`)
 
-(Key unsupported things: methods with arguments of non-`&Self` type,
-traits with parameters, methods returning parameterised types, static
-methods.)
+Unsupported: FIXME #6257: calling methods on borrowed pointer fields,
+e.g. deriving TotalEq/TotalOrd/Clone don't work on `struct A(&int)`,
+because of how the auto-dereferencing happens.
 
 The most important thing for implementers is the `Substructure` and
-`SubstructureFields` objects. The latter groups 3 possibilities of the
+`SubstructureFields` objects. The latter groups 5 possibilities of the
 arguments:
 
 - `Struct`, when `Self` is a struct (including tuple structs, e.g
@@ -42,42 +41,57 @@ arguments:
 - `EnumNonMatching` when `Self` is an enum and the arguments are not
   the same variant (e.g. `None`, `Some(1)` and `None`). If
   `const_nonmatching` is true, this will contain an empty list.
+- `StaticEnum` and `StaticStruct` for static methods, where the type
+  being derived upon is either a enum or struct respectively. (Any
+  argument with type Self is just grouped among the non-self
+  arguments.)
 
 In the first two cases, the values from the corresponding fields in
 all the arguments are grouped together. In the `EnumNonMatching` case
 this isn't possible (different variants have different fields), so the
-fields are grouped by which argument they come from.
+fields are grouped by which argument they come from. There are no
+fields with values in the static cases, so these are treated entirely
+differently.
 
-All of the cases have `Option<ident>` in several places associated
+The non-static cases have `Option<ident>` in several places associated
 with field `expr`s. This represents the name of the field it is
 associated with. It is only not `None` when the associated field has
 an identifier in the source code. For example, the `x`s in the
 following snippet
 
-    struct A { x : int }
+~~~
+struct A { x : int }
 
-    struct B(int);
+struct B(int);
 
-    enum C {
-        C0(int),
-        C1 { x: int }
-    }
+enum C {
+    C0(int),
+    C1 { x: int }
+}
 
 The `int`s in `B` and `C0` don't have an identifier, so the
 `Option<ident>`s would be `None` for them.
 
+In the static cases, the structure is summarised, either into the
+number of fields or a list of field idents (for tuple structs and
+record structs, respectively), or a list of these, for enums (one for
+each variant). For empty struct and empty enum variants, it is
+represented as a count of 0.
+
 # Examples
 
 The following simplified `Eq` is used for in-code examples:
 
-    trait Eq {
-        fn eq(&self, other: &Self);
-    }
-    impl Eq for int {
-        fn eq(&self, other: &int) -> bool {
-            *self == *other
-        }
+~~~
+trait Eq {
+    fn eq(&self, other: &Self);
+}
+impl Eq for int {
+    fn eq(&self, other: &int) -> bool {
+        *self == *other
     }
+}
+~~~
 
 Some examples of the values of `SubstructureFields` follow, using the
 above `Eq`, `A`, `B` and `C`.
@@ -86,65 +100,85 @@ above `Eq`, `A`, `B` and `C`.
 
 When generating the `expr` for the `A` impl, the `SubstructureFields` is
 
-    Struct(~[(Some(<ident of x>),
-             <expr for self.x>,
-             ~[<expr for other.x])])
+~~~
+Struct(~[(Some(<ident of x>),
+         <expr for &self.x>,
+         ~[<expr for &other.x])])
+~~~
 
 For the `B` impl, called with `B(a)` and `B(b)`,
 
-    Struct(~[(None,
-              <expr for a>
-              ~[<expr for b>])])
+~~~
+Struct(~[(None,
+          <expr for &a>
+          ~[<expr for &b>])])
+~~~
 
 ## Enums
 
 When generating the `expr` for a call with `self == C0(a)` and `other
 == C0(b)`, the SubstructureFields is
 
-    EnumMatching(0, <ast::variant for C0>,
-                 ~[None,
-                   <expr for a>,
-                   ~[<expr for b>]])
+~~~
+EnumMatching(0, <ast::variant for C0>,
+             ~[None,
+               <expr for &a>,
+               ~[<expr for &b>]])
+~~~
 
 For `C1 {x}` and `C1 {x}`,
 
-    EnumMatching(1, <ast::variant for C1>,
-                 ~[Some(<ident of x>),
-                   <expr for self.x>,
-                   ~[<expr for other.x>]])
+~~~
+EnumMatching(1, <ast::variant for C1>,
+             ~[Some(<ident of x>),
+               <expr for &self.x>,
+               ~[<expr for &other.x>]])
+~~~
 
 For `C0(a)` and `C1 {x}` ,
 
-    EnumNonMatching(~[(0, <ast::variant for B0>,
-                       ~[(None, <expr for a>)]),
-                      (1, <ast::variant for B1>,
-                       ~[(Some(<ident of x>),
-                          <expr for other.x>)])])
+~~~
+EnumNonMatching(~[(0, <ast::variant for B0>,
+                   ~[(None, <expr for &a>)]),
+                  (1, <ast::variant for B1>,
+                   ~[(Some(<ident of x>),
+                      <expr for &other.x>)])])
+~~~
 
-(and vice verse, but with the order of the outermost list flipped.)
+(and vice versa, but with the order of the outermost list flipped.)
+
+## Static
+
+A static method on the above would result in,
+
+~~~~
+StaticStruct(<ast::struct_def of A>, Right(~[<ident of x>]))
+
+StaticStruct(<ast::struct_def of B>, Left(1))
+
+StaticEnum(<ast::enum_def of C>, ~[(<ident of C0>, Left(1)),
+                                   (<ident of C1>, Right(~[<ident of x>]))])
+~~~
 
 */
 
 use ast;
+use ast::{enum_def, expr, ident, Generics, struct_def};
 
-use ast::{
-    and, binop, deref, enum_def, expr, expr_match, ident, impure_fn,
-    item, Generics, m_imm, meta_item, method, named_field, or,
-    pat_wild, public, struct_def, sty_region, ty_rptr, ty_path,
-    variant};
-
-use ast_util;
 use ext::base::ext_ctxt;
 use ext::build;
 use ext::deriving::*;
 use codemap::{span,respan};
 use opt_vec;
 
+pub use self::ty::*;
+mod ty;
+
 pub fn expand_deriving_generic(cx: @ext_ctxt,
                                span: span,
-                               _mitem: @meta_item,
-                               in_items: ~[@item],
-                               trait_def: &TraitDef) -> ~[@item] {
+                               _mitem: @ast::meta_item,
+                               in_items: ~[@ast::item],
+                               trait_def: &TraitDef) -> ~[@ast::item] {
     let expand_enum: ExpandDerivingEnumDefFn =
         |cx, span, enum_def, type_ident, generics| {
         trait_def.expand_enum_def(cx, span, enum_def, type_ident, generics)
@@ -160,25 +194,38 @@ pub fn expand_deriving_generic(cx: @ext_ctxt,
 }
 
 pub struct TraitDef<'self> {
-    /// Path of the trait
-    path: ~[~str],
-    /// Additional bounds required of any type parameters, other than
-    /// the current trait
-    additional_bounds: ~[~[~str]],
+    /// Path of the trait, including any type parameters
+    path: Path,
+    /// Additional bounds required of any type parameters of the type,
+    /// other than the current trait
+    additional_bounds: ~[Ty],
+
+    /// Any extra lifetimes and/or bounds, e.g. `D: std::serialize::Decoder`
+    generics: LifetimeBounds,
+
     methods: ~[MethodDef<'self>]
 }
 
+
 pub struct MethodDef<'self> {
     /// name of the method
     name: ~str,
-    /// The path of return type of the method, e.g. `~[~"core",
-    /// ~"cmp", ~"Eq"]`. `None` for `Self`.
-    output_type: Option<~[~str]>,
-    /// Number of arguments other than `self` (all of type `&Self`)
-    nargs: uint,
+    /// List of generics, e.g. `R: core::rand::Rng`
+    generics: LifetimeBounds,
+
+    /// Whether there is a self argument (outer Option) i.e. whether
+    /// this is a static function, and whether it is a pointer (inner
+    /// Option)
+    self_ty: Option<Option<PtrTy>>,
+
+    /// Arguments other than the self argument
+    args: ~[Ty],
+
+    /// Return type
+    ret_ty: Ty,
 
     /// if the value of the nonmatching enums is independent of the
-    /// actual enums, i.e. can use _ => .. match.
+    /// actual enum variants, i.e. can use _ => .. match.
     const_nonmatching: bool,
 
     combine_substructure: CombineSubstructureFunc<'self>
@@ -186,18 +233,24 @@ pub struct MethodDef<'self> {
 
 /// All the data about the data structure/method being derived upon.
 pub struct Substructure<'self> {
+    /// ident of self
     type_ident: ident,
+    /// ident of the method
     method_ident: ident,
-    fields: &'self SubstructureFields
+    /// dereferenced access to any Self or Ptr(Self, _) arguments
+    self_args: &'self [@expr],
+    /// verbatim access to any other arguments
+    nonself_args: &'self [@expr],
+    fields: &'self SubstructureFields<'self>
 }
 
 /// A summary of the possible sets of fields. See above for details
 /// and examples
-pub enum SubstructureFields {
+pub enum SubstructureFields<'self> {
     /**
-    Vec of `(field ident, self, [others])` where the field ident is
-    the ident of the current field (`None` for all fields in tuple
-    structs)
+    Vec of `(field ident, self_or_other)` where the field
+    ident is the ident of the current field (`None` for all fields in tuple
+    structs).
     */
     Struct(~[(Option<ident>, @expr, ~[@expr])]),
 
@@ -206,17 +259,23 @@ pub enum SubstructureFields {
     fields: `(field ident, self, [others])`, where the field ident is
     only non-`None` in the case of a struct variant.
     */
-    EnumMatching(uint, variant, ~[(Option<ident>, @expr, ~[@expr])]),
+    EnumMatching(uint, ast::variant, ~[(Option<ident>, @expr, ~[@expr])]),
 
     /**
     non-matching variants of the enum, [(variant index, ast::variant,
     [field ident, fields])] (i.e. all fields for self are in the
     first tuple, for other1 are in the second tuple, etc.)
     */
-    EnumNonMatching(~[(uint, variant, ~[(Option<ident>, @expr)])])
+    EnumNonMatching(~[(uint, ast::variant, ~[(Option<ident>, @expr)])]),
+
+    /// A static method where Self is a struct
+    StaticStruct(&'self ast::struct_def, Either<uint, ~[ident]>),
+    /// A static method where Self is an enum
+    StaticEnum(&'self ast::enum_def, ~[(ident, Either<uint, ~[ident]>)])
 }
 
 
+
 /**
 Combine the values of all the fields together. The last argument is
 all the fields of all the structures, see above for details.
@@ -225,31 +284,34 @@ pub type CombineSubstructureFunc<'self> =
     &'self fn(@ext_ctxt, span, &Substructure) -> @expr;
 
 /**
-Deal with non-matching enum variants, the argument is a list
+Deal with non-matching enum variants, the arguments are a list
 representing each variant: (variant index, ast::variant instance,
-[variant fields])
+[variant fields]), and a list of the nonself args of the type
 */
 pub type EnumNonMatchFunc<'self> =
-    &'self fn(@ext_ctxt, span, ~[(uint, variant, ~[(Option<ident>, @expr)])]) -> @expr;
-
+    &'self fn(@ext_ctxt, span,
+              ~[(uint, ast::variant,
+                 ~[(Option<ident>, @expr)])],
+              &[@expr]) -> @expr;
 
 
 impl<'self> TraitDef<'self> {
     fn create_derived_impl(&self, cx: @ext_ctxt, span: span,
                            type_ident: ident, generics: &Generics,
-                           methods: ~[@method]) -> @item {
-        let trait_path = build::mk_raw_path_global(
-            span,
-            do self.path.map |&s| { cx.ident_of(s) });
+                           methods: ~[@ast::method]) -> @ast::item {
+        let trait_path = self.path.to_path(cx, span, type_ident, generics);
+
+        let trait_generics = self.generics.to_generics(cx, span, type_ident, generics);
 
         let additional_bounds = opt_vec::from(
-            do self.additional_bounds.map |v| {
-                do v.map |&s| { cx.ident_of(s) }
+            do self.additional_bounds.map |p| {
+                p.to_path(cx, span, type_ident, generics)
             });
+
         create_derived_impl(cx, span,
                             type_ident, generics,
                             methods, trait_path,
-                            opt_vec::Empty,
+                            trait_generics,
                             additional_bounds)
     }
 
@@ -257,22 +319,28 @@ impl<'self> TraitDef<'self> {
                          span: span,
                          struct_def: &struct_def,
                          type_ident: ident,
-                         generics: &Generics)
-    -> @item {
-        let is_tuple = is_struct_tuple(struct_def);
-
+                         generics: &Generics) -> @ast::item {
         let methods = do self.methods.map |method_def| {
-            let body = if is_tuple {
-                method_def.expand_struct_tuple_method_body(cx, span,
-                                                           struct_def,
-                                                           type_ident)
+            let (self_ty, self_args, nonself_args, tys) =
+                method_def.split_self_nonself_args(cx, span, type_ident, generics);
+
+            let body = if method_def.is_static() {
+                method_def.expand_static_struct_method_body(
+                    cx, span,
+                    struct_def,
+                    type_ident,
+                    self_args, nonself_args)
             } else {
                 method_def.expand_struct_method_body(cx, span,
                                                      struct_def,
-                                                     type_ident)
+                                                     type_ident,
+                                                     self_args, nonself_args)
             };
 
-            method_def.create_method(cx, span, type_ident, generics, body)
+            method_def.create_method(cx, span,
+                                     type_ident, generics,
+                                     self_ty, tys,
+                                     body)
         };
 
         self.create_derived_impl(cx, span, type_ident, generics, methods)
@@ -282,13 +350,28 @@ impl<'self> TraitDef<'self> {
                        cx: @ext_ctxt, span: span,
                        enum_def: &enum_def,
                        type_ident: ident,
-                       generics: &Generics) -> @item {
+                       generics: &Generics) -> @ast::item {
         let methods = do self.methods.map |method_def| {
-            let body = method_def.expand_enum_method_body(cx, span,
-                                                          enum_def,
-                                                          type_ident);
+            let (self_ty, self_args, nonself_args, tys) =
+                method_def.split_self_nonself_args(cx, span, type_ident, generics);
 
-            method_def.create_method(cx, span, type_ident, generics, body)
+            let body = if method_def.is_static() {
+                method_def.expand_static_enum_method_body(
+                    cx, span,
+                    enum_def,
+                    type_ident,
+                    self_args, nonself_args)
+            } else {
+                method_def.expand_enum_method_body(cx, span,
+                                                   enum_def,
+                                                   type_ident,
+                                                   self_args, nonself_args)
+            };
+
+            method_def.create_method(cx, span,
+                                     type_ident, generics,
+                                     self_ty, tys,
+                                     body)
         };
 
         self.create_derived_impl(cx, span, type_ident, generics, methods)
@@ -300,266 +383,241 @@ impl<'self> MethodDef<'self> {
                                 cx: @ext_ctxt,
                                 span: span,
                                 type_ident: ident,
+                                self_args: &[@expr],
+                                nonself_args: &[@expr],
                                 fields: &SubstructureFields)
         -> @expr {
         let substructure = Substructure {
             type_ident: type_ident,
             method_ident: cx.ident_of(self.name),
+            self_args: self_args,
+            nonself_args: nonself_args,
             fields: fields
         };
         (self.combine_substructure)(cx, span,
                                     &substructure)
     }
 
-    fn get_output_type_path(&self, cx: @ext_ctxt, span: span,
-                              generics: &Generics, type_ident: ident) -> @ast::Path {
-        match self.output_type {
-            None => { // Self, add any type parameters
-                let out_ty_params = do vec::build |push| {
-                    for generics.ty_params.each |ty_param| {
-                        push(build::mk_ty_path(cx, span, ~[ ty_param.ident ]));
-                    }
-                };
+    fn get_ret_ty(&self, cx: @ext_ctxt, span: span,
+                     generics: &Generics, type_ident: ident) -> @ast::Ty {
+        self.ret_ty.to_ty(cx, span, type_ident, generics)
+    }
 
-                build::mk_raw_path_(span, ~[ type_ident ], out_ty_params)
+    fn is_static(&self) -> bool {
+        self.self_ty.is_none()
+    }
+
+    fn split_self_nonself_args(&self, cx: @ext_ctxt, span: span,
+                             type_ident: ident, generics: &Generics)
+        -> (ast::self_ty, ~[@expr], ~[@expr], ~[(ident, @ast::Ty)]) {
+
+        let mut self_args = ~[], nonself_args = ~[], arg_tys = ~[];
+        let mut ast_self_ty = respan(span, ast::sty_static);
+        let mut nonstatic = false;
+
+        match self.self_ty {
+            Some(self_ptr) => {
+                let (self_expr, self_ty) = ty::get_explicit_self(cx, span, self_ptr);
+
+                ast_self_ty = self_ty;
+                self_args.push(self_expr);
+                nonstatic = true;
             }
-            Some(str_path) => {
-                let p = do str_path.map |&s| { cx.ident_of(s) };
-                build::mk_raw_path_global(span, p)
+            _ => {}
+        }
+
+        for self.args.eachi |i, ty| {
+            let ast_ty = ty.to_ty(cx, span, type_ident, generics);
+            let ident = cx.ident_of(fmt!("__arg_%u", i));
+            arg_tys.push((ident, ast_ty));
+
+            let arg_expr = build::mk_path(cx, span, ~[ident]);
+
+            match *ty {
+                // for static methods, just treat any Self
+                // arguments as a normal arg
+                Self if nonstatic  => {
+                    self_args.push(arg_expr);
+                }
+                Ptr(~Self, _) if nonstatic => {
+                    self_args.push(build::mk_deref(cx, span, arg_expr))
+                }
+                _ => {
+                    nonself_args.push(arg_expr);
+                }
             }
         }
+
+        (ast_self_ty, self_args, nonself_args, arg_tys)
     }
 
     fn create_method(&self, cx: @ext_ctxt, span: span,
                      type_ident: ident,
-                     generics: &Generics, body: @expr) -> @method {
-        // Create the `Self` type of the `other` parameters.
-        let arg_path_type = create_self_type_with_params(cx,
-                                                         span,
-                                                         type_ident,
-                                                         generics);
-        let arg_type = ty_rptr(
-            None,
-            ast::mt { ty: arg_path_type, mutbl: m_imm }
-        );
-        let arg_type = @ast::Ty {
-            id: cx.next_id(),
-            node: arg_type,
-            span: span,
+                     generics: &Generics,
+                     self_ty: ast::self_ty,
+                     arg_types: ~[(ident, @ast::Ty)],
+                     body: @expr) -> @ast::method {
+        // create the generics that aren't for Self
+        let fn_generics = self.generics.to_generics(cx, span, type_ident, generics);
+
+        let args = do arg_types.map |&(id, ty)| {
+            build::mk_arg(cx, span, id, ty)
         };
 
-        // create the arguments
-        let other_idents = create_other_idents(cx, self.nargs);
-        let args = do other_idents.map |&id| {
-            build::mk_arg(cx, span, id, arg_type)
-        };
-
-        let output_type = self.get_output_type_path(cx, span, generics, type_ident);
-        let output_type = ty_path(output_type, cx.next_id());
-        let output_type = @ast::Ty {
-            id: cx.next_id(),
-            node: output_type,
-            span: span,
-        };
+        let ret_type = self.get_ret_ty(cx, span, generics, type_ident);
 
         let method_ident = cx.ident_of(self.name);
-        let fn_decl = build::mk_fn_decl(args, output_type);
+        let fn_decl = build::mk_fn_decl(args, ret_type);
         let body_block = build::mk_simple_block(cx, span, body);
 
+
         // Create the method.
-        let self_ty = respan(span, sty_region(None, m_imm));
         @ast::method {
             ident: method_ident,
             attrs: ~[],
-            generics: ast_util::empty_generics(),
+            generics: fn_generics,
             self_ty: self_ty,
-            purity: impure_fn,
+            purity: ast::impure_fn,
             decl: fn_decl,
             body: body_block,
             id: cx.next_id(),
             span: span,
             self_id: cx.next_id(),
-            vis: public
+            vis: ast::public
         }
     }
 
     /**
-    ```
+    ~~~
     #[deriving(Eq)]
-    struct A(int, int);
+    struct A { x: int, y: int }
 
     // equivalent to:
-
     impl Eq for A {
-        fn eq(&self, __other_1: &A) -> bool {
+        fn eq(&self, __arg_1: &A) -> bool {
             match *self {
-                (ref self_1, ref self_2) => {
-                    match *__other_1 {
-                        (ref __other_1_1, ref __other_1_2) => {
-                            self_1.eq(__other_1_1) && self_2.eq(__other_1_2)
+                A {x: ref __self_0_0, y: ref __self_0_1} => {
+                    match *__arg_1 {
+                        A {x: ref __self_1_0, y: ref __self_1_1} => {
+                            __self_0_0.eq(__self_1_0) && __self_0_1.eq(__self_1_1)
                         }
                     }
                 }
             }
         }
     }
-    ```
-    */
-    fn expand_struct_tuple_method_body(&self,
-                                           cx: @ext_ctxt,
-                                               span: span,
-                                               struct_def: &struct_def,
-                                           type_ident: ident) -> @expr {
-        let self_str = ~"self";
-        let other_strs = create_other_strs(self.nargs);
-        let num_fields = struct_def.fields.len();
-
-
-        let fields = do struct_def.fields.mapi |i, _| {
-            let other_fields = do other_strs.map |&other_str| {
-                let other_field_ident = cx.ident_of(fmt!("%s_%u", other_str, i));
-                build::mk_path(cx, span, ~[ other_field_ident ])
-            };
-
-            let self_field_ident = cx.ident_of(fmt!("%s_%u", self_str, i));
-            let self_field = build::mk_path(cx, span, ~[ self_field_ident ]);
-
-            (None, self_field, other_fields)
-        };
-
-        let mut match_body = self.call_substructure_method(cx, span, type_ident, &Struct(fields));
-
-        let type_path = build::mk_raw_path(span, ~[type_ident]);
-
-        // create the matches from inside to out (i.e. other_{self.nargs} to other_1)
-        for other_strs.each_reverse |&other_str| {
-            match_body = create_deref_match(cx, span, type_path,
-                                            other_str, num_fields,
-                                            match_body)
-        }
-
-        // create the match on self
-        return create_deref_match(cx, span, type_path,
-                                  ~"self", num_fields, match_body);
-
-        /**
-        Creates a match expression against a tuple that needs to
-        be dereferenced, but nothing else
-
-        ```
-        match *`to_match` {
-            (`to_match`_1, ..., `to_match`_`num_fields`) => `match_body`
-        }
-        ```
-        */
-        fn create_deref_match(cx: @ext_ctxt,
-                              span: span,
-                              type_path: @ast::Path,
-                              to_match: ~str,
-                              num_fields: uint,
-                              match_body: @expr) -> @expr {
-            let match_subpats = create_subpatterns(cx, span, to_match, num_fields);
-            let match_arm = ast::arm {
-                pats: ~[ build::mk_pat_enum(cx, span, type_path, match_subpats) ],
-                guard: None,
-                body: build::mk_simple_block(cx, span, match_body),
-            };
-
-            let deref_expr = build::mk_unary(cx, span, deref,
-                                             build::mk_path(cx, span,
-                                                            ~[ cx.ident_of(to_match)]));
-            let match_expr = build::mk_expr(cx, span, expr_match(deref_expr, ~[match_arm]));
-
-            match_expr
-        }
-    }
-
-    /**
-    ```
-    #[deriving(Eq)]
-    struct A { x: int, y: int }
-
-    // equivalent to:
-
-    impl Eq for A {
-        fn eq(&self, __other_1: &A) -> bool {
-            self.x.eq(&__other_1.x) &&
-                self.y.eq(&__other_1.y)
-        }
-    }
-    ```
+    ~~~
     */
     fn expand_struct_method_body(&self,
-                                     cx: @ext_ctxt,
-                                     span: span,
-                                     struct_def: &struct_def,
-                                     type_ident: ident)
+                                 cx: @ext_ctxt,
+                                 span: span,
+                                 struct_def: &struct_def,
+                                 type_ident: ident,
+                                 self_args: &[@expr],
+                                 nonself_args: &[@expr])
         -> @expr {
-        let self_ident = cx.ident_of(~"self");
-        let other_idents = create_other_idents(cx, self.nargs);
 
-        let fields = do struct_def.fields.map |struct_field| {
-            match struct_field.node.kind {
-                named_field(ident, _, _) => {
-                    // Create the accessor for this field in the other args.
-                    let other_fields = do other_idents.map |&id| {
-                        build::mk_access(cx, span, ~[id], ident)
-                    };
-                    let other_field_refs = do other_fields.map |&other_field| {
-                        build::mk_addr_of(cx, span, other_field)
-                    };
-
-                    // Create the accessor for this field in self.
-                    let self_field =
-                        build::mk_access(
-                            cx, span,
-                            ~[ self_ident ],
-                            ident);
-
-                    (Some(ident), self_field, other_field_refs)
-                }
-                unnamed_field => {
-                    cx.span_unimpl(span, ~"unnamed fields with `deriving_generic`");
-                }
-            }
+        let mut raw_fields = ~[], // ~[[fields of self], [fields of next Self arg], [etc]]
+                patterns = ~[];
+        for uint::range(0, self_args.len()) |i| {
+            let (pat, ident_expr) = create_struct_pattern(cx, span,
+                                                          type_ident, struct_def,
+                                                          fmt!("__self_%u", i), ast::m_imm);
+            patterns.push(pat);
+            raw_fields.push(ident_expr);
         };
 
-        self.call_substructure_method(cx, span, type_ident, &Struct(fields))
+        // transpose raw_fields
+        let fields = match raw_fields {
+            [self_arg, .. rest] => {
+                do self_arg.mapi |i, &(opt_id, field)| {
+                    let other_fields = do rest.map |l| {
+                        match &l[i] {
+                            &(_, ex) => ex
+                        }
+                    };
+                    (opt_id, field, other_fields)
+                }
+            }
+            [] => { cx.span_bug(span, ~"No self arguments to non-static \
+                                        method in generic `deriving`") }
+        };
+
+        // body of the inner most destructuring match
+        let mut body = self.call_substructure_method(
+            cx, span,
+            type_ident,
+            self_args,
+            nonself_args,
+            &Struct(fields));
+
+        // make a series of nested matches, to destructure the
+        // structs. This is actually right-to-left, but it shoudn't
+        // matter.
+        for vec::each2(self_args, patterns) |&arg_expr, &pat| {
+            let match_arm = ast::arm {
+                pats: ~[ pat ],
+                guard: None,
+                body: build::mk_simple_block(cx, span, body)
+            };
+
+            body = build::mk_expr(cx, span, ast::expr_match(arg_expr, ~[match_arm]))
+        }
+        body
+    }
+
+    fn expand_static_struct_method_body(&self,
+                                        cx: @ext_ctxt,
+                                        span: span,
+                                        struct_def: &struct_def,
+                                        type_ident: ident,
+                                        self_args: &[@expr],
+                                        nonself_args: &[@expr])
+        -> @expr {
+        let summary = summarise_struct(cx, span, struct_def);
+
+        self.call_substructure_method(cx, span,
+                                      type_ident,
+                                      self_args, nonself_args,
+                                      &StaticStruct(struct_def, summary))
     }
 
     /**
-    ```
+    ~~~
     #[deriving(Eq)]
     enum A {
         A1
         A2(int)
     }
 
-    // is equivalent to
+    // is equivalent to (with const_nonmatching == false)
 
     impl Eq for A {
-        fn eq(&self, __other_1: &A) {
+        fn eq(&self, __arg_1: &A) {
             match *self {
-                A1 => match *__other_1 {
-                    A1 => true,
-                    A2(ref __other_1_1) => false
+                A1 => match *__arg_1 {
+                    A1 => true
+                    A2(ref __arg_1_1) => false
                 },
-                A2(self_1) => match *__other_1 {
+                A2(self_1) => match *__arg_1 {
                     A1 => false,
-                    A2(ref __other_1_1) => self_1.eq(__other_1_1)
+                    A2(ref __arg_1_1) => self_1.eq(__arg_1_1)
                 }
             }
         }
     }
-    ```
+    ~~~
     */
     fn expand_enum_method_body(&self,
                                cx: @ext_ctxt,
                                span: span,
                                enum_def: &enum_def,
-                               type_ident: ident)
+                               type_ident: ident,
+                               self_args: &[@expr],
+                               nonself_args: &[@expr])
         -> @expr {
         self.build_enum_match(cx, span, enum_def, type_ident,
+                              self_args, nonself_args,
                               None, ~[], 0)
     }
 
@@ -567,13 +625,13 @@ impl<'self> MethodDef<'self> {
     /**
     Creates the nested matches for an enum definition recursively, i.e.
 
-    ```
+    ~~~
     match self {
        Variant1 => match other { Variant1 => matching, Variant2 => nonmatching, ... },
        Variant2 => match other { Variant1 => nonmatching, Variant2 => matching, ... },
        ...
     }
-    ```
+    ~~~
 
     It acts in the most naive way, so every branch (and subbranch,
     subsubbranch, etc) exists, not just the ones where all the variants in
@@ -589,15 +647,17 @@ impl<'self> MethodDef<'self> {
                         cx: @ext_ctxt, span: span,
                         enum_def: &enum_def,
                         type_ident: ident,
+                        self_args: &[@expr],
+                        nonself_args: &[@expr],
                         matching: Option<uint>,
-                        matches_so_far: ~[(uint, variant,
+                        matches_so_far: ~[(uint, ast::variant,
                                            ~[(Option<ident>, @expr)])],
                         match_count: uint) -> @expr {
-        if match_count == self.nargs + 1 {
+        if match_count == self_args.len() {
             // we've matched against all arguments, so make the final
             // expression at the bottom of the match tree
             match matches_so_far {
-                [] => cx.bug(~"no self match on an enum in `deriving_generic`"),
+                [] => cx.span_bug(span, ~"no self match on an enum in generic `deriving`"),
                 _ => {
                     // we currently have a vec of vecs, where each
                     // subvec is the fields of one of the arguments,
@@ -637,16 +697,17 @@ impl<'self> MethodDef<'self> {
                             substructure = EnumNonMatching(matches_so_far);
                         }
                     }
-                    self.call_substructure_method(cx, span, type_ident, &substructure)
+                    self.call_substructure_method(cx, span, type_ident,
+                                                  self_args, nonself_args,
+                                                  &substructure)
                 }
             }
 
         } else {  // there are still matches to create
-            let (current_match_ident, current_match_str) = if match_count == 0 {
-                (cx.ident_of(~"self"), ~"__self")
+            let current_match_str = if match_count == 0 {
+                ~"__self"
             } else {
-                let s = fmt!("__other_%u", matches_so_far.len() - 1);
-                (cx.ident_of(s), s)
+                fmt!("__arg_%u", match_count)
             };
 
             let mut arms = ~[];
@@ -654,80 +715,50 @@ impl<'self> MethodDef<'self> {
             // this is used as a stack
             let mut matches_so_far = matches_so_far;
 
-            macro_rules! mk_arm(
-                ($pat:expr, $expr:expr) => {
-                    {
-                        let blk = build::mk_simple_block(cx, span, $expr);
-                        let arm = ast::arm {
-                            pats: ~[$ pat ],
-                            guard: None,
-                            body: blk
-                        };
-                        arm
-                    }
-                }
-            )
-
             // the code for nonmatching variants only matters when
             // we've seen at least one other variant already
             if self.const_nonmatching && match_count > 0 {
                 // make a matching-variant match, and a _ match.
                 let index = match matching {
                     Some(i) => i,
-                    None => cx.span_bug(span, ~"Non-matching variants when required to\
-                                                be matching in `deriving_generic`")
+                    None => cx.span_bug(span, ~"Non-matching variants when required to \
+                                                be matching in generic `deriving`")
                 };
 
                 // matching-variant match
                 let variant = &enum_def.variants[index];
-                let pattern = create_enum_variant_pattern(cx, span,
-                                                          variant,
-                                                          current_match_str);
-
-                let idents = do vec::build |push| {
-                    for each_variant_arg_ident(cx, span, variant) |i, field_id| {
-                        let id = cx.ident_of(fmt!("%s_%u", current_match_str, i));
-                        push((field_id, build::mk_path(cx, span, ~[ id ])));
-                    }
-                };
+                let (pattern, idents) = create_enum_variant_pattern(cx, span,
+                                                                    variant,
+                                                                    current_match_str,
+                                                                    ast::m_imm);
 
                 matches_so_far.push((index, *variant, idents));
                 let arm_expr = self.build_enum_match(cx, span,
                                                      enum_def,
                                                      type_ident,
+                                                     self_args, nonself_args,
                                                      matching,
                                                      matches_so_far,
                                                      match_count + 1);
                 matches_so_far.pop();
-                let arm = mk_arm!(pattern, arm_expr);
-                arms.push(arm);
+                arms.push(build::mk_arm(cx, span, ~[ pattern ], arm_expr));
 
                 if enum_def.variants.len() > 1 {
-                    // _ match, if necessary
-                    let wild_pat = @ast::pat {
-                        id: cx.next_id(),
-                        node: pat_wild,
-                        span: span
-                    };
-
                     let wild_expr = self.call_substructure_method(cx, span, type_ident,
+                                                                  self_args, nonself_args,
                                                                   &EnumNonMatching(~[]));
-                    let wild_arm = mk_arm!(wild_pat, wild_expr);
+                    let wild_arm = build::mk_arm(cx, span,
+                                                 ~[ build::mk_pat_wild(cx, span) ],
+                                                 wild_expr);
                     arms.push(wild_arm);
                 }
             } else {
                 // create an arm matching on each variant
                 for enum_def.variants.eachi |index, variant| {
-                    let pattern = create_enum_variant_pattern(cx, span,
-                                                              variant,
-                                                              current_match_str);
-
-                    let idents = do vec::build |push| {
-                        for each_variant_arg_ident(cx, span, variant) |i, field_id| {
-                            let id = cx.ident_of(fmt!("%s_%u", current_match_str, i));
-                            push((field_id, build::mk_path(cx, span, ~[ id ])));
-                        }
-                    };
+                    let (pattern, idents) = create_enum_variant_pattern(cx, span,
+                                                                       variant,
+                                                                       current_match_str,
+                                                                       ast::m_imm);
 
                     matches_so_far.push((index, *variant, idents));
                     let new_matching =
@@ -739,44 +770,75 @@ impl<'self> MethodDef<'self> {
                     let arm_expr = self.build_enum_match(cx, span,
                                                          enum_def,
                                                          type_ident,
+                                                         self_args, nonself_args,
                                                          new_matching,
                                                          matches_so_far,
                                                          match_count + 1);
                     matches_so_far.pop();
 
-                    let arm = mk_arm!(pattern, arm_expr);
+                    let arm = build::mk_arm(cx, span, ~[ pattern ], arm_expr);
                     arms.push(arm);
                 }
             }
-            let deref_expr = build::mk_unary(cx, span, deref,
-                                             build::mk_path(cx, span,
-                                                            ~[ current_match_ident ]));
-            let match_expr = build::mk_expr(cx, span,
-                                            expr_match(deref_expr, arms));
 
-            match_expr
+            // match foo { arm, arm, arm, ... }
+            build::mk_expr(cx, span,
+                           ast::expr_match(self_args[match_count], arms))
         }
     }
+
+    fn expand_static_enum_method_body(&self,
+                               cx: @ext_ctxt,
+                               span: span,
+                               enum_def: &enum_def,
+                               type_ident: ident,
+                               self_args: &[@expr],
+                               nonself_args: &[@expr])
+        -> @expr {
+        let summary = do enum_def.variants.map |v| {
+            let ident = v.node.name;
+            let summary = match v.node.kind {
+                ast::tuple_variant_kind(ref args) => Left(args.len()),
+                ast::struct_variant_kind(struct_def) => {
+                    summarise_struct(cx, span, struct_def)
+                }
+            };
+            (ident, summary)
+        };
+        self.call_substructure_method(cx,
+                                      span, type_ident,
+                                      self_args, nonself_args,
+                                      &StaticEnum(enum_def, summary))
+    }
 }
 
-/// Create variable names (as strings) to refer to the non-self
-/// parameters
-fn create_other_strs(n: uint) -> ~[~str] {
-    do vec::build |push| {
-        for uint::range(0, n) |i| {
-            push(fmt!("__other_%u", i));
+fn summarise_struct(cx: @ext_ctxt, span: span,
+                    struct_def: &struct_def) -> Either<uint, ~[ident]> {
+    let mut named_idents = ~[];
+    let mut unnamed_count = 0;
+    for struct_def.fields.each |field| {
+        match field.node.kind {
+            ast::named_field(ident, _, _) => {
+                named_idents.push(ident)
+            }
+            ast::unnamed_field => {
+                unnamed_count += 1;
+            }
         }
     }
-}
-/// Like `create_other_strs`, but returns idents for the strings
-fn create_other_idents(cx: @ext_ctxt, n: uint) -> ~[ident] {
-    do create_other_strs(n).map |&s| {
-        cx.ident_of(s)
+
+    match (unnamed_count > 0, named_idents.is_empty()) {
+        (true, false) => cx.span_bug(span,
+                                     "A struct with named and unnamed \
+                                      fields in generic `deriving`"),
+        // named fields
+        (_, false) => Right(named_idents),
+        // tuple structs (includes empty structs)
+        (_, _)     => Left(unnamed_count)
     }
 }
 
 
-
 /* helpful premade recipes */
 
 /**
@@ -786,7 +848,7 @@ left-to-right (`true`) or right-to-left (`false`).
 pub fn cs_fold(use_foldl: bool,
                f: &fn(@ext_ctxt, span,
                       old: @expr,
-                      self_f: @expr, other_fs: ~[@expr]) -> @expr,
+                      self_f: @expr, other_fs: &[@expr]) -> @expr,
                base: @expr,
                enum_nonmatch_f: EnumNonMatchFunc,
                cx: @ext_ctxt, span: span,
@@ -803,7 +865,11 @@ pub fn cs_fold(use_foldl: bool,
                 }
             }
         },
-        EnumNonMatching(all_enums) => enum_nonmatch_f(cx, span, all_enums)
+        EnumNonMatching(all_enums) => enum_nonmatch_f(cx, span,
+                                                      all_enums, substructure.nonself_args),
+        StaticEnum(*) | StaticStruct(*) => {
+            cx.span_bug(span, "Static function in `deriving`")
+        }
     }
 }
 
@@ -812,11 +878,12 @@ pub fn cs_fold(use_foldl: bool,
 Call the method that is being derived on all the fields, and then
 process the collected results. i.e.
 
-```
-f(cx, span, ~[self_1.method(__other_1_1, __other_2_1),
-              self_2.method(__other_1_2, __other_2_2)])
-```
+~~~
+f(cx, span, ~[self_1.method(__arg_1_1, __arg_2_1),
+              self_2.method(__arg_1_2, __arg_2_2)])
+~~~
 */
+#[inline(always)]
 pub fn cs_same_method(f: &fn(@ext_ctxt, span, ~[@expr]) -> @expr,
                       enum_nonmatch_f: EnumNonMatchFunc,
                       cx: @ext_ctxt, span: span,
@@ -833,7 +900,11 @@ pub fn cs_same_method(f: &fn(@ext_ctxt, span, ~[@expr]) -> @expr,
 
             f(cx, span, called)
         },
-        EnumNonMatching(all_enums) => enum_nonmatch_f(cx, span, all_enums)
+        EnumNonMatching(all_enums) => enum_nonmatch_f(cx, span,
+                                                      all_enums, substructure.nonself_args),
+        StaticEnum(*) | StaticStruct(*) => {
+            cx.span_bug(span, "Static function in `deriving`")
+        }
     }
 }
 
@@ -842,6 +913,7 @@ Fold together the results of calling the derived method on all the
 fields. `use_foldl` controls whether this is done left-to-right
 (`true`) or right-to-left (`false`).
 */
+#[inline(always)]
 pub fn cs_same_method_fold(use_foldl: bool,
                            f: &fn(@ext_ctxt, span, @expr, @expr) -> @expr,
                            base: @expr,
@@ -869,7 +941,8 @@ pub fn cs_same_method_fold(use_foldl: bool,
 Use a given binop to combine the result of calling the derived method
 on all the fields.
 */
-pub fn cs_binop(binop: binop, base: @expr,
+#[inline(always)]
+pub fn cs_binop(binop: ast::binop, base: @expr,
                 enum_nonmatch_f: EnumNonMatchFunc,
                 cx: @ext_ctxt, span: span,
                 substructure: &Substructure) -> @expr {
@@ -887,18 +960,20 @@ pub fn cs_binop(binop: binop, base: @expr,
 }
 
 /// cs_binop with binop == or
+#[inline(always)]
 pub fn cs_or(enum_nonmatch_f: EnumNonMatchFunc,
              cx: @ext_ctxt, span: span,
              substructure: &Substructure) -> @expr {
-    cs_binop(or, build::mk_bool(cx, span, false),
+    cs_binop(ast::or, build::mk_bool(cx, span, false),
              enum_nonmatch_f,
              cx, span, substructure)
 }
 /// cs_binop with binop == and
+#[inline(always)]
 pub fn cs_and(enum_nonmatch_f: EnumNonMatchFunc,
               cx: @ext_ctxt, span: span,
               substructure: &Substructure) -> @expr {
-    cs_binop(and, build::mk_bool(cx, span, true),
+    cs_binop(ast::and, build::mk_bool(cx, span, true),
              enum_nonmatch_f,
              cx, span, substructure)
 }
diff --git a/src/libsyntax/ext/deriving/iter_bytes.rs b/src/libsyntax/ext/deriving/iter_bytes.rs
index f03306ea07a..c1c34c9a53a 100644
--- a/src/libsyntax/ext/deriving/iter_bytes.rs
+++ b/src/libsyntax/ext/deriving/iter_bytes.rs
@@ -1,4 +1,4 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,25 +8,37 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast;
-use ast::*;
+use ast::{meta_item, item, expr};
+use codemap::span;
 use ext::base::ext_ctxt;
 use ext::build;
-use ext::deriving::*;
-use codemap::{span, spanned};
-use ast_util;
-use opt_vec;
+use ext::deriving::generic::*;
 
 pub fn expand_deriving_iter_bytes(cx: @ext_ctxt,
                                   span: span,
-                                  _mitem: @meta_item,
-                                  in_items: ~[@item])
-                               -> ~[@item] {
-    expand_deriving(cx,
-                    span,
-                    in_items,
-                    expand_deriving_iter_bytes_struct_def,
-                    expand_deriving_iter_bytes_enum_def)
+                                  mitem: @meta_item,
+                                  in_items: ~[@item]) -> ~[@item] {
+    let trait_def = TraitDef {
+        path: Path::new(~[~"core", ~"to_bytes", ~"IterBytes"]),
+        additional_bounds: ~[],
+        generics: LifetimeBounds::empty(),
+        methods: ~[
+            MethodDef {
+                name: ~"iter_bytes",
+                generics: LifetimeBounds::empty(),
+                self_ty: borrowed_explicit_self(),
+                args: ~[
+                    Literal(Path::new(~[~"bool"])),
+                    Literal(Path::new(~[~"core", ~"to_bytes", ~"Cb"]))
+                ],
+                ret_ty: nil_ty(),
+                const_nonmatching: false,
+                combine_substructure: iter_bytes_substructure
+            }
+        ]
+    };
+
+    expand_deriving_generic(cx, span, mitem, in_items, &trait_def)
 }
 
 pub fn expand_deriving_obsolete(cx: @ext_ctxt,
@@ -39,217 +51,43 @@ pub fn expand_deriving_obsolete(cx: @ext_ctxt,
     in_items
 }
 
-fn create_derived_iter_bytes_impl(cx: @ext_ctxt,
-                                  span: span,
-                                  type_ident: ident,
-                                  generics: &Generics,
-                                  method: @method)
-                               -> @item {
-    let methods = [ method ];
-    let trait_path = ~[
-        cx.ident_of(~"core"),
-        cx.ident_of(~"to_bytes"),
-        cx.ident_of(~"IterBytes")
-    ];
-    let trait_path = build::mk_raw_path_global(span, trait_path);
-    create_derived_impl(cx, span, type_ident, generics, methods, trait_path,
-                        opt_vec::Empty, opt_vec::Empty)
-}
-
-// Creates a method from the given set of statements conforming to the
-// signature of the `iter_bytes` method.
-fn create_iter_bytes_method(cx: @ext_ctxt,
-                            span: span,
-                            statements: ~[@stmt])
-                         -> @method {
-    // Create the `lsb0` parameter.
-    let bool_ident = cx.ident_of(~"bool");
-    let lsb0_arg_type = build::mk_simple_ty_path(cx, span, bool_ident);
-    let lsb0_ident = cx.ident_of(~"__lsb0");
-    let lsb0_arg = build::mk_arg(cx, span, lsb0_ident, lsb0_arg_type);
-
-    // Create the `f` parameter.
-    let core_ident = cx.ident_of(~"core");
-    let to_bytes_ident = cx.ident_of(~"to_bytes");
-    let cb_ident = cx.ident_of(~"Cb");
-    let core_to_bytes_cb_ident = ~[ core_ident, to_bytes_ident, cb_ident ];
-    let f_arg_type = build::mk_ty_path(cx, span, core_to_bytes_cb_ident);
-    let f_ident = cx.ident_of(~"__f");
-    let f_arg = build::mk_arg(cx, span, f_ident, f_arg_type);
-
-    // Create the type of the return value.
-    let output_type = @ast::Ty { id: cx.next_id(), node: ty_nil, span: span };
-
-    // Create the function declaration.
-    let inputs = ~[ lsb0_arg, f_arg ];
-    let fn_decl = build::mk_fn_decl(inputs, output_type);
-
-    // Create the body block.
-    let body_block = build::mk_block_(cx, span, statements);
-
-    // Create the method.
-    let self_ty = spanned { node: sty_region(None, m_imm), span: span };
-    let method_ident = cx.ident_of(~"iter_bytes");
-    @ast::method {
-        ident: method_ident,
-        attrs: ~[],
-        generics: ast_util::empty_generics(),
-        self_ty: self_ty,
-        purity: impure_fn,
-        decl: fn_decl,
-        body: body_block,
-        id: cx.next_id(),
-        span: span,
-        self_id: cx.next_id(),
-        vis: public
-    }
-}
-
-fn call_substructure_iter_bytes_method(cx: @ext_ctxt,
-                                       span: span,
-                                       self_field: @expr)
-                                    -> @stmt {
-    // Gather up the parameters we want to chain along.
-    let lsb0_ident = cx.ident_of(~"__lsb0");
-    let f_ident = cx.ident_of(~"__f");
-    let lsb0_expr = build::mk_path(cx, span, ~[ lsb0_ident ]);
-    let f_expr = build::mk_path(cx, span, ~[ f_ident ]);
-
-    // Call the substructure method.
-    let iter_bytes_ident = cx.ident_of(~"iter_bytes");
-    let self_call = build::mk_method_call(cx,
-                                          span,
-                                          self_field,
-                                          iter_bytes_ident,
-                                          ~[ lsb0_expr, f_expr ]);
-
-    // Create a statement out of this expression.
-    build::mk_stmt(cx, span, self_call)
-}
-
-fn expand_deriving_iter_bytes_struct_def(cx: @ext_ctxt,
-                                         span: span,
-                                         struct_def: &struct_def,
-                                         type_ident: ident,
-                                         generics: &Generics)
-                                      -> @item {
-    // Create the method.
-    let method = expand_deriving_iter_bytes_struct_method(cx,
-                                                          span,
-                                                          struct_def);
-
-    // Create the implementation.
-    return create_derived_iter_bytes_impl(cx,
-                                          span,
-                                          type_ident,
-                                          generics,
-                                          method);
-}
-
-fn expand_deriving_iter_bytes_enum_def(cx: @ext_ctxt,
-                                       span: span,
-                                       enum_definition: &enum_def,
-                                       type_ident: ident,
-                                       generics: &Generics)
-                                    -> @item {
-    // Create the method.
-    let method = expand_deriving_iter_bytes_enum_method(cx,
-                                                        span,
-                                                        enum_definition);
-
-    // Create the implementation.
-    return create_derived_iter_bytes_impl(cx,
-                                          span,
-                                          type_ident,
-                                          generics,
-                                          method);
-}
-
-fn expand_deriving_iter_bytes_struct_method(cx: @ext_ctxt,
-                                            span: span,
-                                            struct_def: &struct_def)
-                                         -> @method {
-    let self_ident = cx.ident_of(~"self");
-
-    // Create the body of the method.
-    let mut statements = ~[];
-    for struct_def.fields.each |struct_field| {
-        match struct_field.node.kind {
-            named_field(ident, _, _) => {
-                // Create the accessor for this field.
-                let self_field = build::mk_access(cx,
-                                                  span,
-                                                  ~[ self_ident ],
-                                                  ident);
-
-                // Call the substructure method.
-                let stmt = call_substructure_iter_bytes_method(cx,
-                                                               span,
-                                                               self_field);
-                statements.push(stmt);
-            }
-            unnamed_field => {
-                cx.span_unimpl(span,
-                               ~"unnamed fields with `deriving(IterBytes)`");
-            }
-        }
-    }
-
-    // Create the method itself.
-    return create_iter_bytes_method(cx, span, statements);
-}
-
-fn expand_deriving_iter_bytes_enum_method(cx: @ext_ctxt,
-                                          span: span,
-                                          enum_definition: &enum_def)
-                                       -> @method {
-    // Create the arms of the match in the method body.
-    let arms = do enum_definition.variants.mapi |i, variant| {
-        // Create the matching pattern.
-        let pat = create_enum_variant_pattern(cx, span, variant, ~"__self");
-
-        // Determine the discriminant. We will feed this value to the byte
-        // iteration function.
-        let discriminant;
-        match variant.node.disr_expr {
-            Some(copy disr_expr) => discriminant = disr_expr,
-            None => discriminant = build::mk_uint(cx, span, i),
-        }
-
-        // Feed the discriminant to the byte iteration function.
-        let mut stmts = ~[];
-        let discrim_stmt = call_substructure_iter_bytes_method(cx,
-                                                               span,
-                                                               discriminant);
-        stmts.push(discrim_stmt);
-
-        // Feed each argument in this variant to the byte iteration function
-        // as well.
-        for uint::range(0, variant_arg_count(cx, span, variant)) |j| {
-            // Create the expression for this field.
-            let field_ident = cx.ident_of(~"__self_" + j.to_str());
-            let field = build::mk_path(cx, span, ~[ field_ident ]);
-
-            // Call the substructure method.
-            let stmt = call_substructure_iter_bytes_method(cx, span, field);
-            stmts.push(stmt);
-        }
-
-        // Create the pattern body.
-        let match_body_block = build::mk_block_(cx, span, stmts);
-
-        // Create the arm.
-        ast::arm {
-            pats: ~[ pat ],
-            guard: None,
-            body: match_body_block,
-        }
+fn iter_bytes_substructure(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr {
+    let lsb0_f = match substr.nonself_args {
+        [l, f] => ~[l, f],
+        _ => cx.span_bug(span, "Incorrect number of arguments in `deriving(IterBytes)`")
     };
+    let iter_bytes_ident = substr.method_ident;
+    let call_iterbytes = |thing_expr| {
+        build::mk_stmt(
+            cx, span,
+            build::mk_method_call(cx, span,
+                                  thing_expr, iter_bytes_ident,
+                                  copy lsb0_f))
+    };
+    let mut stmts = ~[];
+    let fields;
+    match *substr.fields {
+        Struct(ref fs) => {
+            fields = fs
+        }
+        EnumMatching(copy index, ref variant, ref fs) => {
+            // Determine the discriminant. We will feed this value to the byte
+            // iteration function.
+            let discriminant = match variant.node.disr_expr {
+                Some(copy d)=> d,
+                None => build::mk_uint(cx, span, index)
+            };
 
-    // Create the method body.
-    let self_match_expr = expand_enum_or_struct_match(cx, span, arms);
-    let self_match_stmt = build::mk_stmt(cx, span, self_match_expr);
+            stmts.push(call_iterbytes(discriminant));
 
-    // Create the method.
-    create_iter_bytes_method(cx, span, ~[ self_match_stmt ])
-}
+            fields = fs;
+        }
+        _ => cx.span_bug(span, "Impossible substructure in `deriving(IterBytes)`")
+    }
+
+    for fields.each |&(_, field, _)| {
+        stmts.push(call_iterbytes(field));
+    }
+
+    build::mk_block(cx, span, ~[], stmts, None)
+}
\ No newline at end of file
diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs
index 5aeeef2b17a..d48ff98be06 100644
--- a/src/libsyntax/ext/deriving/mod.rs
+++ b/src/libsyntax/ext/deriving/mod.rs
@@ -12,14 +12,7 @@
 /// #[deriving(IterBytes)] extensions.
 
 use ast;
-use ast::{Ty, bind_by_ref, deref, enum_def};
-use ast::{expr, expr_match, ident, item, item_};
-use ast::{item_enum, item_impl, item_struct, Generics};
-use ast::{m_imm, meta_item, method};
-use ast::{named_field, pat, pat_ident, public};
-use ast::{struct_def, struct_variant_kind};
-use ast::{tuple_variant_kind};
-use ast::{ty_path, unnamed_field, variant};
+use ast::{Ty, enum_def, expr, ident, item, Generics, meta_item, struct_def};
 use ext::base::ext_ctxt;
 use ext::build;
 use codemap::{span, respan};
@@ -30,6 +23,8 @@ pub mod clone;
 pub mod iter_bytes;
 pub mod encodable;
 pub mod decodable;
+pub mod rand;
+pub mod to_str;
 
 #[path="cmp/eq.rs"]
 pub mod eq;
@@ -78,23 +73,25 @@ pub fn expand_meta_deriving(cx: @ext_ctxt,
                     meta_name_value(tname, _) |
                     meta_list(tname, _) |
                     meta_word(tname) => {
+                        macro_rules! expand(($func:path) => ($func(cx, titem.span,
+                                                                   titem, in_items)));
                         match *tname {
-                            ~"Clone" => clone::expand_deriving_clone(cx,
-                                titem.span, titem, in_items),
-                            ~"IterBytes" => iter_bytes::expand_deriving_iter_bytes(cx,
-                                titem.span, titem, in_items),
-                            ~"Encodable" => encodable::expand_deriving_encodable(cx,
-                                titem.span, titem, in_items),
-                            ~"Decodable" => decodable::expand_deriving_decodable(cx,
-                                titem.span, titem, in_items),
-                            ~"Eq" => eq::expand_deriving_eq(cx, titem.span,
-                                                             titem, in_items),
-                            ~"TotalEq" => totaleq::expand_deriving_totaleq(cx, titem.span,
-                                                                           titem, in_items),
-                            ~"Ord" => ord::expand_deriving_ord(cx, titem.span,
-                                                               titem, in_items),
-                            ~"TotalOrd" => totalord::expand_deriving_totalord(cx, titem.span,
-                                                                              titem, in_items),
+                            ~"Clone" => expand!(clone::expand_deriving_clone),
+
+                            ~"IterBytes" => expand!(iter_bytes::expand_deriving_iter_bytes),
+
+                            ~"Encodable" => expand!(encodable::expand_deriving_encodable),
+                            ~"Decodable" => expand!(decodable::expand_deriving_decodable),
+
+                            ~"Eq" => expand!(eq::expand_deriving_eq),
+                            ~"TotalEq" => expand!(totaleq::expand_deriving_totaleq),
+                            ~"Ord" => expand!(ord::expand_deriving_ord),
+                            ~"TotalOrd" => expand!(totalord::expand_deriving_totalord),
+
+                            ~"Rand" => expand!(rand::expand_deriving_rand),
+
+                            ~"ToStr" => expand!(to_str::expand_deriving_to_str),
+
                             tname => {
                                 cx.span_err(titem.span, fmt!("unknown \
                                     `deriving` trait: `%s`", tname));
@@ -118,14 +115,14 @@ pub fn expand_deriving(cx: @ext_ctxt,
     for in_items.each |item| {
         result.push(copy *item);
         match item.node {
-            item_struct(struct_def, ref generics) => {
+            ast::item_struct(struct_def, ref generics) => {
                 result.push(expand_deriving_struct_def(cx,
                                                        span,
                                                        struct_def,
                                                        item.ident,
                                                        generics));
             }
-            item_enum(ref enum_definition, ref generics) => {
+            ast::item_enum(ref enum_definition, ref generics) => {
                 result.push(expand_deriving_enum_def(cx,
                                                      span,
                                                      enum_definition,
@@ -138,7 +135,7 @@ pub fn expand_deriving(cx: @ext_ctxt,
     result
 }
 
-fn create_impl_item(cx: @ext_ctxt, span: span, item: item_) -> @item {
+fn create_impl_item(cx: @ext_ctxt, span: span, item: ast::item_) -> @item {
     let doc_attr = respan(span,
                           ast::lit_str(@~"Automatically derived."));
     let doc_attr = respan(span, ast::meta_name_value(@~"doc", doc_attr));
@@ -154,7 +151,7 @@ fn create_impl_item(cx: @ext_ctxt, span: span, item: item_) -> @item {
         attrs: ~[doc_attr],
         id: cx.next_id(),
         node: item,
-        vis: public,
+        vis: ast::public,
         span: span,
     }
 }
@@ -173,22 +170,29 @@ pub fn create_self_type_with_params(cx: @ext_ctxt,
         self_ty_params.push(self_ty_param);
     }
 
+    let lifetime = if generics.lifetimes.is_empty() {
+        None
+    } else {
+        Some(@*generics.lifetimes.get(0))
+    };
+
+
     // Create the type of `self`.
     let self_type = build::mk_raw_path_(span,
                                         ~[ type_ident ],
+                                        lifetime,
                                         self_ty_params);
-    let self_type = ty_path(self_type, cx.next_id());
-    @ast::Ty { id: cx.next_id(), node: self_type, span: span }
+    build::mk_ty_path_path(cx, span, self_type)
 }
 
 pub fn create_derived_impl(cx: @ext_ctxt,
                            span: span,
                            type_ident: ident,
                            generics: &Generics,
-                           methods: &[@method],
+                           methods: &[@ast::method],
                            trait_path: @ast::Path,
-                           mut impl_ty_params: opt_vec::OptVec<ast::TyParam>,
-                           bounds_paths: opt_vec::OptVec<~[ident]>)
+                           mut impl_generics:  Generics,
+                           bounds_paths: opt_vec::OptVec<@ast::Path>)
                         -> @item {
     /*!
      *
@@ -204,21 +208,22 @@ pub fn create_derived_impl(cx: @ext_ctxt,
      */
 
     // Copy the lifetimes
-    let impl_lifetimes = generics.lifetimes.map(|l| {
-        build::mk_lifetime(cx, l.span, l.ident)
-    });
+    for generics.lifetimes.each |l| {
+        impl_generics.lifetimes.push(copy *l)
+    };
 
     // Create the type parameters.
     for generics.ty_params.each |ty_param| {
+        // extra restrictions on the generics parameters to the type being derived upon
         let mut bounds = do bounds_paths.map |&bound_path| {
-            build::mk_trait_ty_param_bound_global(cx, span, bound_path)
+            build::mk_trait_ty_param_bound_(cx, bound_path)
         };
 
         let this_trait_bound =
             build::mk_trait_ty_param_bound_(cx, trait_path);
         bounds.push(this_trait_bound);
 
-        impl_ty_params.push(build::mk_ty_param(cx, ty_param.ident, @bounds));
+        impl_generics.ty_params.push(build::mk_ty_param(cx, ty_param.ident, @bounds));
     }
 
     // Create the reference to the trait.
@@ -231,8 +236,7 @@ pub fn create_derived_impl(cx: @ext_ctxt,
                                                  generics);
 
     // Create the impl item.
-    let impl_item = item_impl(Generics {lifetimes: impl_lifetimes,
-                                        ty_params: impl_ty_params},
+    let impl_item = ast::item_impl(impl_generics,
                               Some(trait_ref),
                               self_type,
                               methods.map(|x| *x));
@@ -240,106 +244,128 @@ pub fn create_derived_impl(cx: @ext_ctxt,
 }
 
 pub fn create_subpatterns(cx: @ext_ctxt,
-                      span: span,
-                      prefix: ~str,
-                      n: uint)
-                   -> ~[@pat] {
-    let mut subpats = ~[];
-    for uint::range(0, n) |_i| {
-        // Create the subidentifier.
-        let index = subpats.len();
-        let ident = cx.ident_of(fmt!("%s_%u", prefix, index));
-
-        // Create the subpattern.
-        let subpath = build::mk_raw_path(span, ~[ ident ]);
-        let subpat = pat_ident(bind_by_ref(m_imm), subpath, None);
-        let subpat = build::mk_pat(cx, span, subpat);
-        subpats.push(subpat);
+                          span: span,
+                          field_paths: ~[@ast::Path],
+                          mutbl: ast::mutability)
+                   -> ~[@ast::pat] {
+    do field_paths.map |&path| {
+        build::mk_pat(cx, span,
+                      ast::pat_ident(ast::bind_by_ref(mutbl), path, None))
     }
-    return subpats;
 }
 
-pub fn is_struct_tuple(struct_def: &struct_def) -> bool {
-    struct_def.fields.len() > 0 && struct_def.fields.all(|f| {
-        match f.node.kind {
-            named_field(*) => false,
-            unnamed_field => true
-        }
-    })
+#[deriving(Eq)] // dogfooding!
+enum StructType {
+    Unknown, Record, Tuple
+}
+
+pub fn create_struct_pattern(cx: @ext_ctxt,
+                             span: span,
+                             struct_ident: ident,
+                             struct_def: &struct_def,
+                             prefix: ~str,
+                             mutbl: ast::mutability)
+    -> (@ast::pat, ~[(Option<ident>, @expr)]) {
+    if struct_def.fields.is_empty() {
+        return (
+            build::mk_pat_ident_with_binding_mode(
+                cx, span, struct_ident, ast::bind_infer),
+            ~[]);
+    }
+
+    let matching_path = build::mk_raw_path(span, ~[ struct_ident ]);
+
+    let mut paths = ~[], ident_expr = ~[];
+
+    let mut struct_type = Unknown;
+
+    for struct_def.fields.eachi |i, struct_field| {
+        let opt_id = match struct_field.node.kind {
+            ast::named_field(ident, _, _) if (struct_type == Unknown ||
+                                              struct_type == Record) => {
+                struct_type = Record;
+                Some(ident)
+            }
+            ast::unnamed_field if (struct_type == Unknown ||
+                                   struct_type == Tuple) => {
+                struct_type = Tuple;
+                None
+            }
+            _ => {
+                cx.span_bug(span, "A struct with named and unnamed fields in `deriving`");
+            }
+        };
+        let path = build::mk_raw_path(span,
+                                      ~[ cx.ident_of(fmt!("%s_%u", prefix, i)) ]);
+        paths.push(path);
+        ident_expr.push((opt_id, build::mk_path_raw(cx, span, path)));
+    }
+
+    let subpats = create_subpatterns(cx, span, paths, mutbl);
+
+    // struct_type is definitely not Unknown, since struct_def.fields
+    // must be nonempty to reach here
+    let pattern = if struct_type == Record {
+        let field_pats = do vec::build |push| {
+            for vec::each2(subpats, ident_expr) |&pat, &(id, _)| {
+                // id is guaranteed to be Some
+                push(ast::field_pat { ident: id.get(), pat: pat })
+            }
+        };
+        build::mk_pat_struct(cx, span, matching_path, field_pats)
+    } else {
+        build::mk_pat_enum(cx, span, matching_path, subpats)
+    };
+
+    (pattern, ident_expr)
 }
 
 pub fn create_enum_variant_pattern(cx: @ext_ctxt,
-                               span: span,
-                               variant: &variant,
-                               prefix: ~str)
-                            -> @pat {
+                                   span: span,
+                                   variant: &ast::variant,
+                                   prefix: ~str,
+                                   mutbl: ast::mutability)
+    -> (@ast::pat, ~[(Option<ident>, @expr)]) {
+
     let variant_ident = variant.node.name;
     match variant.node.kind {
-        tuple_variant_kind(ref variant_args) => {
-            if variant_args.len() == 0 {
-                return build::mk_pat_ident_with_binding_mode(
-                    cx, span, variant_ident, ast::bind_infer);
+        ast::tuple_variant_kind(ref variant_args) => {
+            if variant_args.is_empty() {
+                return (build::mk_pat_ident_with_binding_mode(
+                    cx, span, variant_ident, ast::bind_infer), ~[]);
             }
 
             let matching_path = build::mk_raw_path(span, ~[ variant_ident ]);
-            let subpats = create_subpatterns(cx,
-                                             span,
-                                             prefix,
-                                             variant_args.len());
 
-            return build::mk_pat_enum(cx, span, matching_path, subpats);
-        }
-        struct_variant_kind(struct_def) => {
-            let matching_path = build::mk_raw_path(span, ~[ variant_ident ]);
-            let subpats = create_subpatterns(cx,
-                                             span,
-                                             prefix,
-                                             struct_def.fields.len());
+            let mut paths = ~[], ident_expr = ~[];
+            for uint::range(0, variant_args.len()) |i| {
+                let path = build::mk_raw_path(span,
+                                              ~[ cx.ident_of(fmt!("%s_%u", prefix, i)) ]);
 
-            let field_pats = do struct_def.fields.mapi |i, struct_field| {
-                let ident = match struct_field.node.kind {
-                    named_field(ident, _, _) => ident,
-                    unnamed_field => {
-                        cx.span_bug(span, ~"unexpected unnamed field");
-                    }
-                };
-                ast::field_pat { ident: ident, pat: subpats[i] }
-            };
-
-            build::mk_pat_struct(cx, span, matching_path, field_pats)
-        }
-    }
-}
-
-pub fn variant_arg_count(_cx: @ext_ctxt, _span: span, variant: &variant) -> uint {
-    match variant.node.kind {
-        tuple_variant_kind(ref args) => args.len(),
-        struct_variant_kind(ref struct_def) => struct_def.fields.len(),
-    }
-}
-
-/// Iterate through the idents of the variant arguments. The field is
-/// unnamed (i.e. it's not a struct-like enum), then `None`.
-pub fn each_variant_arg_ident(_cx: @ext_ctxt, _span: span,
-                              variant: &variant, it: &fn(uint, Option<ident>) -> bool) {
-    match variant.node.kind {
-        tuple_variant_kind(ref args) => {
-            for uint::range(0, args.len()) |i| {
-                if !it(i, None) { break }
+                paths.push(path);
+                ident_expr.push((None, build::mk_path_raw(cx, span, path)));
             }
+
+            let subpats = create_subpatterns(cx, span, paths, mutbl);
+
+            (build::mk_pat_enum(cx, span, matching_path, subpats),
+             ident_expr)
         }
-        struct_variant_kind(ref struct_def) => {
-            for struct_def.fields.eachi |i, f| {
-                let id = match f.node.kind {
-                    named_field(ident, _, _) => Some(ident),
-                    unnamed_field => None
-                };
-                if !it(i, id) { break }
-            }
+        ast::struct_variant_kind(struct_def) => {
+            create_struct_pattern(cx, span,
+                                  variant_ident, struct_def,
+                                  prefix,
+                                  mutbl)
         }
     }
 }
 
+pub fn variant_arg_count(_cx: @ext_ctxt, _span: span, variant: &ast::variant) -> uint {
+    match variant.node.kind {
+        ast::tuple_variant_kind(ref args) => args.len(),
+        ast::struct_variant_kind(ref struct_def) => struct_def.fields.len(),
+    }
+}
 
 pub fn expand_enum_or_struct_match(cx: @ext_ctxt,
                                span: span,
@@ -347,7 +373,7 @@ pub fn expand_enum_or_struct_match(cx: @ext_ctxt,
                             -> @expr {
     let self_ident = cx.ident_of(~"self");
     let self_expr = build::mk_path(cx, span, ~[ self_ident ]);
-    let self_expr = build::mk_unary(cx, span, deref, self_expr);
-    let self_match_expr = expr_match(self_expr, arms);
+    let self_expr = build::mk_unary(cx, span, ast::deref, self_expr);
+    let self_match_expr = ast::expr_match(self_expr, arms);
     build::mk_expr(cx, span, self_match_expr)
 }
diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs
new file mode 100644
index 00000000000..03202801d20
--- /dev/null
+++ b/src/libsyntax/ext/deriving/rand.rs
@@ -0,0 +1,136 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ast;
+use ast::{meta_item, item, expr, ident};
+use codemap::span;
+use ext::base::ext_ctxt;
+use ext::build;
+use ext::deriving::generic::*;
+
+pub fn expand_deriving_rand(cx: @ext_ctxt,
+                            span: span,
+                            mitem: @meta_item,
+                            in_items: ~[@item])
+    -> ~[@item] {
+    let trait_def = TraitDef {
+        path: Path::new(~[~"core", ~"rand", ~"Rand"]),
+        additional_bounds: ~[],
+        generics: LifetimeBounds::empty(),
+        methods: ~[
+            MethodDef {
+                name: ~"rand",
+                generics: LifetimeBounds {
+                    lifetimes: ~[],
+                    bounds: ~[(~"R",
+                               ~[ Path::new(~[~"core", ~"rand", ~"Rng"]) ])]
+                },
+                self_ty: None,
+                args: ~[
+                    Ptr(~Literal(Path::new_local(~"R")),
+                        Borrowed(None, ast::m_imm))
+                ],
+                ret_ty: Self,
+                const_nonmatching: false,
+                combine_substructure: rand_substructure
+            }
+        ]
+    };
+
+    expand_deriving_generic(cx, span, mitem, in_items, &trait_def)
+}
+
+fn rand_substructure(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr {
+    let rng = match substr.nonself_args {
+        [rng] => ~[ rng ],
+        _ => cx.bug("Incorrect number of arguments to `rand` in `deriving(Rand)`")
+    };
+    let rand_ident = ~[
+        cx.ident_of(~"core"),
+        cx.ident_of(~"rand"),
+        cx.ident_of(~"Rand"),
+        cx.ident_of(~"rand")
+    ];
+    let rand_call = || {
+        build::mk_call_global(cx, span,
+                              copy rand_ident, copy rng)
+    };
+
+    return match *substr.fields {
+        StaticStruct(_, ref summary) => {
+            rand_thing(cx, span, substr.type_ident, summary, rand_call)
+        }
+        StaticEnum(_, ref variants) => {
+            if variants.is_empty() {
+                cx.span_fatal(span, "`Rand` cannot be derived for enums with no variants");
+            }
+
+            let variant_count = build::mk_uint(cx, span, variants.len());
+
+            // need to specify the uint-ness of the random number
+            let u32_ty = build::mk_ty_path(cx, span, ~[cx.ident_of(~"uint")]);
+            let r_ty = build::mk_ty_path(cx, span, ~[cx.ident_of(~"R")]);
+            let rand_name = build::mk_raw_path_(span, copy rand_ident, None, ~[ u32_ty, r_ty ]);
+            let rand_name = build::mk_path_raw(cx, span, rand_name);
+
+            let rv_call = build::mk_call_(cx, span, rand_name, copy rng);
+
+            // rand() % variants.len()
+            let rand_variant = build::mk_binary(cx, span, ast::rem,
+                                                rv_call, variant_count);
+
+            let mut arms = do variants.mapi |i, id_sum| {
+                let i_expr = build::mk_uint(cx, span, i);
+                let pat = build::mk_pat_lit(cx, span, i_expr);
+
+                match *id_sum {
+                    (ident, ref summary) => {
+                        build::mk_arm(cx, span,
+                                      ~[ pat ],
+                                      rand_thing(cx, span, ident, summary, rand_call))
+                    }
+                }
+            };
+
+            // _ => {} at the end. Should never occur
+            arms.push(build::mk_unreachable_arm(cx, span));
+
+            build::mk_expr(cx, span,
+                           ast::expr_match(rand_variant, arms))
+        }
+        _ => cx.bug("Non-static method in `deriving(Rand)`")
+    };
+
+    fn rand_thing(cx: @ext_ctxt, span: span,
+                  ctor_ident: ident,
+                  summary: &Either<uint, ~[ident]>,
+                  rand_call: &fn() -> @expr) -> @expr {
+        let ctor_ident = ~[ ctor_ident ];
+        match *summary {
+            Left(copy count) => {
+                if count == 0 {
+                    build::mk_path(cx, span, ctor_ident)
+                } else {
+                    let exprs = vec::from_fn(count, |_| rand_call());
+                    build::mk_call(cx, span, ctor_ident, exprs)
+                }
+            }
+            Right(ref fields) => {
+                let rand_fields = do fields.map |ident| {
+                    build::Field {
+                        ident: *ident,
+                        ex: rand_call()
+                    }
+                };
+                build::mk_struct_e(cx, span, ctor_ident, rand_fields)
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/libsyntax/ext/deriving/to_str.rs b/src/libsyntax/ext/deriving/to_str.rs
new file mode 100644
index 00000000000..2c7d449585f
--- /dev/null
+++ b/src/libsyntax/ext/deriving/to_str.rs
@@ -0,0 +1,54 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ast::{meta_item, item, expr};
+use codemap::span;
+use ext::base::ext_ctxt;
+use ext::build;
+use ext::deriving::generic::*;
+
+pub fn expand_deriving_to_str(cx: @ext_ctxt,
+                              span: span,
+                              mitem: @meta_item,
+                              in_items: ~[@item])
+    -> ~[@item] {
+    let trait_def = TraitDef {
+        path: Path::new(~[~"core", ~"to_str", ~"ToStr"]),
+        additional_bounds: ~[],
+        generics: LifetimeBounds::empty(),
+        methods: ~[
+            MethodDef {
+                name: ~"to_str",
+                generics: LifetimeBounds::empty(),
+                self_ty: borrowed_explicit_self(),
+                args: ~[],
+                ret_ty: Ptr(~Literal(Path::new_local(~"str")), Owned),
+                const_nonmatching: false,
+                combine_substructure: to_str_substructure
+            }
+        ]
+    };
+
+    expand_deriving_generic(cx, span, mitem, in_items, &trait_def)
+}
+
+fn to_str_substructure(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr {
+    match substr.self_args {
+        [self_obj] => {
+            let self_addr = build::mk_addr_of(cx, span, self_obj);
+            build::mk_call_global(cx, span,
+                                  ~[cx.ident_of(~"core"),
+                                    cx.ident_of(~"sys"),
+                                    cx.ident_of(~"log_str")],
+                                  ~[self_addr])
+        }
+        _ => cx.span_bug(span, ~"Invalid number of arguments in `deriving(ToStr)`")
+    }
+}
\ No newline at end of file
diff --git a/src/libsyntax/ext/deriving/ty.rs b/src/libsyntax/ext/deriving/ty.rs
new file mode 100644
index 00000000000..6195a3a6424
--- /dev/null
+++ b/src/libsyntax/ext/deriving/ty.rs
@@ -0,0 +1,242 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+A mini version of ast::Ty, which is easier to use, and features an
+explicit `Self` type to use when specifying impls to be derived.
+*/
+
+use ast;
+use ast::{expr,Generics,ident};
+use ext::base::ext_ctxt;
+use ext::build;
+use codemap::{span,respan};
+use opt_vec;
+
+/// The types of pointers
+#[deriving(Eq)]
+pub enum PtrTy {
+    Owned, // ~
+    Managed(ast::mutability), // @[mut]
+    Borrowed(Option<~str>, ast::mutability), // &['lifetime] [mut]
+}
+
+/// A path, e.g. `::core::option::Option::<int>` (global). Has support
+/// for type parameters and a lifetime.
+#[deriving(Eq)]
+pub struct Path {
+    path: ~[~str],
+    lifetime: Option<~str>,
+    params: ~[~Ty],
+    global: bool
+}
+
+pub impl Path {
+    fn new(path: ~[~str]) -> Path {
+        Path::new_(path, None, ~[], true)
+    }
+    fn new_local(path: ~str) -> Path {
+        Path::new_(~[ path ], None, ~[], false)
+    }
+    fn new_(path: ~[~str], lifetime: Option<~str>, params: ~[~Ty], global: bool) -> Path {
+        Path {
+            path: path,
+            lifetime: lifetime,
+            params: params,
+            global: global
+        }
+    }
+
+    fn to_ty(&self, cx: @ext_ctxt, span: span,
+             self_ty: ident, self_generics: &Generics) -> @ast::Ty {
+                build::mk_ty_path_path(cx, span,
+                                       self.to_path(cx, span,
+                                                    self_ty, self_generics))
+    }
+    fn to_path(&self, cx: @ext_ctxt, span: span,
+               self_ty: ident, self_generics: &Generics) -> @ast::Path {
+        let idents = self.path.map(|s| cx.ident_of(*s) );
+        let lt = mk_lifetime(cx, span, self.lifetime);
+        let tys = self.params.map(|t| t.to_ty(cx, span, self_ty, self_generics));
+
+        if self.global {
+            build::mk_raw_path_global_(span, idents, lt, tys)
+        } else {
+            build::mk_raw_path_(span, idents, lt, tys)
+        }
+    }
+}
+
+/// A type. Supports pointers (except for *), Self, and literals
+#[deriving(Eq)]
+pub enum Ty {
+    Self,
+    // &/~/@ Ty
+    Ptr(~Ty, PtrTy),
+    // mod::mod::Type<[lifetime], [Params...]>, including a plain type
+    // parameter, and things like `int`
+    Literal(Path),
+    // includes nil
+    Tuple(~[Ty])
+}
+
+pub fn borrowed_ptrty() -> PtrTy {
+    Borrowed(None, ast::m_imm)
+}
+pub fn borrowed(ty: ~Ty) -> Ty {
+    Ptr(ty, borrowed_ptrty())
+}
+
+pub fn borrowed_explicit_self() -> Option<Option<PtrTy>> {
+    Some(Some(borrowed_ptrty()))
+}
+
+pub fn borrowed_self() -> Ty {
+    borrowed(~Self)
+}
+
+pub fn nil_ty() -> Ty {
+    Tuple(~[])
+}
+
+fn mk_lifetime(cx: @ext_ctxt, span: span, lt: Option<~str>) -> Option<@ast::Lifetime> {
+    match lt {
+        Some(s) => Some(@build::mk_lifetime(cx, span, cx.ident_of(s))),
+        None => None
+    }
+}
+
+pub impl Ty {
+    fn to_ty(&self, cx: @ext_ctxt, span: span,
+             self_ty: ident, self_generics: &Generics) -> @ast::Ty {
+        match *self {
+            Ptr(ref ty, ref ptr) => {
+                let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
+                match *ptr {
+                    Owned => {
+                        build::mk_ty_uniq(cx, span, raw_ty)
+                    }
+                    Managed(copy mutbl) => {
+                        build::mk_ty_box(cx, span, raw_ty, mutbl)
+                    }
+                    Borrowed(copy lt, copy mutbl) => {
+                        let lt = mk_lifetime(cx, span, lt);
+                        build::mk_ty_rptr(cx, span, raw_ty, lt, mutbl)
+                    }
+                }
+            }
+            Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) }
+            Self  => {
+                build::mk_ty_path_path(cx, span, self.to_path(cx, span, self_ty, self_generics))
+            }
+            Tuple(ref fields) => {
+                let ty = if fields.is_empty() {
+                    ast::ty_nil
+                } else {
+                    ast::ty_tup(fields.map(|f| f.to_ty(cx, span, self_ty, self_generics)))
+                };
+
+                build::mk_ty(cx, span, ty)
+            }
+        }
+    }
+
+    fn to_path(&self, cx: @ext_ctxt, span: span,
+               self_ty: ident, self_generics: &Generics) -> @ast::Path {
+        match *self {
+            Self => {
+                let self_params = do self_generics.ty_params.map |ty_param| {
+                    build::mk_ty_path(cx, span, ~[ ty_param.ident ])
+                };
+                let lifetime = if self_generics.lifetimes.is_empty() {
+                    None
+                } else {
+                    Some(@*self_generics.lifetimes.get(0))
+                };
+
+                build::mk_raw_path_(span, ~[self_ty], lifetime,
+                                    opt_vec::take_vec(self_params))
+            }
+            Literal(ref p) => {
+                p.to_path(cx, span, self_ty, self_generics)
+            }
+            Ptr(*) => { cx.span_bug(span, ~"Pointer in a path in generic `deriving`") }
+            Tuple(*) => { cx.span_bug(span, ~"Tuple in a path in generic `deriving`") }
+        }
+    }
+}
+
+
+fn mk_ty_param(cx: @ext_ctxt, span: span, name: ~str, bounds: ~[Path],
+               self_ident: ident, self_generics: &Generics) -> ast::TyParam {
+    let bounds = opt_vec::from(
+        do bounds.map |b| {
+            let path = b.to_path(cx, span, self_ident, self_generics);
+            build::mk_trait_ty_param_bound_(cx, path)
+        });
+    build::mk_ty_param(cx, cx.ident_of(name), @bounds)
+}
+
+fn mk_generics(lifetimes: ~[ast::Lifetime],  ty_params: ~[ast::TyParam]) -> Generics {
+    Generics {
+        lifetimes: opt_vec::from(lifetimes),
+        ty_params: opt_vec::from(ty_params)
+    }
+}
+
+/// Lifetimes and bounds on type paramers
+pub struct LifetimeBounds {
+    lifetimes: ~[~str],
+    bounds: ~[(~str, ~[Path])]
+}
+
+pub impl LifetimeBounds {
+    fn empty() -> LifetimeBounds {
+        LifetimeBounds {
+            lifetimes: ~[], bounds: ~[]
+        }
+    }
+    fn to_generics(&self, cx: @ext_ctxt, span: span,
+                   self_ty: ident, self_generics: &Generics) -> Generics {
+        let lifetimes = do self.lifetimes.map |&lt| {
+            build::mk_lifetime(cx, span, cx.ident_of(lt))
+        };
+        let ty_params = do self.bounds.map |&(name, bounds)| {
+            mk_ty_param(cx, span, name, bounds, self_ty, self_generics)
+        };
+        mk_generics(lifetimes, ty_params)
+    }
+}
+
+
+pub fn get_explicit_self(cx: @ext_ctxt, span: span, self_ptr: Option<PtrTy>)
+    -> (@expr, ast::self_ty) {
+    let self_path = build::mk_path(cx, span, ~[cx.ident_of(~"self")]);
+    match self_ptr {
+        None => {
+            (self_path, respan(span, ast::sty_value))
+        }
+        Some(ptr) => {
+            let self_ty = respan(
+                span,
+                match ptr {
+                    Owned => ast::sty_uniq(ast::m_imm),
+                    Managed(mutbl) => ast::sty_box(mutbl),
+                    Borrowed(lt, mutbl) => {
+                        let lt = lt.map(|s| @build::mk_lifetime(cx, span,
+                                                                cx.ident_of(*s)));
+                        ast::sty_region(lt, mutbl)
+                    }
+                });
+            let self_expr = build::mk_deref(cx, span, self_path);
+            (self_expr, self_ty)
+        }
+    }
+}
diff --git a/src/test/run-pass/deriving-rand.rs b/src/test/run-pass/deriving-rand.rs
new file mode 100644
index 00000000000..dd4664e7446
--- /dev/null
+++ b/src/test/run-pass/deriving-rand.rs
@@ -0,0 +1,39 @@
+// xfail-fast #6330
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[deriving(Rand)]
+struct A;
+
+#[deriving(Rand)]
+struct B(int, int);
+
+#[deriving(Rand)]
+struct C {
+    x: f64,
+    y: (u8, u8)
+}
+
+#[deriving(Rand)]
+enum D {
+    D0,
+    D1(uint),
+    D2 { x: (), y: () }
+}
+
+fn main() {
+    // check there's no segfaults
+    for 20.times {
+        rand::random::<A>();
+        rand::random::<B>();
+        rand::random::<C>();
+        rand::random::<D>();
+    }
+}
\ No newline at end of file
diff --git a/src/test/run-pass/deriving-self-lifetime-totalord-totaleq.rs b/src/test/run-pass/deriving-self-lifetime-totalord-totaleq.rs
new file mode 100644
index 00000000000..b0b03d8419b
--- /dev/null
+++ b/src/test/run-pass/deriving-self-lifetime-totalord-totaleq.rs
@@ -0,0 +1,32 @@
+// xfail-test FIXME #6257
+
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::cmp::{Less,Equal,Greater};
+
+#[deriving(TotalEq,TotalOrd)]
+struct A<'self> {
+    x: &'self int
+}
+
+fn main() {
+    let a = A { x: &1 }, b = A { x: &2 };
+
+    assert!(a.equals(&a));
+    assert!(b.equals(&b));
+
+
+    assert_eq!(a.cmp(&a), Equal);
+    assert_eq!(b.cmp(&b), Equal);
+
+    assert_eq!(a.cmp(&b), Less);
+    assert_eq!(b.cmp(&a), Greater);
+}
diff --git a/src/test/run-pass/deriving-self-lifetime.rs b/src/test/run-pass/deriving-self-lifetime.rs
new file mode 100644
index 00000000000..549a9b398a2
--- /dev/null
+++ b/src/test/run-pass/deriving-self-lifetime.rs
@@ -0,0 +1,33 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[deriving(Eq,Ord)]
+struct A<'self> {
+    x: &'self int
+}
+
+fn main() {
+    let a = A { x: &1 }, b = A { x: &2 };
+
+    assert_eq!(a, a);
+    assert_eq!(b, b);
+
+
+    assert!(a < b);
+    assert!(b > a);
+
+    assert!(a <= b);
+    assert!(a <= a);
+    assert!(b <= b);
+
+    assert!(b >= a);
+    assert!(b >= b);
+    assert!(a >= a);
+}
diff --git a/src/test/run-pass/deriving-to-str.rs b/src/test/run-pass/deriving-to-str.rs
new file mode 100644
index 00000000000..4b98f9a73c5
--- /dev/null
+++ b/src/test/run-pass/deriving-to-str.rs
@@ -0,0 +1,45 @@
+// xfail-fast #6330
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[deriving(Rand,ToStr)]
+struct A;
+
+#[deriving(Rand,ToStr)]
+struct B(int, int);
+
+#[deriving(Rand,ToStr)]
+struct C {
+    x: f64,
+    y: (u8, u8)
+}
+
+#[deriving(Rand,ToStr)]
+enum D {
+    D0,
+    D1(uint),
+    D2 { x: (), y: () }
+}
+
+fn main() {
+    macro_rules! t(
+        ($ty:ty) => {{
+            let x =rand::random::<$ty>();
+            assert_eq!(x.to_str(), fmt!("%?", x));
+        }}
+    );
+
+    for 20.times {
+        t!(A);
+        t!(B);
+        t!(C);
+        t!(D);
+    }
+}
\ No newline at end of file