]> git.lizzy.rs Git - enumset.git/commitdiff
Add `no_super_impls` option to `EnumSetType` derive.
authorahcodedthat <83854662+ahcodedthat@users.noreply.github.com>
Mon, 4 Apr 2022 02:48:21 +0000 (19:48 -0700)
committerahcodedthat <83854662+ahcodedthat@users.noreply.github.com>
Mon, 4 Apr 2022 02:48:21 +0000 (19:48 -0700)
enumset/src/lib.rs
enumset/tests/ops.rs
enumset_derive/src/lib.rs

index ab3b76c0efbde8554a14e63bb05ad1e00e84d03e..b5656aa0791524370a2764dceedb44af7e1432ca 100644 (file)
@@ -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
index 72c05e0db14460745ca75c3f4c82a0c2eb43de0f..b76881e3df25b8d5f2edec352c7475f4ceeadd13 100644 (file)
@@ -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));
index a25e94eab5f701e3634461c8bce1d77bb44e66f2..50fad1a6bd914d7100f37c58e24e1e8631610f9a 100644 (file)
@@ -20,6 +20,7 @@ fn error<T>(span: Span, message: &str) -> Result<T> {
 #[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.