about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-04-18 00:48:34 +0000
committerbors <bors@rust-lang.org>2015-04-18 00:48:34 +0000
commit1284be4044420bc4c41767284ae26be61a38d331 (patch)
treee363960cdf71027e69a8a6c35b5c9150c2eefd22 /src/libsyntax
parentb08d6cf529a83caec2f408cd8b1287e493ec57ca (diff)
parented437cd8fcbb9ee89849a7eafff94ea97252189e (diff)
downloadrust-1284be4044420bc4c41767284ae26be61a38d331.tar.gz
rust-1284be4044420bc4c41767284ae26be61a38d331.zip
Auto merge of #23985 - erickt:derive-cleanup, r=erickt
This extracts some of the minor cleanup patches from #23905.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/deriving/bounds.rs24
-rw-r--r--src/libsyntax/ext/deriving/clone.rs11
-rw-r--r--src/libsyntax/ext/deriving/cmp/eq.rs97
-rw-r--r--src/libsyntax/ext/deriving/cmp/ord.rs185
-rw-r--r--src/libsyntax/ext/deriving/cmp/partial_eq.rs94
-rw-r--r--src/libsyntax/ext/deriving/cmp/partial_ord.rs237
-rw-r--r--src/libsyntax/ext/deriving/cmp/totaleq.rs69
-rw-r--r--src/libsyntax/ext/deriving/cmp/totalord.rs142
-rw-r--r--src/libsyntax/ext/deriving/decodable.rs35
-rw-r--r--src/libsyntax/ext/deriving/default.rs11
-rw-r--r--src/libsyntax/ext/deriving/encodable.rs35
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs11
-rw-r--r--src/libsyntax/ext/deriving/hash.rs11
-rw-r--r--src/libsyntax/ext/deriving/mod.rs24
-rw-r--r--src/libsyntax/ext/deriving/primitive.rs11
-rw-r--r--src/libsyntax/ext/deriving/show.rs11
16 files changed, 496 insertions, 512 deletions
diff --git a/src/libsyntax/ext/deriving/bounds.rs b/src/libsyntax/ext/deriving/bounds.rs
index e408c99935d..eb3debeac99 100644
--- a/src/libsyntax/ext/deriving/bounds.rs
+++ b/src/libsyntax/ext/deriving/bounds.rs
@@ -15,22 +15,20 @@ use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
 use ptr::P;
 
-pub fn expand_deriving_unsafe_bound<F>(cx: &mut ExtCtxt,
-                                       span: Span,
-                                       _: &MetaItem,
-                                       _: &Item,
-                                       _: F) where
-    F: FnOnce(P<Item>),
+pub fn expand_deriving_unsafe_bound(cx: &mut ExtCtxt,
+                                    span: Span,
+                                    _: &MetaItem,
+                                    _: &Item,
+                                    _: &mut FnMut(P<Item>))
 {
     cx.span_err(span, "this unsafe trait should be implemented explicitly");
 }
 
