Repository: google/argh (rust)

Issue:
The conflict between argh and anyhow
To reproduce the issue, here is the code:

```rust
use anyhow::Ok;
use argh::FromArgs;

#[derive(FromArgs)]
/// A simple CLI tool
struct Args {
    /// the input file
    #[argh(option)]
    input: String,
}

fn main() -> anyhow::Result<()> {
    let args: Args = argh::from_env();
    println!("Hello, world!: input: {}", args.input);
    Ok(())
}
```

`cargo build` output:

```rust
cargo build
   Compiling argh_vs_anyhow v0.1.0 (/Users/tao/lab/rust/fortune/project/argh_vs_anyhow)
error[E0308]: mismatched types
 --> src/main.rs:4:10
  |
4 | #[derive(FromArgs)]
  |          ^^^^^^^^
  |          |
  |          expected `Result<Args, EarlyExit>`, found `Result<Args, Error>`
  |          expected `Result<Args, EarlyExit>` because of return type
  |
  = note: expected enum `Result<_, EarlyExit>`
             found enum `Result<_, anyhow::Error>`
  = note: this error originates in the derive macro `FromArgs` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
 --> src/main.rs:4:10
  |
4 | #[derive(FromArgs)]
  |          ^^^^^^^^ expected `Result<String, String>`, found `Result<String, Error>`
  |
  = note: expected enum `Result<_, String>`
             found enum `Result<_, anyhow::Error>`
  = note: this error originates in the derive macro `FromArgs` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
 --> src/main.rs:4:10
  |
4 | #[derive(FromArgs)]
  |          ^^^^^^^^
  |          |
  |          expected `Result<Vec<String>, EarlyExit>`, found `Result<Vec<String>, Error>`
  |          expected `Result<Vec<String>, EarlyExit>` because of return type
  |
  = note: expected enum `Result<_, EarlyExit>`
             found enum `Result<_, anyhow::Error>`
  = note: this error originates in the derive macro `FromArgs` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0308`.
