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

required_if_eq doesn't respect global arguments #4941

Closed
2 tasks done
Gordon01 opened this issue May 26, 2023 · 2 comments
Closed
2 tasks done

required_if_eq doesn't respect global arguments #4941

Gordon01 opened this issue May 26, 2023 · 2 comments
Labels
A-parsing Area: Parser's logic and needs it changed somehow. A-validators Area: ArgMatches validation logi C-bug Category: Updating dependencies E-medium Call for participation: Experience needed to fix: Medium / intermediate

Comments

@Gordon01
Copy link

Gordon01 commented May 26, 2023

Please complete the following tasks

Rust Version

rustc 1.69.0 (84c898d65 2023-04-16)

Clap Version

4.3.0

Minimal reproducible code

use clap::{Args, Parser, Subcommand};

#[derive(Parser)]
struct Cli {
    /// Output JSON formatted messages
    #[arg(short, long, global = true)]
    json: bool,
    #[command(subcommand)]
    command: Commands,
}

#[derive(Args)]
struct Force {
    /// Skip confirmation step
    #[arg(short, long, required_if_eq("json", "true"))]
    force: bool,
}

#[derive(Subcommand)]
#[command(rename_all = "snake_case")]
enum Commands {
    /// Delete all expired tokens
    CleanupTokens(Force),
}

fn main() {
    let _ = Cli::parse();
    println!("Success");
}

Steps to reproduce the bug with the above code

cargo r -q -- --json cleanup_tokens

Actual Behaviour

Success printed

Expected Behaviour

error: the following required arguments were not provided:
  --force

Usage: playground.exe --json cleanup_tokens --force

For more information, try '--help'.

Additional Context

TLDR:
cargo r -q -- --json cleanup_tokens doesn't work
cargo r -q -- cleanup_tokens --json does.

Debug Output

cargo r -q -- --json cleanup_tokens

