clap-rs / clap

A full featured, fast Command Line Argument Parser for Rust
docs.rs/clap
Apache License 2.0
14.31k stars 1.04k forks source link

panics with error incomprehensible to `#[derive(..)]` user #4911

Open rukai opened 1 year ago

rukai commented 1 year ago

Please complete the following tasks

Rust Version

rustc 1.69.0 (84c898d65 2023-04-16)

Clap Version

4.2.7

Minimal reproducible code

use clap::{Parser, Subcommand};

fn main() {
    Args::parse();
}

#[derive(Subcommand)]
pub enum Mode {
    Orchestrator {
        domains: Vec<String>,
        email: Option<String>,
    },
    Other,
}

#[derive(Parser)]
pub struct Args {
    #[command(subcommand)]
    pub mode: Mode,
}

Steps to reproduce the bug with the above code

cargo run -- orchestrator --help

Actual Behaviour

It gives the panic message:

thread 'main' panicked at 'When using a positional argument with `.num_args(1..)` that is *not the last* positional argument, the last positional argument (i.e. the one with the highest index) *must* have .required(true) or .last(true) set.', /home/rukai/.cargo/registry/src/github.com-1ecc6299db9ec823/clap_builder-4.2.7/src/builder/debug_asserts.rs:587:9
stack backtrace:

Expected Behaviour

I've observed that swapping the order of email and domains fixes the panic but:

I expect the error to explain how to fix the issue. Maybe the error makes sense to someone that is familiar with the builder API but I have only ever used the #[derive()] API.

Can you maybe detect that the user is using #[derives] so that you can give an error that makes sense to them?

Additional Context

No response

Debug Output

No response

epage commented 1 year ago

4912 clarify the wording a bit

Can you maybe detect that the user is using #[derives] so that you can give an error that makes sense to them?

We could switch the behavior based on the derive feature but that could be coming in through a dependency, so I'd rather not do that.

In general, the error isn't that great. It especially should say which args / fields are involved.