Auto merge of #31977 - bluss:partial-eq-save, r=brson

derive: Avoid emitting provided PartialEq, PartialOrd methods for c-like enums

derive: Avoid emitting provided PartialEq, PartialOrd method for c-like enums

`ne` is completely symmetrical with the method `eq`, and we can save
rust code size and compilation time here if we only emit one of them
when possible.

One case where it's easy to recognize is when it's a C-like enum. Most
other cases can not omit ne, because any value field may have a custom
PartialEq implementation.
This commit is contained in:
bors 2016-03-18 14:36:49 -07:00
commit 02954ae0a8
3 changed files with 43 additions and 11 deletions

View File

@ -80,6 +80,14 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
} }
}
// avoid defining `ne` if we can
// c-like enums, enums without any fields and structs without fields
// can safely define only `eq`.
let mut methods = vec![md!("eq", cs_eq)];
if !is_type_without_fields(item) {
methods.push(md!("ne", cs_ne));
}
let trait_def = TraitDef {
span: span,
attributes: Vec::new(),
@ -87,10 +95,7 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
additional_bounds: Vec::new(),
generics: LifetimeBounds::empty(),
is_unsafe: false,
methods: vec!(
md!("eq", cs_eq),
md!("ne", cs_ne)
),
methods: methods,
associated_types: Vec::new(),
};
trait_def.expand(cx, mitem, item, push)

View File

@ -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)

View File

@ -1647,3 +1647,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
}
}