[clap_builder::builder::command]Command::_do_parse
[clap_builder::builder::command]Command::_build: name="playground"
[clap_builder::builder::command]Command::_propagate:playground
[clap_builder::builder::command]Command::_check_help_and_version:playground expand_help_tree=false
[clap_builder::builder::command]Command::long_help_exists
[clap_builder::builder::command]Command::_check_help_and_version: Building default --help
[clap_builder::builder::command]Command::_check_help_and_version: Building help subcommand
[clap_builder::builder::command]Command::_propagate_global_args:playground
[clap_builder::builder::command]Command::_propagate pushing "json" to cleanup_tokens
[clap_builder::builder::debug_asserts]Command::_debug_asserts
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:json
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:help
[clap_builder::builder::debug_asserts]Command::_verify_positionals
[clap_builder::parser::parser]Parser::get_matches_with
[clap_builder::parser::parser]Parser::get_matches_with: Begin parsing '"--json"'
[clap_builder::parser::parser]Parser::possible_subcommand: arg=Ok("--json")
[clap_builder::parser::parser]Parser::get_matches_with: sc=None
[clap_builder::parser::parser]Parser::parse_long_arg
[clap_builder::parser::parser]Parser::parse_long_arg: Does it contain '='...
[clap_builder::parser::parser]Parser::parse_long_arg: Found valid arg or flag '--json'
[clap_builder::parser::parser]Parser::parse_long_arg("json"): Presence validated
[clap_builder::parser::parser]Parser::react action=SetTrue, identifier=Some(Long), source=CommandLine
[clap_builder::parser::parser]Parser::react: has default_missing_vals
[clap_builder::parser::parser]Parser::remove_overrides: id="json"
[clap_builder::parser::arg_matcher]ArgMatcher::start_custom_arg: id="json", source=CommandLine
[clap_builder::builder::command]Command::groups_for_arg: id="json"
[clap_builder::parser::arg_matcher]ArgMatcher::start_custom_arg: id="Cli", source=CommandLine
[clap_builder::parser::parser]Parser::push_arg_values: ["true"]
[clap_builder::parser::parser]Parser::add_single_val_to_arg: cur_idx:=1
[clap_builder::parser::parser]Parser::get_matches_with: After parse_long_arg ValuesDone
[clap_builder::parser::parser]Parser::get_matches_with: Begin parsing '"cleanup_tokens"'
[clap_builder::parser::parser]Parser::possible_subcommand: arg=Ok("cleanup_tokens")
[clap_builder::parser::parser]Parser::get_matches_with: sc=Some("cleanup_tokens")
[clap_builder::parser::parser]Parser::parse_subcommand
[ clap_builder::output::usage]Usage::get_required_usage_from: incls=[], matcher=false, incl_last=true
[ clap_builder::output::usage]Usage::get_required_usage_from: unrolled_reqs=[]
[ clap_builder::output::usage]Usage::get_required_usage_from: ret_val=[]
[clap_builder::builder::command]Command::_build_subcommand Setting bin_name of cleanup_tokens to "playground.exe cleanup_tokens"     
[clap_builder::builder::command]Command::_build_subcommand Setting display_name of cleanup_tokens to "playground-cleanup_tokens"     
[clap_builder::builder::command]Command::_build: name="cleanup_tokens"
[clap_builder::builder::command]Command::_propagate:cleanup_tokens
[clap_builder::builder::command]Command::_check_help_and_version:cleanup_tokens expand_help_tree=false
[clap_builder::builder::command]Command::long_help_exists
[clap_builder::builder::command]Command::_check_help_and_version: Building default --help
[clap_builder::builder::command]Command::_propagate_global_args:cleanup_tokens
[clap_builder::builder::debug_asserts]Command::_debug_asserts
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:force
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:json
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:help
[clap_builder::builder::debug_asserts]Command::_verify_positionals
[clap_builder::parser::parser]Parser::parse_subcommand: About to parse sc=cleanup_tokens
[clap_builder::parser::parser]Parser::get_matches_with
[clap_builder::parser::parser]Parser::add_defaults
[clap_builder::parser::parser]Parser::add_defaults:iter:force:
[clap_builder::parser::parser]Parser::add_default_value: doesn't have conditional defaults
[clap_builder::parser::parser]Parser::add_default_value:iter:force: has default vals
[clap_builder::parser::parser]Parser::add_default_value:iter:force: wasn't used
[clap_builder::parser::parser]Parser::react action=SetTrue, identifier=None, source=DefaultValue
[clap_builder::parser::arg_matcher]ArgMatcher::start_custom_arg: id="force", source=DefaultValue
[clap_builder::parser::parser]Parser::push_arg_values: ["false"]
[clap_builder::parser::parser]Parser::add_single_val_to_arg: cur_idx:=1
[clap_builder::parser::parser]Parser::add_defaults:iter:json:
[clap_builder::parser::parser]Parser::add_default_value: doesn't have conditional defaults
[clap_builder::parser::parser]Parser::add_default_value:iter:json: has default vals
[clap_builder::parser::parser]Parser::add_default_value:iter:json: wasn't used
[clap_builder::parser::parser]Parser::react action=SetTrue, identifier=None, source=DefaultValue
[clap_builder::parser::arg_matcher]ArgMatcher::start_custom_arg: id="json", source=DefaultValue
[clap_builder::parser::parser]Parser::push_arg_values: ["false"]
[clap_builder::parser::parser]Parser::add_single_val_to_arg: cur_idx:=2
[clap_builder::parser::parser]Parser::add_defaults:iter:help:
[clap_builder::parser::parser]Parser::add_default_value: doesn't have conditional defaults
[clap_builder::parser::parser]Parser::add_default_value:iter:help: doesn't have default vals
[clap_builder::parser::validator]Validator::validate
[clap_builder::parser::validator]Validator::validate_conflicts
[clap_builder::parser::validator]Validator::validate_exclusive
[clap_builder::parser::validator]Validator::validate_required: required=ChildGraph([])
[clap_builder::parser::validator]Validator::gather_requires
[clap_builder::parser::validator]Validator::validate_required: is_exclusive_present=false
[clap_builder::parser::parser]Parser::add_defaults
[clap_builder::parser::parser]Parser::add_defaults:iter:json:
[clap_builder::parser::parser]Parser::add_default_value: doesn't have conditional defaults
[clap_builder::parser::parser]Parser::add_default_value:iter:json: has default vals
[clap_builder::parser::parser]Parser::add_default_value:iter:json: was used
[clap_builder::parser::parser]Parser::add_defaults:iter:help:
[clap_builder::parser::validator]Validator::validate_conflicts::iter: id="json"
[clap_builder::parser::validator]Conflicts::gather_conflicts: arg="json"
[clap_builder::parser::validator]Conflicts::gather_conflicts: conflicts=[]
[clap_builder::parser::validator]Validator::validate_required: required=ChildGraph([])
[clap_builder::parser::validator]Validator::gather_requires
[clap_builder::parser::validator]Validator::gather_requires:iter:"json"
[clap_builder::parser::validator]Validator::gather_requires:iter:"Cli"
[clap_builder::parser::validator]Validator::gather_requires:iter:"Cli":group
[clap_builder::parser::validator]Validator::validate_required: is_exclusive_present=false
[clap_builder::parser::arg_matcher]ArgMatcher::get_global_values: global_arg_vec=["json", "json"]
Success

