about summary refs log tree commit diff
path: root/src/libsyntax_ext
diff options
context:
space:
mode:
authorUlrik Sverdrup <bluss@users.noreply.github.com>2016-03-01 02:27:27 +0100
committerUlrik Sverdrup <bluss@users.noreply.github.com>2016-03-01 02:27:27 +0100
commitedcc02bfee262ce8bc3f087d9793ce68d73b1a40 (patch)
tree209c1bbe422feed715024758bcbb7176227c549b /src/libsyntax_ext
parent57e0a7e5d8872c8fcea47fc20239b8921bda2576 (diff)
downloadrust-edcc02bfee262ce8bc3f087d9793ce68d73b1a40.tar.gz
rust-edcc02bfee262ce8bc3f087d9793ce68d73b1a40.zip
derive: Emit only PartialOrd::partial_cmp for simple enums
Using the same logic as for `PartialEq`, when possible define only
`partial_cmp` and leave `lt, le, gt, ge` to their default
implementations. This works well for c-like enums.
Diffstat (limited to 'src/libsyntax_ext')
-rw-r--r--src/libsyntax_ext/deriving/cmp/partial_eq.rs18
-rw-r--r--src/libsyntax_ext/deriving/cmp/partial_ord.rs23
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs18
3 files changed, 35 insertions, 24 deletions
diff --git a/src/libsyntax_ext/deriving/cmp/partial_eq.rs b/src/libsyntax_ext/deriving/cmp/partial_eq.rs
index 24444c3c39b..6406ee59a5e 100644
--- a/src/libsyntax_ext/deriving/cmp/partial_eq.rs
+++ b/src/libsyntax_ext/deriving/cmp/partial_eq.rs
@@ -11,29 +11,13 @@
 use deriving::generic::*;
 use deriving::generic::ty::*;
 
-use syntax::ast::{MetaItem, Expr, BinOpKind, ItemKind};
+use syntax::ast::{MetaItem, Expr, BinOpKind};
 use syntax::codemap::Span;
 use syntax::ext::base::{ExtCtxt, Annotatable};
 use syntax::ext::build::AstBuilder;
 use syntax::parse::token::InternedString;
 use syntax::ptr::P;
 
-fn is_type_without_fields(item: &Annotatable) -> bool {
-    if let Annotatable::Item(ref item) = *item {
-        match item.node {
-            ItemKind::Enum(ref enum_def, _) => {
-                enum_def.variants.iter().all(|v| v.node.data.fields().is_empty())
-            }
-            ItemKind::Struct(ref variant_data, _) => {
-                variant_data.fields().is_empty()
-            }
-            _ => false
-        }
-    } else {
-        false
-    }
-}
-
 pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
                                   span: Span,
                                   mitem: &MetaItem,
diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
index e857f7d52f9..fafcf0ea960 100644
--- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs
+++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
@@ -67,6 +67,21 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
         }))
     };
 
+    // avoid defining extra methods if we can
+    // c-like enums, enums without any fields and structs without fields
+    // can safely define only `partial_cmp`.
+    let methods = if is_type_without_fields(item) {
+        vec![partial_cmp_def]
+    } else {
+        vec![
+            partial_cmp_def,
+            md!("lt", true, false),
+            md!("le", true, true),
+            md!("gt", false, false),
+            md!("ge", false, true)
+        ]
+    };
+
     let trait_def = TraitDef {
         span: span,
         attributes: vec![],
@@ -74,13 +89,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
         additional_bounds: vec![],
         generics: LifetimeBounds::empty(),
         is_unsafe: false,
-        methods: vec![
-            partial_cmp_def,
-            md!("lt", true, false),
-            md!("le", true, true),
-            md!("gt", false, false),
-            md!("ge", false, true)
-        ],
+        methods: methods,
         associated_types: Vec::new(),
     };
     trait_def.expand(cx, mitem, item, push)
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index c0237a5d29a..e8954b1a2fc 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -1638,3 +1638,21 @@ pub fn cs_same_method<F>(f: F,
         }
     }
 }
+
+/// Return true if the type has no value fields
+/// (for an enum, no variant has any fields)
+pub fn is_type_without_fields(item: &Annotatable) -> bool {
+    if let Annotatable::Item(ref item) = *item {
+        match item.node {
+            ast::ItemKind::Enum(ref enum_def, _) => {
+                enum_def.variants.iter().all(|v| v.node.data.fields().is_empty())
+            }
+            ast::ItemKind::Struct(ref variant_data, _) => {
+                variant_data.fields().is_empty()
+            }
+            _ => false
+        }
+    } else {
+        false
+    }
+}