Repository: clap-rs/clap
Pull request #4239 (2022-09-20 18:41:02)

fix(error): Use a non-generic Error alias 
`clap::Error::raw` was producing ambiguity errors with a default generic
parameter on `clap::error::Error` (which `clap::Error` is a re-export
of).

I tried making `clap::Error` a type alias with a default generic
parameter but that ran into an ambiguity error with `map_err`.

So I'm going ahead and hard coding `clap::Error`.  We don't expect
people to change this all that often.


Patch:
diff --git a/src/error/format.rs b/src/error/format.rs
index 941a40d6..5f5713f4 100644
--- a/src/error/format.rs
+++ b/src/error/format.rs
@@ -15,7 +15,7 @@ use crate::output::TAB;
 /// Defines how to format an error for displaying to the user
 pub trait ErrorFormatter: Sized {
     /// Stylize the error for the terminal
-    fn format_error(error: &crate::Error<Self>) -> StyledStr;
+    fn format_error(error: &crate::error::Error<Self>) -> StyledStr;
 }
 
 /// Report [`ErrorKind`]
@@ -28,7 +28,7 @@ pub trait ErrorFormatter: Sized {
 pub struct KindFormatter;
 
 impl ErrorFormatter for KindFormatter {
-    fn format_error(error: &crate::Error<Self>) -> StyledStr {
+    fn format_error(error: &crate::error::Error<Self>) -> StyledStr {
         let mut styled = StyledStr::new();
         start_error(&mut styled);
         if let Some(msg) = error.kind().as_str() {
@@ -43,43 +43,6 @@ impl ErrorFormatter for KindFormatter {
     }
 }
 
-/// Dump the error context reported
-#[non_exhaustive]
-#[cfg(feature = "error-context")]
-pub struct RawFormatter;
-
-#[cfg(feature = "error-context")]
-impl ErrorFormatter for RawFormatter {
-    fn format_error(error: &crate::Error<Self>) -> StyledStr {
-        let mut styled = StyledStr::new();
-        start_error(&mut styled);
-        if let Some(msg) = error.kind().as_str() {
-            styled.none(msg.to_owned());
-        } else if let Some(source) = error.inner.source.as_ref() {
-            styled.none(source.to_string());
-        } else {
-            styled.none("Unknown cause");
-        }
-        styled.none("\n");
-
-        if error.context().next().is_some() {
-            styled.none("\n");
-        }
-        for (kind, value) in error.context() {
-            if let Some(kind) = kind.as_str() {
-                styled.none(kind);
-                styled.none(": ");
-                styled.none(value.to_string());
-            } else {
-                styled.none(value.to_string());
-            }
-            styled.none("\n");
-        }
-
-        styled
-    }
-}
-
 /// Richly formatted error context
 #[non_exhaustive]
 #[cfg(feature = "error-context")]
@@ -87,7 +50,7 @@ pub struct RichFormatter;
 
 #[cfg(feature = "error-context")]
 impl ErrorFormatter for RichFormatter {
-    fn format_error(error: &crate::Error<Self>) -> StyledStr {
+    fn format_error(error: &crate::error::Error<Self>) -> StyledStr {
         let mut styled = StyledStr::new();
         start_error(&mut styled);
 
@@ -119,7 +82,7 @@ fn start_error(styled: &mut StyledStr) {
 
 #[must_use]
 #[cfg(feature = "error-context")]
-fn write_dynamic_context(error: &crate::Error, styled: &mut StyledStr) -> bool {
+fn write_dynamic_context(error: &crate::error::Error, styled: &mut StyledStr) -> bool {
     match error.kind() {
         ErrorKind::ArgumentConflict => {
             let invalid_arg = error.get(ContextKind::InvalidArg);
diff --git a/src/error/mod.rs b/src/error/mod.rs
index b27486b7..181fd68a 100644
--- a/src/error/mod.rs
+++ b/src/error/mod.rs
@@ -39,8 +39,6 @@ pub use context::ContextKind;
 #[cfg(feature = "error-context")]
 pub use context::ContextValue;
 #[cfg(feature = "error-context")]
-pub use format::RawFormatter;
-#[cfg(feature = "error-context")]
 pub use format::RichFormatter;
 
 #[cfg(not(feature = "error-context"))]
diff --git a/src/lib.rs b/src/lib.rs
index 0059ca39..81748c8d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -101,7 +101,6 @@ pub use crate::builder::ArgAction;
 pub use crate::builder::Command;
 pub use crate::builder::ValueHint;
 pub use crate::builder::{Arg, ArgGroup};
-pub use crate::error::Error;
 pub use crate::parser::ArgMatches;
 #[cfg(feature = "color")]
 pub use crate::util::color::ColorChoice;
@@ -110,6 +109,13 @@ pub use crate::util::color::ColorChoice;
 pub(crate) use crate::util::color::ColorChoice;
 pub use crate::util::Id;
 
+/// Command Line Argument Parser Error
+///
+/// See [`Command::error`] to create an error.
+///
+/// [`Command::error`]: crate::Command::error
+pub type Error = crate::error::Error<crate::error::DefaultFormatter>;
+
 pub use crate::derive::{Args, CommandFactory, FromArgMatches, Parser, Subcommand, ValueEnum};
 
 #[cfg(feature = "derive")]


Test patch:
diff --git a/tests/builder/error.rs b/tests/builder/error.rs
index bbdfa735..f927955f 100644
--- a/tests/builder/error.rs
+++ b/tests/builder/error.rs
@@ -1,6 +1,6 @@
 use super::utils;
 
-use clap::{arg, error::ErrorKind, value_parser, Arg, Command, Error};
+use clap::{arg, error::Error, error::ErrorKind, value_parser, Arg, Command};
 
 #[track_caller]
 fn assert_error<F: clap::error::ErrorFormatter>(
@@ -96,25 +96,6 @@ Options:
     assert_error(err, expected_kind, MESSAGE, false);
 }
 
-#[test]
-#[cfg(feature = "error-context")]
-fn raw_prints_help() {
-    let cmd = Command::new("test");
-    let res = cmd
-        .try_get_matches_from(["test", "--help"])
-        .map_err(|e| e.apply::<clap::error::RawFormatter>());
-    assert!(res.is_err());
-    let err = res.unwrap_err();
-    let expected_kind = ErrorKind::DisplayHelp;
-    static MESSAGE: &str = "\
-Usage: test
-
-Options:
-  -h, --help  Print help information
-";
-    assert_error(err, expected_kind, MESSAGE, false);
-}
-
 #[test]
 fn kind_formats_validation_error() {
     let cmd = Command::new("test");
@@ -147,22 +128,3 @@ For more information try '--help'
 ";
     assert_error(err, expected_kind, MESSAGE, true);
 }
-
-#[test]
-#[cfg(feature = "error-context")]
-fn raw_formats_validation_error() {
-    let cmd = Command::new("test");
-    let res = cmd
-        .try_get_matches_from(["test", "unused"])
-        .map_err(|e| e.apply::<clap::error::RawFormatter>());
-    assert!(res.is_err());
-    let err = res.unwrap_err();
-    let expected_kind = ErrorKind::UnknownArgument;
-    static MESSAGE: &str = "\
-error: Found an argument which wasn't expected or isn't valid in this context
-
-Invalid Argument: unused
-Usage: test
-";
-    assert_error(err, expected_kind, MESSAGE, true);
-}