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.
This commit is contained in:
parent
57e0a7e5d8
commit
edcc02bfee
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user