error: could not compile `argh_vs_anyhow` (bin "argh_vs_anyhow") due to 3 previous errors
```

`anyhow::Ok` conflicted with `core::result::Result Ok`, so, I believe the fully qualified type path should be used in `argh` code to avoid the conflict.

Pull request:
Fix issue 193 (Bad hygiene regarding Ok/Err variants)
I wanted to ask if there was going to be a release including #196,
It didn't feel right to do so without fixing a bug, so this fixes #193.


Patch:
diff --git a/argh_derive/src/lib.rs b/argh_derive/src/lib.rs
index b3d4d58..e9fbde5 100644
--- a/argh_derive/src/lib.rs
+++ b/argh_derive/src/lib.rs
@@ -392,7 +392,7 @@ fn impl_from_args_struct_from_args<'a>(
                 dynamic_subcommands: &<#ty as argh::SubCommands>::dynamic_commands(),
                 parse_func: &mut |__command, __remaining_args| {
                     #name = Some(<#ty as argh::FromArgs>::from_args(__command, __remaining_args)?);
-                    Ok(())
+                    ::core::result::Result::Ok(())
                 },
             })
         }
@@ -412,7 +412,7 @@ fn impl_from_args_struct_from_args<'a>(
 
     let method_impl = quote_spanned! { impl_span =>
         fn from_args(__cmd_name: &[&str], __args: &[&str])
-            -> std::result::Result<Self, argh::EarlyExit>
+            -> ::core::result::Result<Self, argh::EarlyExit>
         {
             #![allow(clippy::unwrap_in_result)]
 
@@ -448,7 +448,7 @@ fn impl_from_args_struct_from_args<'a>(
             )*
             #missing_requirements_ident.err_on_any()?;
 
-            Ok(Self {
+            ::core::result::Result::Ok(Self {
                 #( #unwrap_fields, )*
             })
         }
@@ -536,7 +536,7 @@ fn impl_from_args_struct_redact_arg_values<'a>(
                 dynamic_subcommands: &<#ty as argh::SubCommands>::dynamic_commands(),
                 parse_func: &mut |__command, __remaining_args| {
                     #name = Some(<#ty as argh::FromArgs>::redact_arg_values(__command, __remaining_args)?);
-                    Ok(())
+                    ::core::result::Result::Ok(())
                 },
             })
         }
@@ -598,13 +598,13 @@ fn impl_from_args_struct_redact_arg_values<'a>(
                 if let Some(cmd_name) = __cmd_name.last() {
                     (*cmd_name).to_owned()
                 } else {
-                    return Err(argh::EarlyExit::from(#unwrap_cmd_name_err_string.to_owned()));
+                    return ::core::result::Result::Err(argh::EarlyExit::from(#unwrap_cmd_name_err_string.to_owned()));
                 }
             ];
 
             #( #unwrap_fields )*
 
-            Ok(__redacted)
+            ::core::result::Result::Ok(__redacted)
         }
     };
 
@@ -819,7 +819,7 @@ fn declare_local_storage_for_redacted_fields<'a>(
                     let mut #field_name: argh::ParseValueSlotTy::<#field_slot_type, String> =
                         argh::ParseValueSlotTy {
                         slot: std::default::Default::default(),
-                        parse_func: |arg, _| { Ok(arg.to_owned()) },
+                        parse_func: |arg, _| { ::core::result::Result::Ok(arg.to_owned()) },
                     };
                 }
             }
@@ -841,7 +841,7 @@ fn declare_local_storage_for_redacted_fields<'a>(
                     let mut #field_name: argh::ParseValueSlotTy::<#field_slot_type, String> =
                         argh::ParseValueSlotTy {
                         slot: std::default::Default::default(),
-                        parse_func: |_, _| { Ok(#arg_name.to_owned()) },
+                        parse_func: |_, _| { ::core::result::Result::Ok(#arg_name.to_owned()) },
                     };
                 }
             }
@@ -1106,12 +1106,12 @@ fn impl_from_args_enum(
                 let subcommand_name = if let Some(subcommand_name) = command_name.last() {
                     *subcommand_name
                 } else {
-                    return Err(argh::EarlyExit::from("no subcommand name".to_owned()));
+                    return ::core::result::Result::Err(argh::EarlyExit::from("no subcommand name".to_owned()));
                 };
 
                 #(
                     if subcommand_name == <#variant_ty as argh::SubCommand>::COMMAND.name {
-                        return Ok(#name_repeating::#variant_names(
+                        return ::core::result::Result::Ok(#name_repeating::#variant_names(
                             <#variant_ty as argh::FromArgs>::from_args(command_name, args)?
                         ));
                     }
@@ -1119,14 +1119,14 @@ fn impl_from_args_enum(
 
                 #dynamic_from_args
 
-                Err(argh::EarlyExit::from("no subcommand matched".to_owned()))
+                ::core::result::Result::Err(argh::EarlyExit::from("no subcommand matched".to_owned()))
             }
 
             fn redact_arg_values(command_name: &[&str], args: &[&str]) -> std::result::Result<Vec<String>, argh::EarlyExit> {
                 let subcommand_name = if let Some(subcommand_name) = command_name.last() {
                     *subcommand_name
                 } else {
-                    return Err(argh::EarlyExit::from("no subcommand name".to_owned()));
+                    return ::core::result::Result::Err(argh::EarlyExit::from("no subcommand name".to_owned()));
                 };
 
                 #(
@@ -1137,7 +1137,7 @@ fn impl_from_args_enum(
 
                 #dynamic_redact_arg_values
 
-                Err(argh::EarlyExit::from("no subcommand matched".to_owned()))
+                ::core::result::Result::Err(argh::EarlyExit::from("no subcommand matched".to_owned()))
             }
         }
 
@@ -1262,14 +1262,14 @@ fn impl_from_arg_value_enum(
     quote! {
         impl #impl_generics argh::FromArgValue for #name #ty_generics #where_clause {
             fn from_arg_value(value: &str)
-                -> std::result::Result<Self, String>
+                -> ::core::result::Result<Self, String>
             {
-                Ok(match value {
+                ::core::result::Result::Ok(match value {
                     #(
                         #variant_names => #name_repeating::#variant_idents,
                     )*
                     _ => {
-                        return Err(#err_literal.to_owned())
+                        return ::core::result::Result::Err(#err_literal.to_owned())
                     }
                 })
             }


Test patch:
diff --git a/argh/tests/args_info_tests.rs b/argh/tests/args_info_tests.rs
index 58e2cda..8ceb0ea 100644
--- a/argh/tests/args_info_tests.rs
+++ b/argh/tests/args_info_tests.rs
@@ -1029,3 +1029,21 @@ fn test_dynamic_subcommand() {
         ..Default::default()
     })
 }
+
+#[test]
+fn ok_hygiene() {
+    #![allow(unused)]
+    enum Foo {
+        Ok,
+        Err,
+    }
+    use Foo::*;
+
+    #[derive(FromArgs)]
+    /// A simple CLI tool
+    struct Args {
+        /// the input file
+        #[argh(option)]
+        input: String,
+    }
+}