-pub fn expand_deriving_copy<F>(cx: &mut ExtCtxt,
-                               span: Span,
-                               mitem: &MetaItem,
-                               item: &Item,
-                               push: F) where
-    F: FnOnce(P<Item>),
+pub fn expand_deriving_copy(cx: &mut ExtCtxt,
+                            span: Span,
+                            mitem: &MetaItem,
+                            item: &Item,
+                            push: &mut FnMut(P<Item>))
 {
     let path = Path::new(vec![
         if cx.use_std { "std" } else { "core" },
@@ -48,5 +46,5 @@ pub fn expand_deriving_copy<F>(cx: &mut ExtCtxt,
         associated_types: Vec::new(),
     };
 
-    trait_def.expand(cx, mitem, item, push)
+    trait_def.expand(cx, mitem, item, push);
 }
diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs
index 95eb68ca0d3..97fc3f0bf56 100644
--- a/src/libsyntax/ext/deriving/clone.rs
+++ b/src/libsyntax/ext/deriving/clone.rs
@@ -17,12 +17,11 @@ use ext::deriving::generic::ty::*;
 use parse::token::InternedString;
 use ptr::P;
 
-pub fn expand_deriving_clone<F>(cx: &mut ExtCtxt,
-                                span: Span,
-                                mitem: &MetaItem,
-                                item: &Item,
-                                push: F) where
-    F: FnOnce(P<Item>),
+pub fn expand_deriving_clone(cx: &mut ExtCtxt,
+                             span: Span,
+                             mitem: &MetaItem,
+                             item: &Item,
+                             push: &mut FnMut(P<Item>))
 {
     let inline = cx.meta_word(span, InternedString::new("inline"));
     let attrs = vec!(cx.attribute(span, inline));
diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs
index c02af437b1c..ce8f0a7b32b 100644
--- a/src/libsyntax/ext/deriving/cmp/eq.rs
+++ b/src/libsyntax/ext/deriving/cmp/eq.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast::{MetaItem, Item, Expr, self};
+use ast::{MetaItem, Item, Expr};
 use codemap::Span;
 use ext::base::ExtCtxt;
 use ext::build::AstBuilder;
@@ -17,77 +17,52 @@ use ext::deriving::generic::ty::*;
 use parse::token::InternedString;
 use ptr::P;
 
-pub fn expand_deriving_eq<F>(cx: &mut ExtCtxt,
-                             span: Span,
-                             mitem: &MetaItem,
-                             item: &Item,
-                             push: F) where
-    F: FnOnce(P<Item>),
+pub fn expand_deriving_eq(cx: &mut ExtCtxt,
+                          span: Span,
+                          mitem: &MetaItem,
+                          item: &Item,
+                          push: &mut FnMut(P<Item>))
 {
-    // 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: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
-        cs_fold(
-            true,  // use foldl
-            |cx, span, subexpr, self_f, other_fs| {
-                let other_f = match other_fs {
-                    [ref o_f] => o_f,
-                    _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`")
-                };
-
-                let eq = cx.expr_binary(span, ast::BiEq, self_f, other_f.clone());
-
-                cx.expr_binary(span, ast::BiAnd, subexpr, eq)
-            },
-            cx.expr_bool(span, true),
-            Box::new(|cx, span, _, _| cx.expr_bool(span, false)),
-            cx, span, substr)
-    }
-    fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
-        cs_fold(
-            true,  // use foldl
-            |cx, span, subexpr, self_f, other_fs| {
-                let other_f = match other_fs {
-                    [ref o_f] => o_f,
-                    _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`")
-                };
-
-                let eq = cx.expr_binary(span, ast::BiNe, self_f, other_f.clone());
-
-                cx.expr_binary(span, ast::BiOr, subexpr, eq)
+    fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
+        cs_same_method(
+            |cx, span, exprs| {
+                // create `a.<method>(); b.<method>(); c.<method>(); ...`
+                // (where method is `assert_receiver_is_total_eq`)
+                let stmts = exprs.into_iter().map(|e| cx.stmt_expr(e)).collect();
+                let block = cx.block(span, stmts, None);
+                cx.expr_block(block)
             },
-            cx.expr_bool(span, false),
-            Box::new(|cx, span, _, _| cx.expr_bool(span, true)),
-            cx, span, substr)
+            Box::new(|cx, sp, _, _| {
+                cx.span_bug(sp, "non matching enums in derive(Eq)?") }),
+            cx,
+            span,
+            substr
+        )
     }
 
-    macro_rules! md {
-        ($name:expr, $f:ident) => { {
-            let inline = cx.meta_word(span, InternedString::new("inline"));
-            let attrs = vec!(cx.attribute(span, inline));
+    let inline = cx.meta_word(span, InternedString::new("inline"));
+    let hidden = cx.meta_word(span, InternedString::new("hidden"));
+    let doc = cx.meta_list(span, InternedString::new("doc"), vec!(hidden));
+    let attrs = vec!(cx.attribute(span, inline),
+                     cx.attribute(span, doc));
+    let trait_def = TraitDef {
+        span: span,
+        attributes: Vec::new(),
+        path: path_std!(cx, core::cmp::Eq),
+        additional_bounds: Vec::new(),
+        generics: LifetimeBounds::empty(),
+        methods: vec!(
             MethodDef {
-                name: $name,
+                name: "assert_receiver_is_total_eq",
                 generics: LifetimeBounds::empty(),
                 explicit_self: borrowed_explicit_self(),
-                args: vec!(borrowed_self()),
-                ret_ty: Literal(path_local!(bool)),
+                args: vec!(),
+                ret_ty: nil_ty(),
                 attributes: attrs,
                 combine_substructure: combine_substructure(Box::new(|a, b, c| {
-                    $f(a, b, c)
+                    cs_total_eq_assert(a, b, c)
                 }))
             }
-        } }
-    }
-
-    let trait_def = TraitDef {
-        span: span,
-        attributes: Vec::new(),
-        path: path_std!(cx, core::cmp::PartialEq),
-        additional_bounds: Vec::new(),
-        generics: LifetimeBounds::empty(),
-        methods: vec!(
-            md!("eq", cs_eq),
-            md!("ne", cs_ne)
         ),
         associated_types: Vec::new(),
     };
diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs
index 8ecd172b2f0..b2a4ef1dafb 100644
--- a/src/libsyntax/ext/deriving/cmp/ord.rs
+++ b/src/libsyntax/ext/deriving/cmp/ord.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::OrderingOp::*;
-
 use ast;
 use ast::{MetaItem, Item, Expr};
 use codemap::Span;
@@ -20,114 +18,71 @@ use ext::deriving::generic::ty::*;
 use parse::token::InternedString;
 use ptr::P;
 
-pub fn expand_deriving_ord<F>(cx: &mut ExtCtxt,
-                              span: Span,
-                              mitem: &MetaItem,
-                              item: &Item,
-                              push: F) where
-    F: FnOnce(P<Item>),
+pub fn expand_deriving_ord(cx: &mut ExtCtxt,
+                           span: Span,
+                           mitem: &MetaItem,
+                           item: &Item,
+                           push: &mut FnMut(P<Item>))
 {
-    macro_rules! md {
-        ($name:expr, $op:expr, $equal:expr) => { {
-            let inline = cx.meta_word(span, InternedString::new("inline"));
-            let attrs = vec!(cx.attribute(span, inline));
+    let inline = cx.meta_word(span, InternedString::new("inline"));
+    let attrs = vec!(cx.attribute(span, inline));
+    let trait_def = TraitDef {
+        span: span,
+        attributes: Vec::new(),
+        path: path_std!(cx, core::cmp::Ord),
+        additional_bounds: Vec::new(),
+        generics: LifetimeBounds::empty(),
+        methods: vec!(
             MethodDef {
-                name: $name,
+                name: "cmp",
                 generics: LifetimeBounds::empty(),
                 explicit_self: borrowed_explicit_self(),
                 args: vec!(borrowed_self()),
-                ret_ty: Literal(path_local!(bool)),
+                ret_ty: Literal(path_std!(cx, core::cmp::Ordering)),
                 attributes: attrs,
-                combine_substructure: combine_substructure(Box::new(|cx, span, substr| {
-                    cs_op($op, $equal, cx, span, substr)
-                }))
+                combine_substructure: combine_substructure(Box::new(|a, b, c| {
+                    cs_cmp(a, b, c)
+                })),
             }
-        } }
-    }
-
-    let ordering_ty = Literal(path_std!(cx, core::cmp::Ordering));
-    let ret_ty = Literal(Path::new_(pathvec_std!(cx, core::option::Option),
-                                    None,
-                                    vec![box ordering_ty],
-                                    true));
-
-    let inline = cx.meta_word(span, InternedString::new("inline"));
-    let attrs = vec!(cx.attribute(span, inline));
-
-    let partial_cmp_def = MethodDef {
-        name: "partial_cmp",
-        generics: LifetimeBounds::empty(),
-        explicit_self: borrowed_explicit_self(),
-        args: vec![borrowed_self()],
-        ret_ty: ret_ty,
-        attributes: attrs,
-        combine_substructure: combine_substructure(Box::new(|cx, span, substr| {
-            cs_partial_cmp(cx, span, substr)
-        }))
-    };
-
-    let trait_def = TraitDef {
-        span: span,
-        attributes: vec![],
-        path: path_std!(cx, core::cmp::PartialOrd),
-        additional_bounds: vec![],
-        generics: LifetimeBounds::empty(),
-        methods: vec![
-            partial_cmp_def,
-            md!("lt", true, false),
-            md!("le", true, true),
-            md!("gt", false, false),
-            md!("ge", false, true)
-        ],
+        ),
         associated_types: Vec::new(),
     };
+
     trait_def.expand(cx, mitem, item, push)
 }
 
-#[derive(Copy, Clone)]
-pub enum OrderingOp {
-    PartialCmpOp, LtOp, LeOp, GtOp, GeOp,
-}
 
-pub fn some_ordering_collapsed(cx: &mut ExtCtxt,
-                               span: Span,
-                               op: OrderingOp,
-                               self_arg_tags: &[ast::Ident]) -> P<ast::Expr> {
+pub fn ordering_collapsed(cx: &mut ExtCtxt,
+                          span: Span,
+                          self_arg_tags: &[ast::Ident]) -> P<ast::Expr> {
     let lft = cx.expr_ident(span, self_arg_tags[0]);
     let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1]));
-    let op_str = match op {
-        PartialCmpOp => "partial_cmp",
-        LtOp => "lt", LeOp => "le",
-        GtOp => "gt", GeOp => "ge",
-    };
-    cx.expr_method_call(span, lft, cx.ident_of(op_str), vec![rgt])
+    cx.expr_method_call(span, lft, cx.ident_of("cmp"), vec![rgt])
 }
 
-pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span,
+pub fn cs_cmp(cx: &mut ExtCtxt, span: Span,
               substr: &Substructure) -> P<Expr> {
     let test_id = cx.ident_of("__test");
-    let ordering = cx.path_global(span,
-                                  vec!(cx.ident_of_std("core"),
-                                       cx.ident_of("cmp"),
-                                       cx.ident_of("Ordering"),
-                                       cx.ident_of("Equal")));
-    let ordering = cx.expr_path(ordering);
-    let equals_expr = cx.expr_some(span, ordering);
+    let equals_path = cx.path_global(span,
+                                     vec!(cx.ident_of_std("core"),
+                                          cx.ident_of("cmp"),
+                                          cx.ident_of("Ordering"),
+                                          cx.ident_of("Equal")));
 
-    let partial_cmp_path = vec![
+    let cmp_path = vec![
         cx.ident_of_std("core"),
         cx.ident_of("cmp"),
-        cx.ident_of("PartialOrd"),
-        cx.ident_of("partial_cmp"),
+        cx.ident_of("Ord"),
+        cx.ident_of("cmp"),
     ];
 
     /*
     Builds:
 
-    let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1);
-    if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) {
-        let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2);
-        if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) {
+    let __test = ::std::cmp::Ord::cmp(&self_field1, &other_field1);
+    if other == ::std::cmp::Ordering::Equal {
+        let __test = ::std::cmp::Ord::cmp(&self_field2, &other_field2);
+        if __test == ::std::cmp::Ordering::Equal {
             ...
         } else {
             __test
@@ -144,7 +99,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span,
         false,
         |cx, span, old, self_f, other_fs| {
             // let __test = new;
-            // if __test == Some(::std::cmp::Ordering::Equal) {
+            // if __test == ::std::cmp::Ordering::Equal {
             //    old
             // } else {
             //    __test
@@ -161,77 +116,25 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span,
                     cx.expr_addr_of(span, other_f.clone()),
                 ];
 
-                cx.expr_call_global(span, partial_cmp_path.clone(), args)
+                cx.expr_call_global(span, cmp_path.clone(), args)
             };
 
             let assign = cx.stmt_let(span, false, test_id, new);
 
             let cond = cx.expr_binary(span, ast::BiEq,
                                       cx.expr_ident(span, test_id),
-                                      equals_expr.clone());
+                                      cx.expr_path(equals_path.clone()));
             let if_ = cx.expr_if(span,
                                  cond,
                                  old, Some(cx.expr_ident(span, test_id)));
             cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
         },
-        equals_expr.clone(),
+        cx.expr_path(equals_path.clone()),
         Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
             if self_args.len() != 2 {
-                cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
+                cx.span_bug(span, "not exactly 2 arguments in `derives(Ord)`")
             } else {
-                some_ordering_collapsed(cx, span, PartialCmpOp, tag_tuple)
-            }
-        }),
-        cx, span, substr)
-}
-
-/// Strict inequality.
-fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt,
-         span: Span, substr: &Substructure) -> P<Expr> {
-    let op = if less {ast::BiLt} else {ast::BiGt};
-    cs_fold(
-        false, // need foldr,
-        |cx, span, subexpr, self_f, other_fs| {
-            /*
-            build up a series of chain ||'s and &&'s from the inside
-            out (hence foldr) to get lexical ordering, i.e. for op ==
-            `ast::lt`
-
-            ```
-            self.f1 < other.f1 || (!(other.f1 < self.f1) &&
-                (self.f2 < other.f2 || (!(other.f2 < self.f2) &&
-                    (false)
-                ))
-            )
-            ```
-
-            The optimiser should remove the redundancy. We explicitly
-            get use the binops to avoid auto-deref dereferencing too many
-            layers of pointers, if the type includes pointers.
-            */
-            let other_f = match other_fs {
-                [ref o_f] => o_f,
-                _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
-            };
-
-            let cmp = cx.expr_binary(span, op, self_f.clone(), other_f.clone());
-
-            let not_cmp = cx.expr_unary(span, ast::UnNot,
-                                        cx.expr_binary(span, op, other_f.clone(), self_f));
-
-            let and = cx.expr_binary(span, ast::BiAnd, not_cmp, subexpr);
-            cx.expr_binary(span, ast::BiOr, cmp, and)
-        },
-        cx.expr_bool(span, equal),
-        Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
-            if self_args.len() != 2 {
-                cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
-            } else {
-                let op = match (less, equal) {
-                    (true,  true) => LeOp, (true,  false) => LtOp,
-                    (false, true) => GeOp, (false, false) => GtOp,
-                };
-                some_ordering_collapsed(cx, span, op, tag_tuple)
+                ordering_collapsed(cx, span, tag_tuple)
             }
         }),
         cx, span, substr)
diff --git a/src/libsyntax/ext/deriving/cmp/partial_eq.rs b/src/libsyntax/ext/deriving/cmp/partial_eq.rs
new file mode 100644
index 00000000000..f02e5ee1412
--- /dev/null
+++ b/src/libsyntax/ext/deriving/cmp/partial_eq.rs
@@ -0,0 +1,94 @@
+// 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 ast::{MetaItem, Item, Expr, self};
+use codemap::Span;
+use ext::base::ExtCtxt;
+use ext::build::AstBuilder;
+use ext::deriving::generic::*;
+use ext::deriving::generic::ty::*;
+use parse::token::InternedString;
+use ptr::P;
+
+pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
+                                  span: Span,
+                                  mitem: &MetaItem,
+                                  item: &Item,
+                                  push: &mut FnMut(P<Item>))
+{
+    // 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: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
+        cs_fold(
+            true,  // use foldl
+            |cx, span, subexpr, self_f, other_fs| {
+                let other_f = match other_fs {
+                    [ref o_f] => o_f,
+                    _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`")
+                };
+
+                let eq = cx.expr_binary(span, ast::BiEq, self_f, other_f.clone());
+
+                cx.expr_binary(span, ast::BiAnd, subexpr, eq)
+            },
+            cx.expr_bool(span, true),
+            Box::new(|cx, span, _, _| cx.expr_bool(span, false)),
+            cx, span, substr)
+    }
+    fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
+        cs_fold(
+            true,  // use foldl
+            |cx, span, subexpr, self_f, other_fs| {
+                let other_f = match other_fs {
+                    [ref o_f] => o_f,
+                    _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`")
+                };
+
+                let eq = cx.expr_binary(span, ast::BiNe, self_f, other_f.clone());
+
+                cx.expr_binary(span, ast::BiOr, subexpr, eq)
+            },
+            cx.expr_bool(span, false),
+            Box::new(|cx, span, _, _| cx.expr_bool(span, true)),
+            cx, span, substr)
+    }
+
+    macro_rules! md {
+        ($name:expr, $f:ident) => { {
+            let inline = cx.meta_word(span, InternedString::new("inline"));
+            let attrs = vec!(cx.attribute(span, inline));
+            MethodDef {
+                name: $name,
+                generics: LifetimeBounds::empty(),
+                explicit_self: borrowed_explicit_self(),
+                args: vec!(borrowed_self()),
+                ret_ty: Literal(path_local!(bool)),
+                attributes: attrs,
+                combine_substructure: combine_substructure(Box::new(|a, b, c| {
+                    $f(a, b, c)
+                }))
+            }
+        } }
+    }
+
+    let trait_def = TraitDef {
+        span: span,
+        attributes: Vec::new(),
+        path: path_std!(cx, core::cmp::PartialEq),
+        additional_bounds: Vec::new(),
+        generics: LifetimeBounds::empty(),
+        methods: vec!(
+            md!("eq", cs_eq),
+            md!("ne", cs_ne)
+        ),
+        associated_types: Vec::new(),
+    };
+    trait_def.expand(cx, mitem, item, push)
+}
diff --git a/src/libsyntax/ext/deriving/cmp/partial_ord.rs b/src/libsyntax/ext/deriving/cmp/partial_ord.rs
new file mode 100644
index 00000000000..9da2db25f7e
--- /dev/null
+++ b/src/libsyntax/ext/deriving/cmp/partial_ord.rs
@@ -0,0 +1,237 @@
+// 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.
+
+pub use self::OrderingOp::*;
+
+use ast;
+use ast::{MetaItem, Item, Expr};
+use codemap::Span;
+use ext::base::ExtCtxt;
+use ext::build::AstBuilder;
+use ext::deriving::generic::*;
+use ext::deriving::generic::ty::*;
+use parse::token::InternedString;
+use ptr::P;
+
+pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
+                                   span: Span,
+                                   mitem: &MetaItem,
+                                   item: &Item,
+                                   push: &mut FnMut(P<Item>))
+{
+    macro_rules! md {
+        ($name:expr, $op:expr, $equal:expr) => { {
+            let inline = cx.meta_word(span, InternedString::new("inline"));
+            let attrs = vec!(cx.attribute(span, inline));
+            MethodDef {
+                name: $name,
+                generics: LifetimeBounds::empty(),
+                explicit_self: borrowed_explicit_self(),
+                args: vec!(borrowed_self()),
+                ret_ty: Literal(path_local!(bool)),
+                attributes: attrs,
+                combine_substructure: combine_substructure(Box::new(|cx, span, substr| {
+                    cs_op($op, $equal, cx, span, substr)
+                }))
+            }
+        } }
+    }
+
+    let ordering_ty = Literal(path_std!(cx, core::cmp::Ordering));
+    let ret_ty = Literal(Path::new_(pathvec_std!(cx, core::option::Option),
+                                    None,
+                                    vec![box ordering_ty],
+                                    true));
+
+    let inline = cx.meta_word(span, InternedString::new("inline"));
+    let attrs = vec!(cx.attribute(span, inline));
+
+    let partial_cmp_def = MethodDef {
+        name: "partial_cmp",
+        generics: LifetimeBounds::empty(),
+        explicit_self: borrowed_explicit_self(),
+        args: vec![borrowed_self()],
+        ret_ty: ret_ty,
+        attributes: attrs,
+        combine_substructure: combine_substructure(Box::new(|cx, span, substr| {
+            cs_partial_cmp(cx, span, substr)
+        }))
+    };
+
+    let trait_def = TraitDef {
+        span: span,
+        attributes: vec![],
+        path: path_std!(cx, core::cmp::PartialOrd),
+        additional_bounds: vec![],
+        generics: LifetimeBounds::empty(),
+        methods: vec![
+            partial_cmp_def,
+            md!("lt", true, false),
+            md!("le", true, true),
+            md!("gt", false, false),
+            md!("ge", false, true)
+        ],
+        associated_types: Vec::new(),
+    };
+    trait_def.expand(cx, mitem, item, push)
+}
+
+#[derive(Copy, Clone)]
+pub enum OrderingOp {
+    PartialCmpOp, LtOp, LeOp, GtOp, GeOp,
+}
+
+pub fn some_ordering_collapsed(cx: &mut ExtCtxt,
+                               span: Span,
+                               op: OrderingOp,
+                               self_arg_tags: &[ast::Ident]) -> P<ast::Expr> {
+    let lft = cx.expr_ident(span, self_arg_tags[0]);
+    let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1]));
+    let op_str = match op {
+        PartialCmpOp => "partial_cmp",
+        LtOp => "lt", LeOp => "le",
+        GtOp => "gt", GeOp => "ge",
+    };
+    cx.expr_method_call(span, lft, cx.ident_of(op_str), vec![rgt])
+}
+
+pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span,
+              substr: &Substructure) -> P<Expr> {
+    let test_id = cx.ident_of("__test");
+    let ordering = cx.path_global(span,
+                                  vec!(cx.ident_of_std("core"),
+                                       cx.ident_of("cmp"),
+                                       cx.ident_of("Ordering"),
+                                       cx.ident_of("Equal")));
+    let ordering = cx.expr_path(ordering);
+    let equals_expr = cx.expr_some(span, ordering);
+
+    let partial_cmp_path = vec![
+        cx.ident_of_std("core"),
+        cx.ident_of("cmp"),
+        cx.ident_of("PartialOrd"),
+        cx.ident_of("partial_cmp"),
+    ];
+
+    /*
+    Builds:
+
+    let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1);
+    if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) {
+        let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2);
+        if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) {
+            ...
+        } else {
+            __test
+        }
+    } else {
+        __test
+    }
+
+    FIXME #6449: These `if`s could/should be `match`es.
+    */
+    cs_fold(
+        // foldr nests the if-elses correctly, leaving the first field
+        // as the outermost one, and the last as the innermost.
+        false,
+        |cx, span, old, self_f, other_fs| {
+            // let __test = new;
+            // if __test == Some(::std::cmp::Ordering::Equal) {
+            //    old
+            // } else {
+            //    __test
+            // }
+
+            let new = {
+                let other_f = match other_fs {
+                    [ref o_f] => o_f,
+                    _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"),
+                };
+
+                let args = vec![
+                    cx.expr_addr_of(span, self_f),
+                    cx.expr_addr_of(span, other_f.clone()),
+                ];
+
+                cx.expr_call_global(span, partial_cmp_path.clone(), args)
+            };
+
+            let assign = cx.stmt_let(span, false, test_id, new);
+
+            let cond = cx.expr_binary(span, ast::BiEq,
+                                      cx.expr_ident(span, test_id),
+                                      equals_expr.clone());
+            let if_ = cx.expr_if(span,
+                                 cond,
+                                 old, Some(cx.expr_ident(span, test_id)));
+            cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
+        },
+        equals_expr.clone(),
+        Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
+            if self_args.len() != 2 {
+                cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
+            } else {
+                some_ordering_collapsed(cx, span, PartialCmpOp, tag_tuple)
+            }
+        }),
+        cx, span, substr)
+}
+
+/// Strict inequality.
+fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt,
+         span: Span, substr: &Substructure) -> P<Expr> {
+    let op = if less {ast::BiLt} else {ast::BiGt};
+    cs_fold(
+        false, // need foldr,
+        |cx, span, subexpr, self_f, other_fs| {
+            /*
+            build up a series of chain ||'s and &&'s from the inside
+            out (hence foldr) to get lexical ordering, i.e. for op ==
+            `ast::lt`
+
+            ```
+            self.f1 < other.f1 || (!(other.f1 < self.f1) &&
+                (self.f2 < other.f2 || (!(other.f2 < self.f2) &&
+                    (false)
+                ))
+            )
+            ```
+
+            The optimiser should remove the redundancy. We explicitly
+            get use the binops to avoid auto-deref dereferencing too many
+            layers of pointers, if the type includes pointers.
+            */
+            let other_f = match other_fs {
+                [ref o_f] => o_f,
+                _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
+            };
+
+            let cmp = cx.expr_binary(span, op, self_f.clone(), other_f.clone());
+
+            let not_cmp = cx.expr_unary(span, ast::UnNot,
+                                        cx.expr_binary(span, op, other_f.clone(), self_f));
+
+            let and = cx.expr_binary(span, ast::BiAnd, not_cmp, subexpr);
+            cx.expr_binary(span, ast::BiOr, cmp, and)
+        },
+        cx.expr_bool(span, equal),
+        Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
+            if self_args.len() != 2 {
+                cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
+            } else {
+                let op = match (less, equal) {
+                    (true,  true) => LeOp, (true,  false) => LtOp,
+                    (false, true) => GeOp, (false, false) => GtOp,
+                };
+                some_ordering_collapsed(cx, span, op, tag_tuple)
+            }
+        }),
+        cx, span, substr)
+}
diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs
deleted file mode 100644
index 83164d242e8..00000000000
--- a/src/libsyntax/ext/deriving/cmp/totaleq.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-// 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 ast::{MetaItem, Item, Expr};
-use codemap::Span;
-use ext::base::ExtCtxt;
-use ext::build::AstBuilder;
-use ext::deriving::generic::*;
-use ext::deriving::generic::ty::*;
-use parse::token::InternedString;
-use ptr::P;
-
-pub fn expand_deriving_totaleq<F>(cx: &mut ExtCtxt,
-                                  span: Span,
-                                  mitem: &MetaItem,
-                                  item: &Item,
-                                  push: F) where
-    F: FnOnce(P<Item>),
-{
-    fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
-        cs_same_method(|cx, span, exprs| {
-            // create `a.<method>(); b.<method>(); c.<method>(); ...`
-            // (where method is `assert_receiver_is_total_eq`)
-            let stmts = exprs.into_iter().map(|e| cx.stmt_expr(e)).collect();
-            let block = cx.block(span, stmts, None);
-            cx.expr_block(block)
-        },
-                       Box::new(|cx, sp, _, _| {
-                           cx.span_bug(sp, "non matching enums in derive(Eq)?") }),
-                       cx,
-                       span,
-                       substr)
-    }
-
-    let inline = cx.meta_word(span, InternedString::new("inline"));
-    let hidden = cx.meta_word(span, InternedString::new("hidden"));
-    let doc = cx.meta_list(span, InternedString::new("doc"), vec!(hidden));
-    let attrs = vec!(cx.attribute(span, inline),
-                     cx.attribute(span, doc));
-    let trait_def = TraitDef {
-        span: span,
-        attributes: Vec::new(),
-        path: path_std!(cx, core::cmp::Eq),
-        additional_bounds: Vec::new(),
-        generics: LifetimeBounds::empty(),
-        methods: vec!(
-            MethodDef {
-                name: "assert_receiver_is_total_eq",
-                generics: LifetimeBounds::empty(),
-                explicit_self: borrowed_explicit_self(),
-                args: vec!(),
-                ret_ty: nil_ty(),
-                attributes: attrs,
-                combine_substructure: combine_substructure(Box::new(|a, b, c| {
-                    cs_total_eq_assert(a, b, c)
-                }))
-            }
-        ),
-        associated_types: Vec::new(),
-    };
-    trait_def.expand(cx, mitem, item, push)
-}
diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs
deleted file mode 100644
index 1de955856e7..00000000000
--- a/src/libsyntax/ext/deriving/cmp/totalord.rs
+++ /dev/null
@@ -1,142 +0,0 @@
-// 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 ast;
-use ast::{MetaItem, Item, Expr};
-use codemap::Span;
-use ext::base::ExtCtxt;
-use ext::build::AstBuilder;
-use ext::deriving::generic::*;
-use ext::deriving::generic::ty::*;
-use parse::token::InternedString;
-use ptr::P;
-
-pub fn expand_deriving_totalord<F>(cx: &mut ExtCtxt,
-                                   span: Span,
-                                   mitem: &MetaItem,
-                                   item: &Item,
-                                   push: F) where
-    F: FnOnce(P<Item>),
-{
-    let inline = cx.meta_word(span, InternedString::new("inline"));
-    let attrs = vec!(cx.attribute(span, inline));
-    let trait_def = TraitDef {
-        span: span,
-        attributes: Vec::new(),
-        path: path_std!(cx, core::cmp::Ord),
-        additional_bounds: Vec::new(),
-        generics: LifetimeBounds::empty(),
-        methods: vec!(
-            MethodDef {
-                name: "cmp",
-                generics: LifetimeBounds::empty(),
-                explicit_self: borrowed_explicit_self(),
-                args: vec!(borrowed_self()),
-                ret_ty: Literal(path_std!(cx, core::cmp::Ordering)),
-                attributes: attrs,
-                combine_substructure: combine_substructure(Box::new(|a, b, c| {
-                    cs_cmp(a, b, c)
-                })),
-            }
-        ),
-        associated_types: Vec::new(),
-    };
-
-    trait_def.expand(cx, mitem, item, push)
-}
-
-
-pub fn ordering_collapsed(cx: &mut ExtCtxt,
-                          span: Span,
-                          self_arg_tags: &[ast::Ident]) -> P<ast::Expr> {
-    let lft = cx.expr_ident(span, self_arg_tags[0]);
-    let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1]));
-    cx.expr_method_call(span, lft, cx.ident_of("cmp"), vec![rgt])
-}
-
-pub fn cs_cmp(cx: &mut ExtCtxt, span: Span,
-              substr: &Substructure) -> P<Expr> {
-    let test_id = cx.ident_of("__test");
-    let equals_path = cx.path_global(span,
-                                     vec!(cx.ident_of_std("core"),
-                                          cx.ident_of("cmp"),
-                                          cx.ident_of("Ordering"),
-                                          cx.ident_of("Equal")));
-
-    let cmp_path = vec![
-        cx.ident_of_std("core"),
-        cx.ident_of("cmp"),
-        cx.ident_of("Ord"),
-        cx.ident_of("cmp"),
-    ];
-
-    /*
-    Builds:
-
-    let __test = ::std::cmp::Ord::cmp(&self_field1, &other_field1);
-    if other == ::std::cmp::Ordering::Equal {
-        let __test = ::std::cmp::Ord::cmp(&self_field2, &other_field2);
-        if __test == ::std::cmp::Ordering::Equal {
-            ...
-        } else {
-            __test
-        }
-    } else {
-        __test
-    }
-
-    FIXME #6449: These `if`s could/should be `match`es.
-    */
-    cs_fold(
-        // foldr nests the if-elses correctly, leaving the first field
-        // as the outermost one, and the last as the innermost.
-        false,
-        |cx, span, old, self_f, other_fs| {
-            // let __test = new;
-            // if __test == ::std::cmp::Ordering::Equal {
-            //    old
-            // } else {
-            //    __test
-            // }
-
-            let new = {
-                let other_f = match other_fs {
-                    [ref o_f] => o_f,
-                    _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"),
-                };
-
-                let args = vec![
-                    cx.expr_addr_of(span, self_f),
-                    cx.expr_addr_of(span, other_f.clone()),
-                ];
-
-                cx.expr_call_global(span, cmp_path.clone(), args)
-            };
-
-            let assign = cx.stmt_let(span, false, test_id, new);
-
-            let cond = cx.expr_binary(span, ast::BiEq,
-                                      cx.expr_ident(span, test_id),
-                                      cx.expr_path(equals_path.clone()));
-            let if_ = cx.expr_if(span,
-                                 cond,
-                                 old, Some(cx.expr_ident(span, test_id)));
-            cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
-        },
-        cx.expr_path(equals_path.clone()),
-        Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
-            if self_args.len() != 2 {
-                cx.span_bug(span, "not exactly 2 arguments in `derives(Ord)`")
-            } else {
-                ordering_collapsed(cx, span, tag_tuple)
-            }
-        }),
-        cx, span, substr)
-}
diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs
index 6ce68948e4b..14f0004101c 100644
--- a/src/libsyntax/ext/deriving/decodable.rs
+++ b/src/libsyntax/ext/deriving/decodable.rs
@@ -21,33 +21,30 @@ use parse::token::InternedString;
 use parse::token;
 use ptr::P;
 
