diff options
| author | bors <bors@rust-lang.org> | 2016-03-18 14:36:49 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2016-03-18 14:36:49 -0700 |
| commit | 02954ae0a86c5c2f00e9e06b520999c1e67e9cd7 (patch) | |
| tree | 82dbdf0e43aa662e476a1e2d609f29ec10ca9c64 /src/libsyntax_ext | |
| parent | fc9e1d0f55f721461b73628f12cf64de31be55af (diff) | |
| parent | edcc02bfee262ce8bc3f087d9793ce68d73b1a40 (diff) | |
| download | rust-02954ae0a86c5c2f00e9e06b520999c1e67e9cd7.tar.gz rust-02954ae0a86c5c2f00e9e06b520999c1e67e9cd7.zip | |
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.
Diffstat (limited to 'src/libsyntax_ext')
| -rw-r--r-- | src/libsyntax_ext/deriving/cmp/partial_eq.rs | 13 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/cmp/partial_ord.rs | 23 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/generic/mod.rs | 18 |
3 files changed, 43 insertions, 11 deletions
diff --git a/src/libsyntax_ext/deriving/cmp/partial_eq.rs b/src/libsyntax_ext/deriving/cmp/partial_eq.rs index 0150a073b07..6406ee59a5e 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_eq.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_eq.rs @@ -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) diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs index c864ce0db51..e49c77285ab 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 ef7f455632c..6654afd3664 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -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 + } +} |
