From: ahcodedthat <83854662+ahcodedthat@users.noreply.github.com> Date: Mon, 4 Apr 2022 02:48:21 +0000 (-0700) Subject: Add `no_super_impls` option to `EnumSetType` derive. X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=7fe79c8340d7237c93a9c3b579977ed75d59cb0a;p=enumset.git Add `no_super_impls` option to `EnumSetType` derive. --- diff --git a/enumset/src/lib.rs b/enumset/src/lib.rs index ab3b76c..b5656aa 100644 --- a/enumset/src/lib.rs +++ b/enumset/src/lib.rs @@ -143,7 +143,12 @@ use crate::repr::EnumSetTypeRepr; /// annotation to the enum. /// /// The custom derive for `EnumSetType` automatically implements [`Copy`], [`Clone`], [`Eq`], and -/// [`PartialEq`] on the enum. These are required for the [`EnumSet`] to function. +/// [`PartialEq`] on the enum. These are required for the [`EnumSet`] to function. These automatic +/// implementations can be disabled by adding an `#[enumset(no_super_impls)]` annotation to +/// the enum, but they must still be implemented. Disabling the automatic implementations can be +/// useful if, for example, you are using a code generator that already derives these traits. Note +/// that the `PartialEq` implementation, if not derived, **must** produce the same results as a +/// derived implementation would, or else `EnumSet` will not work correctly. /// /// In addition, if you have renamed the `enumset` crate in your crate, you can use the /// `#[enumset(crate_name = "enumset2")]` attribute to tell the custom derive to use that name diff --git a/enumset/tests/ops.rs b/enumset/tests/ops.rs index 72c05e0..b76881e 100644 --- a/enumset/tests/ops.rs +++ b/enumset/tests/ops.rs @@ -15,6 +15,11 @@ pub enum Enum1 { pub enum SmallEnum { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, } +#[derive(Clone, Copy, Debug, EnumSetType, Eq, PartialEq)] +#[enumset(no_super_impls)] +pub enum SmallEnumExplicitDerive { + A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, +} #[derive(EnumSetType, Debug)] pub enum LargeEnum { _00, _01, _02, _03, _04, _05, _06, _07, @@ -86,6 +91,9 @@ macro_rules! test_variants { test_variants! { SmallEnum small_enum_all_empty A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, } +test_variants! { SmallEnumExplicitDerive small_enum_explicit_derive_all_empty + A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, +} test_variants! { LargeEnum large_enum_all_empty _00, _01, _02, _03, _04, _05, _06, _07, _10, _11, _12, _13, _14, _15, _16, _17, @@ -317,10 +325,10 @@ macro_rules! test_enum { assert!(!$set.contains(&SET_TEST_E)); }} } - + let mut hash_set = HashSet::new(); test_set!(hash_set); - + let mut tree_set = BTreeSet::new(); test_set!(tree_set); } @@ -353,6 +361,7 @@ macro_rules! tests { } tests!(small_enum, test_enum!(SmallEnum, 4)); +tests!(small_enum_explicit_derive, test_enum!(SmallEnumExplicitDerive, 4)); tests!(large_enum, test_enum!(LargeEnum, 16)); tests!(enum8, test_enum!(Enum8, 1)); tests!(enum128, test_enum!(Enum128, 16)); diff --git a/enumset_derive/src/lib.rs b/enumset_derive/src/lib.rs index a25e94e..50fad1a 100644 --- a/enumset_derive/src/lib.rs +++ b/enumset_derive/src/lib.rs @@ -20,6 +20,7 @@ fn error(span: Span, message: &str) -> Result { #[darling(attributes(enumset), default)] struct EnumsetAttrs { no_ops: bool, + no_super_impls: bool, serialize_as_list: bool, serialize_deny_unknown: bool, #[darling(default)] @@ -63,6 +64,8 @@ struct EnumSetInfo { /// Avoid generating operator overloads on the enum type. no_ops: bool, + /// Avoid generating implementations for `Clone`, `Copy`, `Eq`, and `PartialEq`. + no_super_impls: bool, /// Serialize the enum as a list. serialize_as_list: bool, /// Disallow unknown bits while deserializing the enum. @@ -82,6 +85,7 @@ impl EnumSetInfo { used_variant_names: HashSet::new(), used_discriminants: HashSet::new(), no_ops: attrs.no_ops, + no_super_impls: attrs.no_super_impls, serialize_as_list: attrs.serialize_as_list, serialize_deny_unknown: attrs.serialize_deny_unknown } @@ -438,6 +442,25 @@ fn enum_set_type_impl(info: EnumSetInfo) -> SynTokenStream { quote! { 1 << self as #repr } }; + let super_impls = if info.no_super_impls { + quote! {} + } else { + quote! { + impl #core::cmp::PartialEq for #name { + fn eq(&self, other: &Self) -> bool { + #eq_impl + } + } + impl #core::cmp::Eq for #name { } + impl #core::clone::Clone for #name { + fn clone(&self) -> Self { + *self + } + } + impl #core::marker::Copy for #name { } + } + }; + quote! { unsafe impl #enumset::__internal::EnumSetTypePrivate for #name { type Repr = #repr; @@ -448,18 +471,7 @@ fn enum_set_type_impl(info: EnumSetInfo) -> SynTokenStream { unsafe impl #enumset::EnumSetType for #name { } - impl #core::cmp::PartialEq for #name { - fn eq(&self, other: &Self) -> bool { - #eq_impl - } - } - impl #core::cmp::Eq for #name { } - impl #core::clone::Clone for #name { - fn clone(&self) -> Self { - *self - } - } - impl #core::marker::Copy for #name { } + #super_impls impl #name { /// Creates a new enumset with only this variant.