Repository: Peternator7/strum
Pull request #75 (2019-11-06 23:19:38)

Const enum variants names
I tried to write code like this:
```rust
pub const LETTERS: &'static [&'static str] = Letter::variants();

#[derive(EnumVariantNames)]
pub enum Letter { A, B, C }
```
But I've found that `variants` fn is not `const`.

This pr changes the behaviour of `EnumVariantNames` in that way:
1. Add `pub const VARIANTS: &'static [&'static str] = ...` to enum
2. make `variants` fn `const`
3. deprecate `variants` fn with a message like ``"Use `Letter::VARIANTS` instead"``

hobofan: > deprecate variants fn with a message like "Use `Letter::VARIANTS` instead"

Why deprecate the function if you made the access via the function const too?
WaffleLapkin: Because I see no reasons to use the function, when you can use associated constant.
Peternator7: Thanks for the PR! Sorry I thought I responded to this last week, but it looks like I forgot to. Based on #74, I don't think we should deprecate the function because it will be extracted into a trait, and those can't be `const` yet.

Let's definitely get the associated constant added though :)
WaffleLapkin: > Based on #74, I don't think we should deprecate the function because it will be extracted into a trait, and those can't be const yet.

So I must undeprecate `variants` and make it non-`const` again? Ok, I'll make these changes tomorrow :)
Peternator7: Thanks! Merging #74 created a conflict so here's the resolution you'll want in the enum variants file. 

```rust
    quote! {
        impl #impl_generics ::strum::VariantNames for #name #ty_generics #where_clause {
            /// Return a slice containing the names of the variants of this enum
            #[allow(dead_code)]
            fn variants() -> &'static [&'static str] {
                Self::VARIANTS
            }
        }

        impl #impl_generics #name #ty_generics #where_clause {
            /// Names of the variants of this enum
            #[allow(dead_code)]
            pub const VARIANTS: &'static [&'static str] = &[ #(#names),* ];
        }
    }
```
WaffleLapkin: @Peternator7 shouldn't I add `VARIANTS` const to the trait?
Peternator7: @WaffleLapkin, that would be preferred, but if I remember correctly, const in traits isn't supported on stable yet :(
WaffleLapkin: @Peternator7 `const` in traits [is supported] on stable

[is supported]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b6ac0c13065e798fbc51a43378ab649b
WaffleLapkin: @Peternator7 I've added `VARIANTS` const to `VariantNames` trait and it seems like there is still no need in `variants` function... Am I wrong?
WaffleLapkin: @Peternator7 ping

Patch:
diff --git a/README.md b/README.md
index 75ecd2d..14531cb 100644
--- a/README.md
+++ b/README.md
@@ -50,7 +50,7 @@ Strum has implemented the following macros:
 | [EnumProperty] | Add custom properties to enum variants. |
 | [EnumMessage] | Add a verbose message to an enum variant. |
 | [EnumDiscriminants] | Generate a new type with only the discriminant names. |
-| [EnumCount] | Add a constant `usize` equal to the number of variantes. |
+| [EnumCount] | Add a constant `usize` equal to the number of variants. |
 
 # Contributing
 
diff --git a/strum/src/lib.rs b/strum/src/lib.rs
index fb36882..7254479 100644
--- a/strum/src/lib.rs
+++ b/strum/src/lib.rs
@@ -221,7 +221,8 @@ pub trait EnumCount {
 /// A trait for retrieving the names of each variant in Enum. This trait can
 /// be autoderived by `strum_macros`.
 pub trait VariantNames {
-    fn variants() -> &'static [&'static str];
+    /// Names of the variants of this enum
+    const VARIANTS: &'static [&'static str];
 }
 
 #[cfg(feature = "derive")]
diff --git a/strum_macros/src/macros/enum_variant_names.rs b/strum_macros/src/macros/enum_variant_names.rs
index 0bc550e..ae6dcd7 100644
--- a/strum_macros/src/macros/enum_variant_names.rs
+++ b/strum_macros/src/macros/enum_variant_names.rs
@@ -26,13 +26,7 @@ pub fn enum_variant_names_inner(ast: &syn::DeriveInput) -> TokenStream {
 
     quote! {
         impl #impl_generics ::strum::VariantNames for #name #ty_generics #where_clause {
-            /// Return a slice containing the names of the variants of this enum
-            #[allow(dead_code)]
-            fn variants() -> &'static [&'static str] {
-                &[
-                    #(#names),*
-                ]
-            }
+            const VARIANTS: &'static [&'static str] = &[ #(#names),* ];
         }
     }
 }


Test patch:
diff --git a/strum_tests/tests/enum_variant_names.rs b/strum_tests/tests/enum_variant_names.rs
index f5f78ce..37d8758 100644
--- a/strum_tests/tests/enum_variant_names.rs
+++ b/strum_tests/tests/enum_variant_names.rs
@@ -15,7 +15,7 @@ fn simple() {
         Yellow,
     }
 
-    assert_eq!(&Color::variants(), &["Red", "Blue", "Yellow"]);
+    assert_eq!(Color::VARIANTS, &["Red", "Blue", "Yellow"]);
 }
 
 #[test]
@@ -29,7 +29,7 @@ fn variant_names_trait() {
     }
 
     fn generic_function<T: VariantNames>() {
-        assert_eq!(T::variants(), &["Red", "Blue", "Yellow"]);
+        assert_eq!(T::VARIANTS, &["Red", "Blue", "Yellow"]);
     }
 
     generic_function::<Color>();
@@ -47,10 +47,7 @@ fn plain_kebab() {
         RebeccaPurple,
     }
 
-    assert_eq!(
-        &Color::variants(),
-        &["red", "blue", "yellow", "rebecca-purple"]
-    );
+    assert_eq!(Color::VARIANTS, &["red", "blue", "yellow", "rebecca-purple"]);
 }
 
 #[test]
@@ -66,7 +63,7 @@ fn non_plain_camel() {
     }
 
     assert_eq!(
-        &Color::variants(),
+        Color::VARIANTS,
         &["deep-pink", "green-yellow", "cornflower-blue", "other"]
     );
 }
@@ -83,14 +80,14 @@ fn clap_and_structopt() {
     }
 
     assert_eq!(
-        &Color::variants(),
+        Color::VARIANTS,
         &["red", "blue", "yellow", "rebecca-purple"]
     );
 
     let _clap_example = clap::App::new("app").arg(
         clap::Arg::with_name("color")
             .long("color")
-            .possible_values(Color::variants())
+            .possible_values(Color::VARIANTS)
             .case_insensitive(true),
     );
 
@@ -101,7 +98,7 @@ fn clap_and_structopt() {
         #[structopt(
             long = "color",
             default_value = "Color::Blue",
-            raw(possible_values = "Color::variants()")
+            raw(possible_values = "Color::VARIANTS")
         )]
         color: Color,
     }