Skip to content

Commit edcc02b

Browse files
committed
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.
1 parent 57e0a7e commit edcc02b

File tree

3 files changed

+35
-24
lines changed

3 files changed

+35
-24
lines changed

src/libsyntax_ext/deriving/cmp/partial_eq.rs

+1-17
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,13 @@
1111
use deriving::generic::*;
1212
use deriving::generic::ty::*;
1313

14-
use syntax::ast::{MetaItem, Expr, BinOpKind, ItemKind};
14+
use syntax::ast::{MetaItem, Expr, BinOpKind};
1515
use syntax::codemap::Span;
1616
use syntax::ext::base::{ExtCtxt, Annotatable};
1717
use syntax::ext::build::AstBuilder;
1818
use syntax::parse::token::InternedString;
1919
use syntax::ptr::P;
2020

21-
fn is_type_without_fields(item: &Annotatable) -> bool {
22-
if let Annotatable::Item(ref item) = *item {
23-
match item.node {
24-
ItemKind::Enum(ref enum_def, _) => {
25-
enum_def.variants.iter().all(|v| v.node.data.fields().is_empty())
26-
}
27-
ItemKind::Struct(ref variant_data, _) => {
28-
variant_data.fields().is_empty()
29-
}
30-
_ => false
31-
}
32-
} else {
33-
false
34-
}
35-
}
36-
3721
pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
3822
span: Span,
3923
mitem: &MetaItem,

src/libsyntax_ext/deriving/cmp/partial_ord.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,29 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
6767
}))
6868
};
6969

70+
// avoid defining extra methods if we can
71+
// c-like enums, enums without any fields and structs without fields
72+
// can safely define only `partial_cmp`.
73+
let methods = if is_type_without_fields(item) {
74+
vec![partial_cmp_def]
75+
} else {
76+
vec![
77+
partial_cmp_def,
78+
md!("lt", true, false),
79+
md!("le", true, true),
80+
md!("gt", false, false),
81+
md!("ge", false, true)
82+
]
83+
};
84+
7085
let trait_def = TraitDef {
7186
span: span,
7287
attributes: vec![],
7388
path: path_std!(cx, core::cmp::PartialOrd),
7489
additional_bounds: vec![],
7590
generics: LifetimeBounds::empty(),
7691
is_unsafe: false,
77-
methods: vec![
78-
partial_cmp_def,
79-
md!("lt", true, false),
80-
md!("le", true, true),
81-
md!("gt", false, false),
82-
md!("ge", false, true)
83-
],
92+
methods: methods,
8493
associated_types: Vec::new(),
8594
};
8695
trait_def.expand(cx, mitem, item, push)

src/libsyntax_ext/deriving/generic/mod.rs

+18
Original file line numberDiff line numberDiff line change
@@ -1638,3 +1638,21 @@ pub fn cs_same_method<F>(f: F,
16381638
}
16391639
}
16401640
}
1641+
1642+
/// Return true if the type has no value fields
1643+
/// (for an enum, no variant has any fields)
1644+
pub fn is_type_without_fields(item: &Annotatable) -> bool {
1645+
if let Annotatable::Item(ref item) = *item {
1646+
match item.node {
1647+
ast::ItemKind::Enum(ref enum_def, _) => {
1648+
enum_def.variants.iter().all(|v| v.node.data.fields().is_empty())
1649+
}
1650+
ast::ItemKind::Struct(ref variant_data, _) => {
1651+
variant_data.fields().is_empty()
1652+
}
1653+
_ => false
1654+
}
1655+
} else {
1656+
false
1657+
}
1658+
}

0 commit comments

Comments
 (0)