Repository: clap-rs/clap
Pull request #3799 (2022-06-08 16:01:34)

fix(derive): Clarify ArgEnum as ValueEnum
We aren't enumerating arguments but values for an argument, so the name
should reflect that.

This will be important as part of #1807 when we have more specific
attribute names.

<!--
Thanks for helping out!

Please link the appropriate issue from your PR.

If you don't have an issue, we'd recommend starting with one first so the PR can focus on the
implementation (unless its an obvious bug or documentation fix that will have
little conversation).
-->



Patch:
diff --git a/clap_complete/src/shells/shell.rs b/clap_complete/src/shells/shell.rs
index b8268639..9621f741 100644
--- a/clap_complete/src/shells/shell.rs
+++ b/clap_complete/src/shells/shell.rs
@@ -23,8 +23,8 @@ pub enum Shell {
 }
 
 impl Shell {
-    /// Deprecated, replaced with [`ArgEnumValueParser`][clap::builder::ArgEnumValueParser]
-    #[deprecated(since = "3.2.0", note = "Replaced with `ArgEnumValueParser`")]
+    /// Deprecated, replaced with [`EnumValueParser`][clap::builder::EnumValueParser]
+    #[deprecated(since = "3.2.0", note = "Replaced with `EnumValueParser`")]
     pub fn possible_values() -> impl Iterator<Item = PossibleValue<'static>> {
         Shell::value_variants()
             .iter()
diff --git a/clap_derive/src/attrs.rs b/clap_derive/src/attrs.rs
index ed5c581a..612fde30 100644
--- a/clap_derive/src/attrs.rs
+++ b/clap_derive/src/attrs.rs
@@ -486,7 +486,7 @@ impl Attrs {
                     self.push_method(ident, self.name.clone().translate(*self.env_casing));
                 }
 
-                ArgEnum(_) => self.is_enum = true,
+                ValueEnum(_) => self.is_enum = true,
 
                 FromGlobal(ident) => {
                     let ty = Sp::call_site(Ty::Other);
@@ -536,11 +536,11 @@ impl Attrs {
                         quote!(<#ty as ::std::default::Default>::default())
                     };
 
-                    let val = if parsed.iter().any(|a| matches!(a, ArgEnum(_))) {
+                    let val = if parsed.iter().any(|a| matches!(a, ValueEnum(_))) {
                         quote_spanned!(ident.span()=> {
                             {
                                 let val: #ty = #val;
-                                clap::ArgEnum::to_possible_value(&val).unwrap().get_name()
+                                clap::ValueEnum::to_possible_value(&val).unwrap().get_name()
                             }
                         })
                     } else {
@@ -579,11 +579,11 @@ impl Attrs {
                         quote!(<#ty as ::std::default::Default>::default())
                     };
 
-                    let val = if parsed.iter().any(|a| matches!(a, ArgEnum(_))) {
+                    let val = if parsed.iter().any(|a| matches!(a, ValueEnum(_))) {
                         quote_spanned!(ident.span()=> {
                             {
                                 let val: #ty = #val;
-                                clap::ArgEnum::to_possible_value(&val).unwrap().get_name()
+                                clap::ValueEnum::to_possible_value(&val).unwrap().get_name()
                             }
                         })
                     } else {
diff --git a/clap_derive/src/derives/arg_enum.rs b/clap_derive/src/derives/arg_enum.rs
index 77067e90..9ba0ac68 100644
--- a/clap_derive/src/derives/arg_enum.rs
+++ b/clap_derive/src/derives/arg_enum.rs
@@ -29,7 +29,7 @@ pub fn derive_arg_enum(input: &DeriveInput) -> TokenStream {
 
     match input.data {
         Data::Enum(ref e) => gen_for_enum(ident, &input.attrs, e),
-        _ => abort_call_site!("`#[derive(ArgEnum)]` only supports enums"),
+        _ => abort_call_site!("`#[derive(ValueEnum)]` only supports enums"),
     }
 }
 
@@ -60,7 +60,7 @@ pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStr
             clippy::suspicious_else_formatting,
         )]
         #[deny(clippy::correctness)]
-        impl clap::ArgEnum for #name {
+        impl clap::ValueEnum for #name {
             #value_variants
             #to_possible_value
         }
@@ -83,7 +83,7 @@ fn lits(
                 None
             } else {
                 if !matches!(variant.fields, Fields::Unit) {
-                    abort!(variant.span(), "`#[derive(ArgEnum)]` only supports non-unit variants, unless they are skipped");
+                    abort!(variant.span(), "`#[derive(ValueEnum)]` only supports non-unit variants, unless they are skipped");
                 }
                 let fields = attrs.field_methods(false);
                 let name = attrs.cased_name();
diff --git a/clap_derive/src/derives/args.rs b/clap_derive/src/derives/args.rs
index 345a68e7..6fbe94a8 100644
--- a/clap_derive/src/derives/args.rs
+++ b/clap_derive/src/derives/args.rs
@@ -426,7 +426,7 @@ pub fn gen_augment(
 
 fn gen_arg_enum_possible_values(ty: &Type) -> TokenStream {
     quote_spanned! { ty.span()=>
-        .possible_values(<#ty as clap::ArgEnum>::value_variants().iter().filter_map(clap::ArgEnum::to_possible_value))
+        .possible_values(<#ty as clap::ValueEnum>::value_variants().iter().filter_map(clap::ValueEnum::to_possible_value))
     }
 }
 
@@ -643,7 +643,7 @@ fn gen_parsers(
         let ci = attrs.ignore_case();
 
         parse = quote_spanned! { convert_type.span()=>
-            |s| <#convert_type as clap::ArgEnum>::from_str(s, #ci).map_err(|err| clap::Error::raw(clap::ErrorKind::ValueValidation, format!("Invalid value for {}: {}", #id, err)))
+            |s| <#convert_type as clap::ValueEnum>::from_str(s, #ci).map_err(|err| clap::Error::raw(clap::ErrorKind::ValueValidation, format!("Invalid value for {}: {}", #id, err)))
         }
     }
 
diff --git a/clap_derive/src/dummies.rs b/clap_derive/src/dummies.rs
index be158306..a046483b 100644
--- a/clap_derive/src/dummies.rs
+++ b/clap_derive/src/dummies.rs
@@ -76,7 +76,7 @@ pub fn args(name: &Ident) {
 
 pub fn arg_enum(name: &Ident) {
     append_dummy(quote! {
-        impl clap::ArgEnum for #name {
+        impl clap::ValueEnum for #name {
             fn value_variants<'a>() -> &'a [Self]{
                 unimplemented!()
             }
diff --git a/clap_derive/src/lib.rs b/clap_derive/src/lib.rs
index 973b61e1..b12515ac 100644
--- a/clap_derive/src/lib.rs
+++ b/clap_derive/src/lib.rs
@@ -28,7 +28,15 @@ mod dummies;
 mod parse;
 mod utils;
 
-/// Generates the `ArgEnum` impl.
+/// Generates the `ValueEnum` impl.
+#[proc_macro_derive(ValueEnum, attributes(clap))]
+#[proc_macro_error]
+pub fn value_enum(input: TokenStream) -> TokenStream {
+    let input: DeriveInput = parse_macro_input!(input);
+    derives::derive_arg_enum(&input).into()
+}
+
+/// Generates the `ValueEnum` impl.
 #[proc_macro_derive(ArgEnum, attributes(clap))]
 #[proc_macro_error]
 pub fn arg_enum(input: TokenStream) -> TokenStream {
diff --git a/clap_derive/src/parse.rs b/clap_derive/src/parse.rs
index 15cd3e0f..253736cf 100644
--- a/clap_derive/src/parse.rs
+++ b/clap_derive/src/parse.rs
@@ -30,7 +30,7 @@ pub enum ClapAttr {
     Action(Ident),
     Env(Ident),
     Flatten(Ident),
-    ArgEnum(Ident),
+    ValueEnum(Ident),
     FromGlobal(Ident),
     Subcommand(Ident),
     VerbatimDocComment(Ident),
@@ -188,7 +188,8 @@ impl Parse for ClapAttr {
                 "action" => Ok(Action(name)),
                 "env" => Ok(Env(name)),
                 "flatten" => Ok(Flatten(name)),
-                "arg_enum" => Ok(ArgEnum(name)),
+                "arg_enum" => Ok(ValueEnum(name)),
+                "value_enum" => Ok(ValueEnum(name)),
                 "from_global" => Ok(FromGlobal(name)),
                 "subcommand" => Ok(Subcommand(name)),
                 "external_subcommand" => Ok(ExternalSubcommand(name)),
diff --git a/examples/derive_ref/README.md b/examples/derive_ref/README.md
index 35bee90f..dd973ed3 100644
--- a/examples/derive_ref/README.md
+++ b/examples/derive_ref/README.md
@@ -20,7 +20,7 @@ See [demo.rs](../demo.rs) and [demo.md](../demo.md) for a brief example.
 
 Let's start by breaking down the anatomy of the derive attributes:
 ```rust
-use clap::{Parser, Args, Subcommand, ArgEnum};
+use clap::{Parser, Args, Subcommand, ValueEnum};
 
 /// Doc comment
 #[derive(Parser)]
@@ -30,7 +30,7 @@ struct Cli {
     #[clap(ARG ATTRIBUTE)]
     field: UserType,
 
-    #[clap(arg_enum, ARG ATTRIBUTE...)]
+    #[clap(value_enum, ARG ATTRIBUTE...)]
     field: EnumValues,
 
     #[clap(flatten)]
@@ -67,7 +67,7 @@ enum Command {
 }
 
 /// Doc comment
-#[derive(ArgEnum)]
+#[derive(ValueEnum)]
 #[clap(ARG ENUM ATTRIBUTE)]
 enum EnumValues {
     /// Doc comment
@@ -84,7 +84,7 @@ fn main() {
 - `Args` allows defining a set of re-usable arguments that get merged into their parent container.
 - `Subcommand` defines available subcommands.
   - Subcommand arguments can be defined in a struct-variant or automatically flattened with a tuple-variant.
-- `ArgEnum` allows parsing a value directly into an `enum`, erroring on unsupported values.
+- `ValueEnum` allows parsing a value directly into an `enum`, erroring on unsupported values.
   - The derive doesn't work on enums that contain non-unit variants, unless they are skipped
 
 See also the [tutorial](../tutorial_derive/README.md) and [examples](../README.md).
@@ -212,15 +212,15 @@ These correspond to a `clap::Arg`.
   - Default: `try_from_str`
   - Warning: for `Path` / `OsString`, be sure to use `try_from_os_str`
   - See [Arg Types](#arg-types) for more details
-- `arg_enum`: Parse the value using the `ArgEnum` trait
+- `value_enum`: Parse the value using the `ValueEnum` trait
 - `skip [= <expr>]`: Ignore this field, filling in with `<expr>`
   - Without `<expr>`: fills the field with `Default::default()`
 - `default_value = <str>`: `clap::Arg::default_value` and `clap::Arg::required(false)`
 - `default_value_t [= <expr>]`: `clap::Arg::default_value` and `clap::Arg::required(false)`
-  - Requires `std::fmt::Display` or `#[clap(arg_enum)]`
+  - Requires `std::fmt::Display` or `#[clap(value_enum)]`
   - Without `<expr>`, relies on `Default::default()`
 - `default_value_os_t [= <expr>]`: `clap::Arg::default_value_os` and `clap::Arg::required(false)`
-  - Requires `std::convert::Into<OsString>` or `#[clap(arg_enum)]`
+  - Requires `std::convert::Into<OsString>` or `#[clap(value_enum)]`
   - Without `<expr>`, relies on `Default::default()`
 
 ### Arg Enum Attributes
diff --git a/examples/tutorial_builder/04_01_enum.rs b/examples/tutorial_builder/04_01_enum.rs
index 61f70125..ad2177c2 100644
--- a/examples/tutorial_builder/04_01_enum.rs
+++ b/examples/tutorial_builder/04_01_enum.rs
@@ -1,8 +1,8 @@
 // Note: this requires the `cargo` feature
 
-use clap::{arg, command, value_parser, ArgEnum};
+use clap::{arg, command, value_parser, ValueEnum};
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ArgEnum)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
 enum Mode {
     Fast,
     Slow,
diff --git a/examples/tutorial_builder/README.md b/examples/tutorial_builder/README.md
index 3d16270e..70e85e23 100644
--- a/examples/tutorial_builder/README.md
+++ b/examples/tutorial_builder/README.md
@@ -409,7 +409,7 @@ For more information try --help
 
 ```
 
-When enabling the `derive` feature, you can use `ArgEnum` to take care of the boiler plate for you, giving the same results.
+When enabling the `derive` feature, you can use `ValueEnum` to take care of the boiler plate for you, giving the same results.
 
 [Example:](04_01_enum.rs)
 ```console
diff --git a/examples/tutorial_derive/README.md b/examples/tutorial_derive/README.md
index 7e42a8ad..6127b6cd 100644
--- a/examples/tutorial_derive/README.md
+++ b/examples/tutorial_derive/README.md
@@ -378,7 +378,7 @@ name: "bob"
 ### Enumerated values
 
 If you have arguments of specific values you want to test for, you can derive
-`ArgEnum`.
+`ValueEnum`.
 
 This allows you specify the valid values for that argument. If the user does not use one of
 those specific values, they will receive a graceful exit with error message informing them
diff --git a/src/builder/arg.rs b/src/builder/arg.rs
index e1e47ef0..1407496d 100644
--- a/src/builder/arg.rs
+++ b/src/builder/arg.rs
@@ -955,7 +955,7 @@ impl<'help> Arg<'help> {
     ///   - [`BoolishValueParser`][crate::builder::BoolishValueParser], and [`FalseyValueParser`][crate::builder::FalseyValueParser] for alternative `bool` implementations
     ///   - [`NonEmptyStringValueParser`][crate::builder::NonEmptyStringValueParser] for basic validation for strings
     /// - [`RangedI64ValueParser`][crate::builder::RangedI64ValueParser] and [`RangedU64ValueParser`][crate::builder::RangedU64ValueParser] for numeric ranges
-    /// - [`ArgEnumValueParser`][crate::builder::ArgEnumValueParser] and  [`PossibleValuesParser`][crate::builder::PossibleValuesParser] for static enumerated values
+    /// - [`EnumValueParser`][crate::builder::EnumValueParser] and  [`PossibleValuesParser`][crate::builder::PossibleValuesParser] for static enumerated values
     /// - or any other [`TypedValueParser`][crate::builder::TypedValueParser] implementation
     ///
     /// ```rust
diff --git a/src/builder/mod.rs b/src/builder/mod.rs
index 885b46a1..b203592a 100644
--- a/src/builder/mod.rs
+++ b/src/builder/mod.rs
@@ -34,10 +34,10 @@ pub use possible_value::PossibleValue;
 pub use value_hint::ValueHint;
 pub use value_parser::via_prelude;
 pub use value_parser::AnyValueParser;
-pub use value_parser::ArgEnumValueParser;
 pub use value_parser::AutoValueParser;
 pub use value_parser::BoolValueParser;
 pub use value_parser::BoolishValueParser;
+pub use value_parser::EnumValueParser;
 pub use value_parser::FalseyValueParser;
 pub use value_parser::NonEmptyStringValueParser;
 pub use value_parser::OsStringValueParser;
diff --git a/src/builder/value_parser.rs b/src/builder/value_parser.rs
index 27a3670d..588a1445 100644
--- a/src/builder/value_parser.rs
+++ b/src/builder/value_parser.rs
@@ -79,7 +79,7 @@ impl ValueParser {
     /// To create a custom parser, see [`TypedValueParser`]
     ///
     /// Pre-existing implementations include:
-    /// - [`ArgEnumValueParser`] and  [`PossibleValuesParser`] for static enumerated values
+    /// - [`EnumValueParser`] and  [`PossibleValuesParser`] for static enumerated values
     /// - [`BoolishValueParser`] and [`FalseyValueParser`] for alternative `bool` implementations
     /// - [`RangedI64ValueParser`] and [`RangedU64ValueParser`]
     /// - [`NonEmptyStringValueParser`]
@@ -809,7 +809,7 @@ impl Default for PathBufValueParser {
     }
 }
 
-/// Parse an [`ArgEnum`][crate::ArgEnum] value.
+/// Parse an [`ValueEnum`][crate::ValueEnum] value.
 ///
 /// See also:
 /// - [`PossibleValuesParser`]
@@ -829,7 +829,7 @@ impl Default for PathBufValueParser {
 ///     Never,
 /// }
 ///
-/// impl clap::ArgEnum for ColorChoice {
+/// impl clap::ValueEnum for ColorChoice {
 ///     fn value_variants<'a>() -> &'a [Self] {
 ///         &[Self::Always, Self::Auto, Self::Never]
 ///     }
@@ -847,7 +847,7 @@ impl Default for PathBufValueParser {
 /// let mut cmd = clap::Command::new("raw")
 ///     .arg(
 ///         clap::Arg::new("color")
-///             .value_parser(clap::builder::ArgEnumValueParser::<ColorChoice>::new())
+///             .value_parser(clap::builder::EnumValueParser::<ColorChoice>::new())
 ///             .required(true)
 ///     );
 ///
@@ -857,7 +857,7 @@ impl Default for PathBufValueParser {
 /// assert_eq!(port, ColorChoice::Always);
 ///
 /// // Semantics
-/// let value_parser = clap::builder::ArgEnumValueParser::<ColorChoice>::new();
+/// let value_parser = clap::builder::EnumValueParser::<ColorChoice>::new();
 /// // or
 /// let value_parser = clap::value_parser!(ColorChoice);
 /// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).is_err());
@@ -867,19 +867,19 @@ impl Default for PathBufValueParser {
 /// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("never")).unwrap(), ColorChoice::Never);
 /// ```
 #[derive(Clone, Debug)]
-pub struct ArgEnumValueParser<E: crate::ArgEnum + Clone + Send + Sync + 'static>(
+pub struct EnumValueParser<E: crate::ValueEnum + Clone + Send + Sync + 'static>(
     std::marker::PhantomData<E>,
 );
 
-impl<E: crate::ArgEnum + Clone + Send + Sync + 'static> ArgEnumValueParser<E> {
-    /// Parse an [`ArgEnum`][crate::ArgEnum]
+impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> EnumValueParser<E> {
+    /// Parse an [`ValueEnum`][crate::ValueEnum]
     pub fn new() -> Self {
         let phantom: std::marker::PhantomData<E> = Default::default();
         Self(phantom)
     }
 }
 
-impl<E: crate::ArgEnum + Clone + Send + Sync + 'static> TypedValueParser for ArgEnumValueParser<E> {
+impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> TypedValueParser for EnumValueParser<E> {
     type Value = E;
 
     fn parse_ref(
@@ -911,7 +911,7 @@ impl<E: crate::ArgEnum + Clone + Send + Sync + 'static> TypedValueParser for Arg
             .iter()
             .find(|v| {
                 v.to_possible_value()
-                    .expect("ArgEnum::value_variants contains only values with a corresponding ArgEnum::to_possible_value")
+                    .expect("ValueEnum::value_variants contains only values with a corresponding ValueEnum::to_possible_value")
                     .matches(value, ignore_case)
             })
             .ok_or_else(|| {
@@ -938,7 +938,7 @@ impl<E: crate::ArgEnum + Clone + Send + Sync + 'static> TypedValueParser for Arg
     }
 }
 
-impl<E: crate::ArgEnum + Clone + Send + Sync + 'static> Default for ArgEnumValueParser<E> {
+impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> Default for EnumValueParser<E> {
     fn default() -> Self {
         Self::new()
     }
@@ -947,7 +947,7 @@ impl<E: crate::ArgEnum + Clone + Send + Sync + 'static> Default for ArgEnumValue
 /// Verify the value is from an enumerated set of [`PossibleValue`][crate::PossibleValue].
 ///
 /// See also:
-/// - [`ArgEnumValueParser`]
+/// - [`EnumValueParser`]
 ///
 /// # Example
 ///
@@ -1930,18 +1930,18 @@ pub mod via_prelude {
     }
 
     #[doc(hidden)]
-    pub trait ValueParserViaArgEnum: private::ValueParserViaArgEnumSealed {
+    pub trait ValueParserViaValueEnum: private::ValueParserViaValueEnumSealed {
         type Output;
 
         fn value_parser(&self) -> Self::Output;
     }
-    impl<E: crate::ArgEnum + Clone + Send + Sync + 'static> ValueParserViaArgEnum
+    impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> ValueParserViaValueEnum
         for &AutoValueParser<E>
     {
-        type Output = ArgEnumValueParser<E>;
+        type Output = EnumValueParser<E>;
 
         fn value_parser(&self) -> Self::Output {
-            ArgEnumValueParser::<E>::new()
+            EnumValueParser::<E>::new()
         }
     }
 
@@ -2004,14 +2004,14 @@ pub mod via_prelude {
 /// let parser = clap::value_parser!(usize);
 /// assert_eq!(format!("{:?}", parser), "ValueParser::other(usize)");
 ///
-/// // ArgEnum types
+/// // ValueEnum types
 /// #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 /// enum ColorChoice {
 ///     Always,
 ///     Auto,
 ///     Never,
 /// }
-/// impl clap::ArgEnum for ColorChoice {
+/// impl clap::ValueEnum for ColorChoice {
 ///     // ...
 /// #     fn value_variants<'a>() -> &'a [Self] {
 /// #         &[Self::Always, Self::Auto, Self::Never]
@@ -2025,7 +2025,7 @@ pub mod via_prelude {
 /// #     }
 /// }
 /// let parser = clap::value_parser!(ColorChoice);
-/// assert_eq!(format!("{:?}", parser), "ArgEnumValueParser(PhantomData)");
+/// assert_eq!(format!("{:?}", parser), "EnumValueParser(PhantomData)");
 /// ```
 #[macro_export]
 macro_rules! value_parser {
@@ -2053,8 +2053,8 @@ mod private {
     pub trait ValueParserViaFactorySealed {}
     impl<P: ValueParserFactory> ValueParserViaFactorySealed for &&AutoValueParser<P> {}
 
-    pub trait ValueParserViaArgEnumSealed {}
-    impl<E: crate::ArgEnum> ValueParserViaArgEnumSealed for &AutoValueParser<E> {}
+    pub trait ValueParserViaValueEnumSealed {}
+    impl<E: crate::ValueEnum> ValueParserViaValueEnumSealed for &AutoValueParser<E> {}
 
     pub trait ValueParserViaFromStrSealed {}
     impl<FromStr> ValueParserViaFromStrSealed for AutoValueParser<FromStr>
diff --git a/src/derive.rs b/src/derive.rs
index 19d1e917..7bee6b3c 100644
--- a/src/derive.rs
+++ b/src/derive.rs
@@ -430,8 +430,8 @@ pub trait Subcommand: FromArgMatches + Sized {
 
 /// Parse arguments into enums.
 ///
-/// When deriving [`Parser`], a field whose type implements `ArgEnum` can have the attribute
-/// `#[clap(arg_enum)]` which will
+/// When deriving [`Parser`], a field whose type implements `ValueEnum` can have the attribute
+/// `#[clap(value_enum)]` which will
 /// - Call [`Arg::possible_values`][crate::Arg::possible_values]
 /// - Allowing using the `#[clap(default_value_t)]` attribute without implementing `Display`.
 ///
@@ -447,11 +447,11 @@ pub trait Subcommand: FromArgMatches + Sized {
 #[cfg_attr(feature = "derive", doc = " ```")]
 /// #[derive(clap::Parser)]
 /// struct Args {
-///     #[clap(arg_enum)]
+///     #[clap(value_enum)]
 ///     level: Level,
 /// }
 ///
-/// #[derive(clap::ArgEnum, Clone)]
+/// #[derive(clap::ValueEnum, Clone)]
 /// enum Level {
 ///     Debug,
 ///     Info,
@@ -459,7 +459,7 @@ pub trait Subcommand: FromArgMatches + Sized {
 ///     Error,
 /// }
 /// ```
-pub trait ArgEnum: Sized + Clone {
+pub trait ValueEnum: Sized + Clone {
     /// All possible argument values, in display order.
     fn value_variants<'a>() -> &'a [Self];
 
@@ -469,7 +469,7 @@ pub trait ArgEnum: Sized + Clone {
             .iter()
             .find(|v| {
                 v.to_possible_value()
-                    .expect("ArgEnum::value_variants contains only values with a corresponding ArgEnum::to_possible_value")
+                    .expect("ValueEnum::value_variants contains only values with a corresponding ValueEnum::to_possible_value")
                     .matches(input, ignore_case)
             })
             .cloned()
diff --git a/src/lib.rs b/src/lib.rs
index f1f58a97..ae402e35 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -37,7 +37,7 @@ pub use crate::util::color::ColorChoice;
 #[allow(unused_imports)]
 pub(crate) use crate::util::color::ColorChoice;
 
-pub use crate::derive::{ArgEnum, Args, CommandFactory, FromArgMatches, Parser, Subcommand};
+pub use crate::derive::{Args, CommandFactory, FromArgMatches, Parser, Subcommand, ValueEnum};
 
 #[allow(deprecated)]
 pub use crate::builder::App;
@@ -66,6 +66,9 @@ pub use CommandFactory as IntoApp;
 #[deprecated(since = "3.0.0", note = "Replaced with `Parser`")]
 #[doc(hidden)]
 pub use Parser as StructOpt;
+/// Deprecated, replaced with [`ValueEnum`]
+#[deprecated(since = "3.2.0", note = "Replaced with `ValueEnum`")]
+pub use ValueEnum as ArgEnum;
 
 #[cfg(any(feature = "derive", feature = "cargo"))]
 #[doc(hidden)]


Test patch:
diff --git a/tests/derive/doc_comments_help.rs b/tests/derive/doc_comments_help.rs
index 5ff6290f..e6aab515 100644
--- a/tests/derive/doc_comments_help.rs
+++ b/tests/derive/doc_comments_help.rs
@@ -14,7 +14,7 @@
 
 use crate::utils;
 
-use clap::{ArgEnum, CommandFactory, Parser};
+use clap::{CommandFactory, Parser, ValueEnum};
 
 #[test]
 fn doc_comments() {
@@ -211,7 +211,7 @@ fn multiline_separates_default() {
 
 #[test]
 fn argenum_multiline_doc_comment() {
-    #[derive(ArgEnum, Clone)]
+    #[derive(ValueEnum, Clone)]
     enum LoremIpsum {
         /// Multiline
         ///
diff --git a/tests/derive/help.rs b/tests/derive/help.rs
index 8e9f7d50..0b9846fd 100644
--- a/tests/derive/help.rs
+++ b/tests/derive/help.rs
@@ -505,11 +505,11 @@ OPTIONS:
     #[derive(Parser, PartialEq, Debug)]
     struct Args {
         /// Argument help
-        #[clap(arg_enum, value_parser)]
+        #[clap(value_enum, value_parser)]
         arg: ArgChoice,
     }
 
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     enum ArgChoice {
         /// Foo help
         Foo,
diff --git a/tests/derive/main.rs b/tests/derive/main.rs
index f352244f..78a8eee3 100644
--- a/tests/derive/main.rs
+++ b/tests/derive/main.rs
@@ -1,7 +1,6 @@
 #![cfg(feature = "derive")]
 
 mod app_name;
-mod arg_enum;
 mod arguments;
 mod author_version_about;
 mod basic;
@@ -32,3 +31,4 @@ mod subcommands;
 mod type_alias_regressions;
 mod utf8;
 mod utils;
+mod value_enum;
diff --git a/tests/derive/type_alias_regressions.rs b/tests/derive/type_alias_regressions.rs
index a792ccb1..fe4b4573 100644
--- a/tests/derive/type_alias_regressions.rs
+++ b/tests/derive/type_alias_regressions.rs
@@ -3,7 +3,7 @@
 /// Regression test to ensure that type aliases do not cause compilation failures.
 use std::str::FromStr;
 
-use clap::{ArgEnum, Parser, Subcommand};
+use clap::{Parser, Subcommand, ValueEnum};
 
 // Result type alias
 #[allow(dead_code)]
@@ -29,7 +29,7 @@ pub struct Opts {
     another_string: String,
     #[clap(subcommand)]
     command: Command,
-    #[clap(short, long, arg_enum, value_parser)]
+    #[clap(short, long, value_enum, value_parser)]
     choice: ArgChoice,
 }
 
@@ -38,7 +38,7 @@ enum Command {
     DoSomething { arg: Option<String> },
 }
 
-#[derive(ArgEnum, PartialEq, Debug, Clone)]
+#[derive(ValueEnum, PartialEq, Debug, Clone)]
 enum ArgChoice {
     Foo,
     Bar,
diff --git a/tests/derive/arg_enum.rs b/tests/derive/value_enum.rs
similarity index 83%
rename from tests/derive/arg_enum.rs
rename to tests/derive/value_enum.rs
index 2c9ec781..4f93f57d 100644
--- a/tests/derive/arg_enum.rs
+++ b/tests/derive/value_enum.rs
@@ -11,7 +11,7 @@ use clap::Parser;
 
 #[test]
 fn basic() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     enum ArgChoice {
         Foo,
         Bar,
@@ -19,7 +19,7 @@ fn basic() {
 
     #[derive(Parser, PartialEq, Debug)]
     struct Opt {
-        #[clap(arg_enum, value_parser)]
+        #[clap(value_enum, value_parser)]
         arg: ArgChoice,
     }
 
@@ -40,7 +40,7 @@ fn basic() {
 
 #[test]
 fn default_value() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     enum ArgChoice {
         Foo,
         Bar,
@@ -54,7 +54,7 @@ fn default_value() {
 
     #[derive(Parser, PartialEq, Debug)]
     struct Opt {
-        #[clap(arg_enum, value_parser, default_value_t)]
+        #[clap(value_enum, value_parser, default_value_t)]
         arg: ArgChoice,
     }
 
@@ -80,7 +80,7 @@ fn default_value() {
 
 #[test]
 fn multi_word_is_renamed_kebab() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     #[allow(non_camel_case_types)]
     enum ArgChoice {
         FooBar,
@@ -89,7 +89,7 @@ fn multi_word_is_renamed_kebab() {
 
     #[derive(Parser, PartialEq, Debug)]
     struct Opt {
-        #[clap(arg_enum, value_parser)]
+        #[clap(value_enum, value_parser)]
         arg: ArgChoice,
     }
 
@@ -110,7 +110,7 @@ fn multi_word_is_renamed_kebab() {
 
 #[test]
 fn variant_with_defined_casing() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     enum ArgChoice {
         #[clap(rename_all = "screaming_snake")]
         FooBar,
@@ -118,7 +118,7 @@ fn variant_with_defined_casing() {
 
     #[derive(Parser, PartialEq, Debug)]
     struct Opt {
-        #[clap(arg_enum, value_parser)]
+        #[clap(value_enum, value_parser)]
         arg: ArgChoice,
     }
 
@@ -133,7 +133,7 @@ fn variant_with_defined_casing() {
 
 #[test]
 fn casing_is_propagated_from_parent() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     #[clap(rename_all = "screaming_snake")]
     enum ArgChoice {
         FooBar,
@@ -141,7 +141,7 @@ fn casing_is_propagated_from_parent() {
 
     #[derive(Parser, PartialEq, Debug)]
     struct Opt {
-        #[clap(arg_enum, value_parser)]
+        #[clap(value_enum, value_parser)]
         arg: ArgChoice,
     }
 
@@ -156,7 +156,7 @@ fn casing_is_propagated_from_parent() {
 
 #[test]
 fn casing_propagation_is_overridden() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     #[clap(rename_all = "screaming_snake")]
     enum ArgChoice {
         #[clap(rename_all = "camel")]
@@ -165,7 +165,7 @@ fn casing_propagation_is_overridden() {
 
     #[derive(Parser, PartialEq, Debug)]
     struct Opt {
-        #[clap(arg_enum, value_parser)]
+        #[clap(value_enum, value_parser)]
         arg: ArgChoice,
     }
 
@@ -181,14 +181,14 @@ fn casing_propagation_is_overridden() {
 
 #[test]
 fn ignore_case() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     enum ArgChoice {
         Foo,
     }
 
     #[derive(Parser, PartialEq, Debug)]
     struct Opt {
-        #[clap(arg_enum, value_parser, ignore_case(true))]
+        #[clap(value_enum, value_parser, ignore_case(true))]
         arg: ArgChoice,
     }
 
@@ -208,14 +208,14 @@ fn ignore_case() {
 
 #[test]
 fn ignore_case_set_to_false() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     enum ArgChoice {
         Foo,
     }
 
     #[derive(Parser, PartialEq, Debug)]
     struct Opt {
-        #[clap(arg_enum, ignore_case(false), value_parser)]
+        #[clap(value_enum, ignore_case(false), value_parser)]
         arg: ArgChoice,
     }
 
@@ -230,7 +230,7 @@ fn ignore_case_set_to_false() {
 
 #[test]
 fn alias() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     enum ArgChoice {
         #[clap(alias = "TOTP")]
         Totp,
@@ -238,7 +238,7 @@ fn alias() {
 
     #[derive(Parser, PartialEq, Debug)]
     struct Opt {
-        #[clap(arg_enum, ignore_case(false), value_parser)]
+        #[clap(value_enum, ignore_case(false), value_parser)]
         arg: ArgChoice,
     }
 
@@ -258,7 +258,7 @@ fn alias() {
 
 #[test]
 fn multiple_alias() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     enum ArgChoice {
         #[clap(alias = "TOTP", alias = "t")]
         Totp,
@@ -266,7 +266,7 @@ fn multiple_alias() {
 
     #[derive(Parser, PartialEq, Debug)]
     struct Opt {
-        #[clap(arg_enum, ignore_case(false), value_parser)]
+        #[clap(value_enum, ignore_case(false), value_parser)]
         arg: ArgChoice,
     }
 
@@ -292,7 +292,7 @@ fn multiple_alias() {
 
 #[test]
 fn skip_variant() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     #[allow(dead_code)] // silence warning about `Baz` being unused
     enum ArgChoice {
         Foo,
@@ -302,9 +302,9 @@ fn skip_variant() {
     }
 
     assert_eq!(
-        <ArgChoice as clap::ArgEnum>::value_variants()
+        <ArgChoice as clap::ValueEnum>::value_variants()
             .iter()
-            .map(clap::ArgEnum::to_possible_value)
+            .map(clap::ValueEnum::to_possible_value)
             .map(Option::unwrap)
             .collect::<Vec<_>>(),
         vec![
@@ -314,7 +314,7 @@ fn skip_variant() {
     );
 
     {
-        use clap::ArgEnum;
+        use clap::ValueEnum;
         assert!(ArgChoice::from_str("foo", true).is_ok());
         assert!(ArgChoice::from_str("bar", true).is_ok());
         assert!(ArgChoice::from_str("baz", true).is_err());
@@ -323,7 +323,7 @@ fn skip_variant() {
 
 #[test]
 fn skip_non_unit_variant() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     #[allow(dead_code)] // silence warning about `Baz` being unused
     enum ArgChoice {
         Foo,
@@ -333,9 +333,9 @@ fn skip_non_unit_variant() {
     }
 
     assert_eq!(
-        <ArgChoice as clap::ArgEnum>::value_variants()
+        <ArgChoice as clap::ValueEnum>::value_variants()
             .iter()
-            .map(clap::ArgEnum::to_possible_value)
+            .map(clap::ValueEnum::to_possible_value)
             .map(Option::unwrap)
             .collect::<Vec<_>>(),
         vec![
@@ -345,7 +345,7 @@ fn skip_non_unit_variant() {
     );
 
     {
-        use clap::ArgEnum;
+        use clap::ValueEnum;
         assert!(ArgChoice::from_str("foo", true).is_ok());
         assert!(ArgChoice::from_str("bar", true).is_ok());
         assert!(ArgChoice::from_str("baz", true).is_err());
@@ -354,20 +354,20 @@ fn skip_non_unit_variant() {
 
 #[test]
 fn from_str_invalid() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     enum ArgChoice {
         Foo,
     }
 
     {
-        use clap::ArgEnum;
+        use clap::ValueEnum;
         assert!(ArgChoice::from_str("bar", true).is_err());
     }
 }
 
 #[test]
 fn option_type() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     enum ArgChoice {
         Foo,
         Bar,
@@ -375,7 +375,7 @@ fn option_type() {
 
     #[derive(Parser, PartialEq, Debug)]
     struct Opt {
-        #[clap(arg_enum, value_parser)]
+        #[clap(value_enum, value_parser)]
         arg: Option<ArgChoice>,
     }
 
@@ -397,7 +397,7 @@ fn option_type() {
 
 #[test]
 fn option_option_type() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     enum ArgChoice {
         Foo,
         Bar,
@@ -405,7 +405,7 @@ fn option_option_type() {
 
     #[derive(Parser, PartialEq, Debug)]
     struct Opt {
-        #[clap(arg_enum, long, value_parser)]
+        #[clap(value_enum, long, value_parser)]
         arg: Option<Option<ArgChoice>>,
     }
 
@@ -431,7 +431,7 @@ fn option_option_type() {
 
 #[test]
 fn vec_type() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     enum ArgChoice {
         Foo,
         Bar,
@@ -439,7 +439,7 @@ fn vec_type() {
 
     #[derive(Parser, PartialEq, Debug)]
     struct Opt {
-        #[clap(arg_enum, short, long, value_parser)]
+        #[clap(value_enum, short, long, value_parser)]
         arg: Vec<ArgChoice>,
     }
 
@@ -461,7 +461,7 @@ fn vec_type() {
 
 #[test]
 fn option_vec_type() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     enum ArgChoice {
         Foo,
         Bar,
@@ -469,7 +469,7 @@ fn option_vec_type() {
 
     #[derive(Parser, PartialEq, Debug)]
     struct Opt {
-        #[clap(arg_enum, short, long, value_parser)]
+        #[clap(value_enum, short, long, value_parser)]
         arg: Option<Vec<ArgChoice>>,
     }
 
@@ -491,7 +491,7 @@ fn option_vec_type() {
 
 #[test]
 fn vec_type_default_value() {
-    #[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
+    #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
     enum ArgChoice {
         Foo,
         Bar,
@@ -501,7 +501,7 @@ fn vec_type_default_value() {
     #[derive(Parser, PartialEq, Debug)]
     struct Opt {
         #[clap(
-            arg_enum,
+            value_enum,
             short,
             long,
             default_value = "foo,bar",
diff --git a/tests/derive_ui/arg_enum_non_unit.stderr b/tests/derive_ui/arg_enum_non_unit.stderr
deleted file mode 100644
index 117cfcec..00000000
--- a/tests/derive_ui/arg_enum_non_unit.stderr
+++ /dev/null
@@ -1,5 +0,0 @@
-error: `#[derive(ArgEnum)]` only supports non-unit variants, unless they are skipped
- --> tests/derive_ui/arg_enum_non_unit.rs:5:5
-  |
-5 |     Foo(usize),
-  |     ^^^
diff --git a/tests/derive_ui/arg_enum_on_struct.stderr b/tests/derive_ui/arg_enum_on_struct.stderr
deleted file mode 100644
index 3b7175d7..00000000
--- a/tests/derive_ui/arg_enum_on_struct.stderr
+++ /dev/null
@@ -1,7 +0,0 @@
-error: `#[derive(ArgEnum)]` only supports enums
- --> $DIR/arg_enum_on_struct.rs:3:10
-  |
-3 | #[derive(ArgEnum, Clone, Debug)]
-  |          ^^^^^^^
-  |
-  = note: this error originates in the derive macro `ArgEnum` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/derive_ui/bool_arg_enum.rs b/tests/derive_ui/next/bool_value_enum.rs
similarity index 84%
rename from tests/derive_ui/bool_arg_enum.rs
rename to tests/derive_ui/next/bool_value_enum.rs
index 58951d8e..f98d507b 100644
--- a/tests/derive_ui/bool_arg_enum.rs
+++ b/tests/derive_ui/next/bool_value_enum.rs
@@ -3,7 +3,7 @@ use clap::Parser;
 #[derive(Parser, Debug)]
 #[clap(name = "basic")]
 struct Opt {
-    #[clap(short, arg_enum)]
+    #[clap(short, value_enum)]
     opts: bool,
 }
 
diff --git a/tests/derive_ui/bool_arg_enum.stderr b/tests/derive_ui/next/bool_value_enum.stderr
similarity index 78%
rename from tests/derive_ui/bool_arg_enum.stderr
rename to tests/derive_ui/next/bool_value_enum.stderr
index e963b89f..692ee8aa 100644
--- a/tests/derive_ui/bool_arg_enum.stderr
+++ b/tests/derive_ui/next/bool_value_enum.stderr
@@ -1,31 +1,31 @@
 warning: use of deprecated variant `clap::ArgAction::IncOccurrence`: Replaced with `ArgAction::SetTrue` or `ArgAction::Count`
- --> tests/derive_ui/bool_arg_enum.rs:6:5
+ --> tests/derive_ui/next/bool_value_enum.rs:6:5
   |
-6 |     #[clap(short, arg_enum)]
+6 |     #[clap(short, value_enum)]
   |     ^
   |
   = note: `#[warn(deprecated)]` on by default
 
 warning: use of deprecated variant `clap::ArgAction::IncOccurrence`: Replaced with `ArgAction::SetTrue` or `ArgAction::Count`
- --> tests/derive_ui/bool_arg_enum.rs:6:5
+ --> tests/derive_ui/next/bool_value_enum.rs:6:5
   |
-6 |     #[clap(short, arg_enum)]
+6 |     #[clap(short, value_enum)]
   |     ^
 
 error[E0277]: the trait bound `bool: ArgEnum` is not satisfied
-   --> tests/derive_ui/bool_arg_enum.rs:7:11
+   --> tests/derive_ui/next/bool_value_enum.rs:7:11
     |
 7   |     opts: bool,
     |           ^^^^ the trait `ArgEnum` is not implemented for `bool`
     |
-note: required by `clap::ArgEnum::from_str`
+note: required by `clap::ValueEnum::from_str`
    --> src/derive.rs
     |
     |     fn from_str(input: &str, ignore_case: bool) -> Result<Self, String> {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0618]: expected function, found enum variant `bool`
- --> tests/derive_ui/bool_arg_enum.rs:7:11
+ --> tests/derive_ui/next/bool_value_enum.rs:7:11
   |
 7 |     opts: bool,
   |           ^^^^ call expression requires function
@@ -36,13 +36,13 @@ help: `bool` is a unit variant, you need to write it without the parenthesis
   |           ~~~~
 
 warning: use of deprecated associated function `clap::Arg::<'help>::possible_values`: Replaced with `Arg::value_parser(PossibleValuesParser::new(...)).takes_value(true)`
- --> tests/derive_ui/bool_arg_enum.rs:7:11
+ --> tests/derive_ui/next/bool_value_enum.rs:7:11
   |
 7 |     opts: bool,
   |           ^^^^
 
 error[E0277]: the trait bound `bool: ArgEnum` is not satisfied
-   --> tests/derive_ui/bool_arg_enum.rs:7:11
+   --> tests/derive_ui/next/bool_value_enum.rs:7:11
     |
 7   |     opts: bool,
     |           ^^^^ the trait `ArgEnum` is not implemented for `bool`
@@ -54,16 +54,16 @@ note: required by `value_variants`
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `bool: ArgEnum` is not satisfied
-   --> tests/derive_ui/bool_arg_enum.rs:6:5
+   --> tests/derive_ui/next/bool_value_enum.rs:6:5
     |
-6   | /     #[clap(short, arg_enum)]
+6   | /     #[clap(short, value_enum)]
 7   | |     opts: bool,
     | |______________^ the trait `ArgEnum` is not implemented for `bool`
     |
 note: required by a bound in `ArgEnum`
    --> src/derive.rs
     |
-    | / pub trait ArgEnum: Sized + Clone {
+    | / pub trait ValueEnum: Sized + Clone {
     | |     /// All possible argument values, in display order.
     | |     fn value_variants<'a>() -> &'a [Self];
     | |
diff --git a/tests/derive_ui/stable/bool_value_enum.rs b/tests/derive_ui/stable/bool_value_enum.rs
new file mode 100644
index 00000000..f98d507b
--- /dev/null
+++ b/tests/derive_ui/stable/bool_value_enum.rs
@@ -0,0 +1,13 @@
+use clap::Parser;
+
+#[derive(Parser, Debug)]
+#[clap(name = "basic")]
+struct Opt {
+    #[clap(short, value_enum)]
+    opts: bool,
+}
+
+fn main() {
+    let opt = Opt::parse();
+    println!("{:?}", opt);
+}
diff --git a/tests/derive_ui/stable/bool_value_enum.stderr b/tests/derive_ui/stable/bool_value_enum.stderr
new file mode 100644
index 00000000..d7fd7828
--- /dev/null
+++ b/tests/derive_ui/stable/bool_value_enum.stderr
@@ -0,0 +1,73 @@
+warning: use of deprecated variant `clap::ArgAction::IncOccurrence`: Replaced with `ArgAction::SetTrue` or `ArgAction::Count`
+ --> tests/derive_ui/stable/bool_value_enum.rs:6:5
+  |
+6 |     #[clap(short, value_enum)]
+  |     ^
+  |
+  = note: `#[warn(deprecated)]` on by default
+
+warning: use of deprecated variant `clap::ArgAction::IncOccurrence`: Replaced with `ArgAction::SetTrue` or `ArgAction::Count`
+ --> tests/derive_ui/stable/bool_value_enum.rs:6:5
+  |
+6 |     #[clap(short, value_enum)]
+  |     ^
+
+error[E0277]: the trait bound `bool: ValueEnum` is not satisfied
+   --> tests/derive_ui/stable/bool_value_enum.rs:7:11
+    |
+7   |     opts: bool,
+    |           ^^^^ the trait `ValueEnum` is not implemented for `bool`
+    |
+note: required by `clap::ValueEnum::from_str`
+   --> src/derive.rs
+    |
+    |     fn from_str(input: &str, ignore_case: bool) -> Result<Self, String> {
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0618]: expected function, found enum variant `bool`
+ --> tests/derive_ui/stable/bool_value_enum.rs:7:11
+  |
+7 |     opts: bool,
+  |           ^^^^ call expression requires function
+  |
+help: `bool` is a unit variant, you need to write it without the parenthesis
+  |
+7 |     opts: bool,
+  |           ~~~~
+
+warning: use of deprecated associated function `clap::Arg::<'help>::possible_values`: Replaced with `Arg::value_parser(PossibleValuesParser::new(...)).takes_value(true)`
+ --> tests/derive_ui/stable/bool_value_enum.rs:7:11
+  |
+7 |     opts: bool,
+  |           ^^^^
+
+error[E0277]: the trait bound `bool: ValueEnum` is not satisfied
+   --> tests/derive_ui/stable/bool_value_enum.rs:7:11
+    |
+7   |     opts: bool,
+    |           ^^^^ the trait `ValueEnum` is not implemented for `bool`
+    |
+note: required by `value_variants`
+   --> src/derive.rs
+    |
+    |     fn value_variants<'a>() -> &'a [Self];
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `bool: ValueEnum` is not satisfied
+   --> tests/derive_ui/stable/bool_value_enum.rs:6:5
+    |
+6   | /     #[clap(short, value_enum)]
+7   | |     opts: bool,
+    | |______________^ the trait `ValueEnum` is not implemented for `bool`
+    |
+note: required by a bound in `ValueEnum`
+   --> src/derive.rs
+    |
+    | / pub trait ValueEnum: Sized + Clone {
+    | |     /// All possible argument values, in display order.
+    | |     fn value_variants<'a>() -> &'a [Self];
+    | |
+...   |
+    | |     fn to_possible_value<'a>(&self) -> Option<PossibleValue<'a>>;
+    | | }
+    | |_^ required by this bound in `ValueEnum`
diff --git a/tests/derive_ui/arg_enum_non_unit.rs b/tests/derive_ui/value_enum_non_unit.rs
similarity index 59%
rename from tests/derive_ui/arg_enum_non_unit.rs
rename to tests/derive_ui/value_enum_non_unit.rs
index be031005..646323ab 100644
--- a/tests/derive_ui/arg_enum_non_unit.rs
+++ b/tests/derive_ui/value_enum_non_unit.rs
@@ -1,6 +1,6 @@
-use clap::ArgEnum;
+use clap::ValueEnum;
 
-#[derive(ArgEnum, Clone, Debug)]
+#[derive(ValueEnum, Clone, Debug)]
 enum Opt {
     Foo(usize),
 }
diff --git a/tests/derive_ui/value_enum_non_unit.stderr b/tests/derive_ui/value_enum_non_unit.stderr
new file mode 100644
index 00000000..07cc473e
--- /dev/null
+++ b/tests/derive_ui/value_enum_non_unit.stderr
@@ -0,0 +1,5 @@
+error: `#[derive(ValueEnum)]` only supports non-unit variants, unless they are skipped
+ --> tests/derive_ui/value_enum_non_unit.rs:5:5
+  |
+5 |     Foo(usize),
+  |     ^^^
diff --git a/tests/derive_ui/arg_enum_on_struct.rs b/tests/derive_ui/value_enum_on_struct.rs
similarity index 57%
rename from tests/derive_ui/arg_enum_on_struct.rs
rename to tests/derive_ui/value_enum_on_struct.rs
index a26c9658..982e98e5 100644
--- a/tests/derive_ui/arg_enum_on_struct.rs
+++ b/tests/derive_ui/value_enum_on_struct.rs
@@ -1,6 +1,6 @@
-use clap::ArgEnum;
+use clap::ValueEnum;
 
-#[derive(ArgEnum, Clone, Debug)]
+#[derive(ValueEnum, Clone, Debug)]
 struct Opt {}
 
 fn main() {
diff --git a/tests/derive_ui/value_enum_on_struct.stderr b/tests/derive_ui/value_enum_on_struct.stderr
new file mode 100644
index 00000000..2557d92d
--- /dev/null
+++ b/tests/derive_ui/value_enum_on_struct.stderr
@@ -0,0 +1,7 @@
+error: `#[derive(ValueEnum)]` only supports enums
+ --> tests/derive_ui/value_enum_on_struct.rs:3:10
+  |
+3 | #[derive(ValueEnum, Clone, Debug)]
+  |          ^^^^^^^^^
+  |
+  = note: this error originates in the derive macro `ValueEnum` (in Nightly builds, run with -Z macro-backtrace for more info)