cargo r -q -- cleanup_tokens --json

[clap_builder::builder::command]Command::_do_parse
[clap_builder::builder::command]Command::_build: name="playground"
[clap_builder::builder::command]Command::_propagate:playground
[clap_builder::builder::command]Command::_check_help_and_version:playground expand_help_tree=false
[clap_builder::builder::command]Command::long_help_exists
[clap_builder::builder::command]Command::_check_help_and_version: Building default --help
[clap_builder::builder::command]Command::_check_help_and_version: Building help subcommand
[clap_builder::builder::command]Command::_propagate_global_args:playground
[clap_builder::builder::command]Command::_propagate pushing "json" to cleanup_tokens
[clap_builder::builder::debug_asserts]Command::_debug_asserts
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:json
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:help
[clap_builder::builder::debug_asserts]Command::_verify_positionals
[clap_builder::parser::parser]Parser::get_matches_with
[clap_builder::parser::parser]Parser::get_matches_with: Begin parsing '"cleanup_tokens"'
[clap_builder::parser::parser]Parser::possible_subcommand: arg=Ok("cleanup_tokens")
[clap_builder::parser::parser]Parser::get_matches_with: sc=Some("cleanup_tokens")
[clap_builder::parser::parser]Parser::parse_subcommand
[ clap_builder::output::usage]Usage::get_required_usage_from: incls=[], matcher=false, incl_last=true
[ clap_builder::output::usage]Usage::get_required_usage_from: unrolled_reqs=[]
[ clap_builder::output::usage]Usage::get_required_usage_from: ret_val=[]
[clap_builder::builder::command]Command::_build_subcommand Setting bin_name of cleanup_tokens to "playground.exe cleanup_tokens"
[clap_builder::builder::command]Command::_build_subcommand Setting display_name of cleanup_tokens to "playground-cleanup_tokens"        
[clap_builder::builder::command]Command::_build: name="cleanup_tokens"
[clap_builder::builder::command]Command::_propagate:cleanup_tokens
[clap_builder::builder::command]Command::_check_help_and_version:cleanup_tokens expand_help_tree=false
[clap_builder::builder::command]Command::long_help_exists
[clap_builder::builder::command]Command::_check_help_and_version: Building default --help
[clap_builder::builder::command]Command::_propagate_global_args:cleanup_tokens
[clap_builder::builder::debug_asserts]Command::_debug_asserts
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:force
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:json
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:help
[clap_builder::builder::debug_asserts]Command::_verify_positionals
[clap_builder::parser::parser]Parser::parse_subcommand: About to parse sc=cleanup_tokens
[clap_builder::parser::parser]Parser::get_matches_with
[clap_builder::parser::parser]Parser::get_matches_with: Begin parsing '"--json"'
[clap_builder::parser::parser]Parser::possible_subcommand: arg=Ok("--json")
[clap_builder::parser::parser]Parser::get_matches_with: sc=None
[clap_builder::parser::parser]Parser::parse_long_arg
[clap_builder::parser::parser]Parser::parse_long_arg: Does it contain '='...
[clap_builder::parser::parser]Parser::parse_long_arg: Found valid arg or flag '--json'
[clap_builder::parser::parser]Parser::parse_long_arg("json"): Presence validated
[clap_builder::parser::parser]Parser::react action=SetTrue, identifier=Some(Long), source=CommandLine
[clap_builder::parser::parser]Parser::react: has default_missing_vals
[clap_builder::parser::parser]Parser::remove_overrides: id="json"
[clap_builder::parser::arg_matcher]ArgMatcher::start_custom_arg: id="json", source=CommandLine
[clap_builder::builder::command]Command::groups_for_arg: id="json"
[clap_builder::parser::parser]Parser::push_arg_values: ["true"]
[clap_builder::parser::parser]Parser::add_single_val_to_arg: cur_idx:=1
[clap_builder::parser::parser]Parser::get_matches_with: After parse_long_arg ValuesDone
[clap_builder::parser::parser]Parser::add_defaults
[clap_builder::parser::parser]Parser::add_defaults:iter:force:
[clap_builder::parser::parser]Parser::add_default_value: doesn't have conditional defaults
[clap_builder::parser::parser]Parser::add_default_value:iter:force: has default vals
[clap_builder::parser::parser]Parser::add_default_value:iter:force: wasn't used
[clap_builder::parser::parser]Parser::react action=SetTrue, identifier=None, source=DefaultValue
[clap_builder::parser::arg_matcher]ArgMatcher::start_custom_arg: id="force", source=DefaultValue
[clap_builder::parser::parser]Parser::push_arg_values: ["false"]
[clap_builder::parser::parser]Parser::add_single_val_to_arg: cur_idx:=2
[clap_builder::parser::parser]Parser::add_defaults:iter:json:
[clap_builder::parser::parser]Parser::add_default_value: doesn't have conditional defaults
[clap_builder::parser::parser]Parser::add_default_value:iter:json: has default vals
[clap_builder::parser::parser]Parser::add_default_value:iter:json: was used
[clap_builder::parser::parser]Parser::add_defaults:iter:help:
[clap_builder::parser::parser]Parser::add_default_value: doesn't have conditional defaults
[clap_builder::parser::parser]Parser::add_default_value:iter:help: doesn't have default vals
[clap_builder::parser::validator]Validator::validate
[clap_builder::builder::command]Command::groups_for_arg: id="json"
[clap_builder::parser::validator]Conflicts::gather_direct_conflicts id="json", conflicts=[]
[clap_builder::parser::validator]Validator::validate_conflicts
[clap_builder::parser::validator]Validator::validate_exclusive
[clap_builder::parser::validator]Validator::validate_conflicts::iter: id="json"
[clap_builder::parser::validator]Conflicts::gather_conflicts: arg="json"
[clap_builder::parser::validator]Conflicts::gather_conflicts: conflicts=[]
[clap_builder::parser::validator]Validator::validate_required: required=ChildGraph([])
[clap_builder::parser::validator]Validator::gather_requires
[clap_builder::parser::validator]Validator::gather_requires:iter:"json"
[clap_builder::parser::validator]Validator::validate_required: is_exclusive_present=false
[clap_builder::parser::validator]Validator::validate_required:iter: Missing "force"
[clap_builder::parser::validator]Validator::missing_required_error; incl=["force"]
[clap_builder::parser::validator]Validator::missing_required_error: reqs=ChildGraph([])
[ clap_builder::output::usage]Usage::get_required_usage_from: incls=["force"], matcher=true, incl_last=true
[ clap_builder::output::usage]Usage::get_required_usage_from: unrolled_reqs=[]
[ clap_builder::output::usage]Usage::get_required_usage_from:iter:"force" arg is_present=false
[ clap_builder::output::usage]Usage::get_required_usage_from: ret_val=[StyledStr("\u{1b}[1m--force\u{1b}[0m")]
[clap_builder::parser::validator]Validator::missing_required_error: req_args=[
    "--force",
]
[ clap_builder::output::usage]Usage::create_usage_with_title
[ clap_builder::output::usage]Usage::create_usage_no_title
[ clap_builder::output::usage]Usage::create_smart_usage
[ clap_builder::output::usage]Usage::get_args: incls=["json", "force"]
[ clap_builder::output::usage]Usage::get_args: unrolled_reqs=[]
[ clap_builder::output::usage]Usage::get_args: ret_val=[StyledStr("\u{1b}[1m--json\u{1b}[0m"), StyledStr("\u{1b}[1m--force\u{1b}[0m")]  
[clap_builder::builder::command]Command::color: Color setting...
[clap_builder::builder::command]Auto
[clap_builder::builder::command]Command::color: Color setting...
[clap_builder::builder::command]Auto
error: the following required arguments were not provided:
  --force

Usage: playground.exe cleanup_tokens --json --force
@Gordon01 Gordon01 added the C-bug Category: Updating dependencies label May 26, 2023
@epage epage added A-parsing Area: Parser's logic and needs it changed somehow. E-medium Call for participation: Experience needed to fix: Medium / intermediate A-validators Area: ArgMatches validation logi labels May 26, 2023
@epage
Copy link
Member

epage commented May 26, 2023

Currently, as we recurse through subcommands, we

  1. Parse
  2. Add defaults
  3. Validate

Once done, we then add globals.

We'd need to rework this and my gut says it'll take some finessing to ensure we get the behavior we want for validation, defaults, and globals.

@epage
Copy link
Member

epage commented Jun 1, 2023

Ah, we do have an existing issue for this, closing in favor of #1546

@epage epage closed this as not planned Won't fix, can't repro, duplicate, stale Jun 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-parsing Area: Parser's logic and needs it changed somehow. A-validators Area: ArgMatches validation logi C-bug Category: Updating dependencies E-medium Call for participation: Experience needed to fix: Medium / intermediate
Projects
None yet
Development

No branches or pull requests

2 participants