-pub fn expand_deriving_rustc_decodable<F>(cx: &mut ExtCtxt,
-                                          span: Span,
-                                          mitem: &MetaItem,
-                                          item: &Item,
-                                          push: F) where
-    F: FnOnce(P<Item>),
+pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt,
+                                       span: Span,
+                                       mitem: &MetaItem,
+                                       item: &Item,
+                                       push: &mut FnMut(P<Item>))
 {
     expand_deriving_decodable_imp(cx, span, mitem, item, push, "rustc_serialize")
 }
 
-pub fn expand_deriving_decodable<F>(cx: &mut ExtCtxt,
-                                    span: Span,
-                                    mitem: &MetaItem,
-                                    item: &Item,
-                                    push: F) where
-    F: FnOnce(P<Item>),
+pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
+                                 span: Span,
+                                 mitem: &MetaItem,
+                                 item: &Item,
+                                 push: &mut FnMut(P<Item>))
 {
     expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize")
 }
 
-fn expand_deriving_decodable_imp<F>(cx: &mut ExtCtxt,
-                                    span: Span,
-                                    mitem: &MetaItem,
-                                    item: &Item,
-                                    push: F,
-                                    krate: &'static str) where
-    F: FnOnce(P<Item>),
+fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
+                                 span: Span,
+                                 mitem: &MetaItem,
+                                 item: &Item,
+                                 push: &mut FnMut(P<Item>),
+                                 krate: &'static str)
 {
     if !cx.use_std {
         // FIXME(#21880): lift this requirement.
diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs
index f9991a23354..f04eaa08dea 100644
--- a/src/libsyntax/ext/deriving/default.rs
+++ b/src/libsyntax/ext/deriving/default.rs
@@ -17,12 +17,11 @@ use ext::deriving::generic::ty::*;
 use parse::token::InternedString;
 use ptr::P;
 
-pub fn expand_deriving_default<F>(cx: &mut ExtCtxt,
-                                  span: Span,
-                                  mitem: &MetaItem,
-                                  item: &Item,
-                                  push: F) where
-    F: FnOnce(P<Item>),
+pub fn expand_deriving_default(cx: &mut ExtCtxt,
+                               span: Span,
+                               mitem: &MetaItem,
+                               item: &Item,
+                               push: &mut FnMut(P<Item>))
 {
     let inline = cx.meta_word(span, InternedString::new("inline"));
     let attrs = vec!(cx.attribute(span, inline));
diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs
index 6425e6a28ec..175f986f6dd 100644
--- a/src/libsyntax/ext/deriving/encodable.rs
+++ b/src/libsyntax/ext/deriving/encodable.rs
@@ -97,33 +97,30 @@ use ext::deriving::generic::ty::*;
 use parse::token;
 use ptr::P;
 
-pub fn expand_deriving_rustc_encodable<F>(cx: &mut ExtCtxt,
-                                          span: Span,
-                                          mitem: &MetaItem,
-                                          item: &Item,
-                                          push: F) where
-    F: FnOnce(P<Item>),
+pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt,
+                                       span: Span,
+                                       mitem: &MetaItem,
+                                       item: &Item,
+                                       push: &mut FnMut(P<Item>))
 {
     expand_deriving_encodable_imp(cx, span, mitem, item, push, "rustc_serialize")
 }
 
-pub fn expand_deriving_encodable<F>(cx: &mut ExtCtxt,
-                                    span: Span,
-                                    mitem: &MetaItem,
-                                    item: &Item,
-                                    push: F) where
-    F: FnOnce(P<Item>),
+pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
+                                 span: Span,
+                                 mitem: &MetaItem,
+                                 item: &Item,
+                                 push: &mut FnMut(P<Item>))
 {
     expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize")
 }
 
-fn expand_deriving_encodable_imp<F>(cx: &mut ExtCtxt,
-                                    span: Span,
-                                    mitem: &MetaItem,
-                                    item: &Item,
-                                    push: F,
-                                    krate: &'static str) where
-    F: FnOnce(P<Item>),
+fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
+                                 span: Span,
+                                 mitem: &MetaItem,
+                                 item: &Item,
+                                 push: &mut FnMut(P<Item>),
+                                 krate: &'static str)
 {
     if !cx.use_std {
         // FIXME(#21880): lift this requirement.
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index 7f6f29df530..4685b4b2954 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -375,12 +375,11 @@ fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec<P<ast
 }
 
 impl<'a> TraitDef<'a> {
-    pub fn expand<F>(&self,
-                     cx: &mut ExtCtxt,
-                     mitem: &ast::MetaItem,
-                     item: &ast::Item,
-                     push: F) where
-        F: FnOnce(P<ast::Item>),
+    pub fn expand(&self,
+                  cx: &mut ExtCtxt,
+                  mitem: &ast::MetaItem,
+                  item: &ast::Item,
+                  push: &mut FnMut(P<ast::Item>))
     {
         let newitem = match item.node {
             ast::ItemStruct(ref struct_def, ref generics) => {
diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs
index da80c7a0e6d..2f6734b1a14 100644
--- a/src/libsyntax/ext/deriving/hash.rs
+++ b/src/libsyntax/ext/deriving/hash.rs
@@ -16,12 +16,11 @@ use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
 use ptr::P;
 
-pub fn expand_deriving_hash<F>(cx: &mut ExtCtxt,
-                               span: Span,
-                               mitem: &MetaItem,
-                               item: &Item,
-                               push: F) where
-    F: FnOnce(P<Item>),
+pub fn expand_deriving_hash(cx: &mut ExtCtxt,
+                            span: Span,
+                            mitem: &MetaItem,
+                            item: &Item,
+                            push: &mut FnMut(P<Item>))
 {
 
     let path = Path::new_(pathvec_std!(cx, core::hash::Hash), None,
diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs
index 65554efdd68..a3725355840 100644
--- a/src/libsyntax/ext/deriving/mod.rs
+++ b/src/libsyntax/ext/deriving/mod.rs
@@ -65,14 +65,14 @@ pub mod show;
 pub mod default;
 pub mod primitive;
 
+#[path="cmp/partial_eq.rs"]
+pub mod partial_eq;
 #[path="cmp/eq.rs"]
 pub mod eq;
-#[path="cmp/totaleq.rs"]
-pub mod totaleq;
+#[path="cmp/partial_ord.rs"]
+pub mod partial_ord;
 #[path="cmp/ord.rs"]
 pub mod ord;
-#[path="cmp/totalord.rs"]
-pub mod totalord;
 
 
 pub mod generic;
@@ -118,7 +118,7 @@ fn expand_derive(cx: &mut ExtCtxt,
 }
 
 macro_rules! derive_traits {
-    ($( $name:expr => $func:path, )*) => {
+    ($( $name:expr => $func:path, )+) => {
         pub fn register_all(env: &mut SyntaxEnv) {
             // Define the #[derive_*] extensions.
             $({
@@ -132,13 +132,13 @@ macro_rules! derive_traits {
                               item: &Item,
                               push: &mut FnMut(P<Item>)) {
                         warn_if_deprecated(ecx, sp, $name);
-                        $func(ecx, sp, mitem, item, |i| push(i));
+                        $func(ecx, sp, mitem, item, push);
                     }
                 }
 
                 env.insert(intern(concat!("derive_", $name)),
                            Decorator(Box::new(DeriveExtension)));
-            })*
+            })+
 
             env.insert(intern("derive"),
                        Modifier(Box::new(expand_derive)));
@@ -146,7 +146,7 @@ macro_rules! derive_traits {
 
         fn is_builtin_trait(name: &str) -> bool {
             match name {
-                $( $name )|* => true,
+                $( $name )|+ => true,
                 _ => false,
             }
         }
@@ -162,10 +162,10 @@ derive_traits! {
 
     "RustcDecodable" => decodable::expand_deriving_rustc_decodable,
 
-    "PartialEq" => eq::expand_deriving_eq,
-    "Eq" => totaleq::expand_deriving_totaleq,
-    "PartialOrd" => ord::expand_deriving_ord,
-    "Ord" => totalord::expand_deriving_totalord,
+    "PartialEq" => partial_eq::expand_deriving_partial_eq,
+    "Eq" => eq::expand_deriving_eq,
+    "PartialOrd" => partial_ord::expand_deriving_partial_ord,
+    "Ord" => ord::expand_deriving_ord,
 
     "Debug" => show::expand_deriving_show,
 
diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs
index b2d0a9f6b51..625f759fced 100644
--- a/src/libsyntax/ext/deriving/primitive.rs
+++ b/src/libsyntax/ext/deriving/primitive.rs
@@ -18,12 +18,11 @@ use ext::deriving::generic::ty::*;
 use parse::token::InternedString;
 use ptr::P;
 
-pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt,
-                                         span: Span,
-                                         mitem: &MetaItem,
-                                         item: &Item,
-                                         push: F) where
-    F: FnOnce(P<Item>),
+pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
+                                      span: Span,
+                                      mitem: &MetaItem,
+                                      item: &Item,
+                                      push: &mut FnMut(P<Item>))
 {
     let inline = cx.meta_word(span, InternedString::new("inline"));
     let attrs = vec!(cx.attribute(span, inline));
diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs
index ae9a4020060..f3b0e8a7681 100644
--- a/src/libsyntax/ext/deriving/show.rs
+++ b/src/libsyntax/ext/deriving/show.rs
@@ -18,12 +18,11 @@ use ext::deriving::generic::ty::*;
 use parse::token;
 use ptr::P;
 
-pub fn expand_deriving_show<F>(cx: &mut ExtCtxt,
-                               span: Span,
-                               mitem: &MetaItem,
-                               item: &Item,
-                               push: F) where
-    F: FnOnce(P<Item>),
+pub fn expand_deriving_show(cx: &mut ExtCtxt,
+                            span: Span,
+                            mitem: &MetaItem,
+                            item: &Item,
+                            push: &mut FnMut(P<Item>))
 {
     // &mut ::std::fmt::Formatter
     let fmtr = Ptr(box Literal(path_std!(cx, core::fmt::Formatter)),