Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Derive parser: FromStr implemention with Err=Box<dyn Error> causes inscrutible compiler error #5736

Open
2 tasks done
Sciencentistguy opened this issue Sep 19, 2024 · 4 comments
Labels
A-derive Area: #[derive]` macro API C-bug Category: Updating dependencies S-blocked Status: Blocked on something else such as an RFC or other implementation work.

Comments

@Sciencentistguy
Copy link

Please complete the following tasks

Rust Version

1.81.0

Clap Version

4.5.17

Minimal reproducible code

use std::str::FromStr;
use clap::Parser;

#[derive(Debug, Clone)]
struct ArgT {
    value: usize,
}

impl FromStr for ArgT {
    type Err = Box<dyn std::error::Error>;

    fn from_str(x: &str) -> Result<Self, Self::Err> {
        todo!()
    }
}

#[derive(Parser)]
struct Args {
    #[clap()]
    arg: ArgT
}

Steps to reproduce the bug with the above code

Compile the code

Actual Behaviour

It rejects the code, and the error message is rather unhelpful

Expected Behaviour

Either this should be supported (I don't know why it isn't, but it may be non-trivial), or ideally the error message should be improved

Additional Context

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=5598d6ddacf4b3784b92969617c54318

Debug Output

No response

@Sciencentistguy Sciencentistguy added the C-bug Category: Updating dependencies label Sep 19, 2024
@epage
Copy link
Member

epage commented Sep 19, 2024

The error message

error[E0599]: the method `value_parser` exists for reference `&&&&&&_infer_ValueParser_for<ArgT>`, but its trait bounds were not satisfied
    --> src/lib.rs:19:5
     |
5    |   struct ArgT {
     |   ----------- doesn't satisfy 6 bounds
...
19   |       #[clap()]
     |       ^ method cannot be called on `&&&&&&_infer_ValueParser_for<ArgT>` due to unsatisfied trait bounds
     |
    ::: /playground/.cargo/registry/src/index.crates.io-6f17d22bba15001f/clap_builder-4.5.17/src/builder/value_parser.rs:2423:1
     |
2423 |   pub struct _infer_ValueParser_for<T>(std::marker::PhantomData<T>);
     |   ------------------------------------ doesn't satisfy `_: _impls_FromStr`
     |
    ::: /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:238:1
     |
238  | / pub struct Box<
239  | |     T: ?Sized,
240  | |     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
241  | | >(Unique<T>, A);
     | |_- doesn't satisfy `_: Into<Box<dyn Error + Send + Sync>>`
     |
     = note: the following trait bounds were not satisfied:
             `ArgT: ValueEnum`
             which is required by `&&&&&_infer_ValueParser_for<ArgT>: clap::builder::impl_prelude::_impls_ValueEnum`
             `ArgT: ValueParserFactory`
             which is required by `&&&&&&_infer_ValueParser_for<ArgT>: clap::builder::impl_prelude::_impls_ValueParserFactory`
             `ArgT: From<OsString>`
             which is required by `&&&&_infer_ValueParser_for<ArgT>: clap::builder::impl_prelude::_impls_From_OsString`
             `ArgT: From<&'s std::ffi::OsStr>`
             which is required by `&&&_infer_ValueParser_for<ArgT>: clap::builder::impl_prelude::_impls_From_OsStr`
             `ArgT: From<std::string::String>`
             which is required by `&&_infer_ValueParser_for<ArgT>: clap::builder::impl_prelude::_impls_From_String`
             `ArgT: From<&'s str>`
             which is required by `&_infer_ValueParser_for<ArgT>: clap::builder::impl_prelude::_impls_From_str`
             `Box<(dyn std::error::Error + 'static)>: Into<Box<(dyn std::error::Error + Send + Sync + 'static)>>`
             which is required by `_infer_ValueParser_for<ArgT>: clap::builder::impl_prelude::_impls_FromStr`
note: the traits `From`, `ValueEnum`,  and `ValueParserFactory` must be implemented
    --> /playground/.cargo/registry/src/index.crates.io-6f17d22bba15001f/clap_builder-4.5.17/src/builder/value_parser.rs:2272:1
     |
2272 | pub trait ValueParserFactory {
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
    ::: /playground/.cargo/registry/src/index.crates.io-6f17d22bba15001f/clap_builder-4.5.17/src/derive.rs:276:1
     |
276  | pub trait ValueEnum: Sized + Clone {
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
    ::: /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/convert/mod.rs:580:1
     |
580  | pub trait From<T>: Sized {
     | ^^^^^^^^^^^^^^^^^^^^^^^^
     = note: this error originates in the macro `clap::value_parser` (in Nightly builds, run with -Z macro-backtrace for more info)

warning: unused variable: `x`
  --> src/lib.rs:12:17
   |
12 |     fn from_str(x: &str) -> Result<Self, Self::Err> {
   |                 ^ help: if this is intentional, prefix it with an underscore: `_x`
   |
   = note: `#[warn(unused_variables)]` on by default

For more information about this error, try `rustc --explain E0599`.
warning: `playground` (lib) generated 1 warning
error: could not compile `playground` (lib) due to 2 previous errors; 1 warning emitted

@epage
Copy link
Member

epage commented Sep 19, 2024

clap needs to know what ValueParser to use for a field.

 the method `value_parser` exists for reference `&&&&&&_infer_ValueParser_for<ArgT>`, but its trait bounds were not satisfied

We have a trait to "infer ValueParser for your ArgT"

     |   ----------- doesn't satisfy 6 bounds

We have 6 traits available to provide _infer_ValueParser_for for you

             `Box<(dyn std::error::Error + 'static)>: Into<Box<(dyn std::error::Error + Send + Sync + 'static)>>`
             which is required by `_infer_ValueParser_for<ArgT>: clap::builder::impl_prelude::_impls_FromStr`

when inferring for FromStr, your error type is not convertable to Error + Send + Sync + 'static

To fix this, change

    type Err = Box<dyn std::error::Error>;

to

    type Err = Box<dyn std::error::Error + Send + Sync>;

@epage
Copy link
Member

epage commented Sep 19, 2024

#5704 previously improved the error message (browse per-commit to see how it evolved). There isn't a #[diagnostic] for our case to further improve it.

@Sciencentistguy
Copy link
Author

I see. Thanks for the quick reply and explanation 🙂

Maybe if/when #[diagnostic] becomes a thing, this could be improved

@epage epage added A-derive Area: #[derive]` macro API S-blocked Status: Blocked on something else such as an RFC or other implementation work. labels Sep 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-derive Area: #[derive]` macro API C-bug Category: Updating dependencies S-blocked Status: Blocked on something else such as an RFC or other implementation work.
Projects
None yet
Development

No branches or pull requests

2 participants