You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A-parsingArea: Parser's logic and needs it changed somehow.C-bugCategory: Updating dependenciesE-mediumCall for participation: Experience needed to fix: Medium / intermediate
use clap::{Arg,ArgAction,Command};use std::process::exit;fnmain(){let matches = Command::new("cmd").args_conflicts_with_subcommands(true).arg(Arg::new("foo").short('f').long("foo").action(ArgAction::SetTrue).exclusive(true),).subcommand(Command::new("bar").short_flag('B').long_flag("bar").arg(Arg::new("baz").short('b').long("baz").action(ArgAction::Append).num_args(1..),),).get_matches();if matches.get_flag("foo"){println!("-f is used")};println!("{:?}",
matches
.subcommand_matches("bar")
.unwrap_or_else(|| {
println!("Bar subcommand is not used");
exit(0)})
.get_many::<String>("baz").unwrap().map(|x|x.to_string()).collect::<Vec<String>>());}
Steps to reproduce the bug with the above code
cargo run -- -f -Bb 1 2
Actual Behaviour
-f is used
["1", "2"]
Expected Behaviour
error: -f can not be used with -B subcommand
example:
-f <foo>
Additional Context
Using it with/without.subcommand_precedence_over_arg(true) won't make any difference
Debug Output
[clap_builder::builder::command]Command::_do_parse
[clap_builder::builder::command]Command::_build: name="cmd"
[clap_builder::builder::command]Command::_propagate:cmd
[clap_builder::builder::command]Command::_check_help_and_version:cmd 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:cmd
[clap_builder::builder::debug_asserts]Command::_debug_asserts
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:foo
[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 '"-f"'
[clap_builder::parser::parser]Parser::possible_subcommand: arg=Ok("-f")
[clap_builder::parser::parser]Parser::get_matches_with: sc=None
[clap_builder::parser::parser]Parser::parse_short_arg: short_arg=ShortFlags { inner: "f", utf8_prefix: CharIndices { front_offset: 0, iter: Chars(['f']) }, invalid_suffix: None }
[clap_builder::parser::parser]Parser::parse_short_arg:iter:f
[clap_builder::parser::parser]Parser::parse_short_arg:iter:f: Found valid opt or flag
[clap_builder::parser::parser]Parser::react action=SetTrue, identifier=Some(Short), source=CommandLine
[clap_builder::parser::parser]Parser::react: has default_missing_vals
[clap_builder::parser::parser]Parser::remove_overrides: id="foo"
[clap_builder::parser::arg_matcher]ArgMatcher::start_custom_arg: id="foo", source=CommandLine
[clap_builder::builder::command]Command::groups_for_arg: id="foo"
[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_short_arg ValuesDone
[clap_builder::parser::parser]Parser::get_matches_with: Begin parsing '"-Bb"'
[clap_builder::parser::parser]Parser::possible_subcommand: arg=Ok("-Bb")
[clap_builder::parser::parser]Parser::get_matches_with: sc=None
[clap_builder::parser::parser]Parser::parse_short_arg: short_arg=ShortFlags { inner: "Bb", utf8_prefix: CharIndices { front_offset: 0, iter: Chars(['B', 'b']) }, invalid_suffix: None }
[clap_builder::parser::parser]Parser::parse_short_arg:iter:B
[clap_builder::parser::parser]Parser::parse_short_arg:iter:B: subcommand=bar
[clap_builder::parser::parser]Parser::parse_short_arg: cur_idx:=2
[clap_builder::parser::parser]Parser::get_matches_with: After parse_short_arg FlagSubCommand("bar")
[clap_builder::parser::parser]Parser::get_matches_with:FlagSubCommandShort: subcmd_name=bar, keep_state=true, flag_subcmd_skip=1
[clap_builder::parser::parser]Parser::parse_subcommand
[clap_builder::builder::command]Command::_build_subcommand Setting bin_name of bar to "args bar"
[clap_builder::builder::command]Command::_build_subcommand Setting display_name of bar to "cmd-bar"
[clap_builder::builder::command]Command::_build: name="bar"
[clap_builder::builder::command]Command::_propagate:bar
[clap_builder::builder::command]Command::_check_help_and_version:bar 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:bar
[clap_builder::builder::debug_asserts]Command::_debug_asserts
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:baz
[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=bar
[clap_builder::parser::parser]Parser::get_matches_with
[clap_builder::parser::parser]Parser::get_matches_with: Begin parsing '"-Bb"'
[clap_builder::parser::parser]Parser::possible_subcommand: arg=Ok("-Bb")
[clap_builder::parser::parser]Parser::get_matches_with: sc=None
[clap_builder::parser::parser]Parser::parse_short_arg: short_arg=ShortFlags { inner: "Bb", utf8_prefix: CharIndices { front_offset: 0, iter: Chars(['B', 'b']) }, invalid_suffix: None }
[clap_builder::parser::parser]Parser::parse_short_arg:iter:b
[clap_builder::parser::parser]Parser::parse_short_arg:iter:b: Found valid opt or flag
[clap_builder::parser::parser]Parser::parse_short_arg:iter:b: val="", short_arg=ShortFlags { inner: "Bb", utf8_prefix: CharIndices { front_offset: 2, iter: Chars([]) }, invalid_suffix: None }
[clap_builder::parser::parser]Parser::parse_opt_value; arg=baz, val=None, has_eq=false
[clap_builder::parser::parser]Parser::parse_opt_value; arg.settings=ArgFlags(0)
[clap_builder::parser::parser]Parser::parse_opt_value; Checking for val...
[clap_builder::parser::parser]Parser::parse_opt_value: More arg vals required...
[clap_builder::parser::parser]Parser::get_matches_with: After parse_short_arg Opt("baz")
[clap_builder::parser::parser]Parser::get_matches_with: Begin parsing '"1"'
[clap_builder::parser::arg_matcher]ArgMatcher::needs_more_vals: o=baz, pending=1
[clap_builder::parser::arg_matcher]ArgMatcher::needs_more_vals: expected=1..=18446744073709551615, actual=1
[clap_builder::parser::parser]Parser::get_matches_with: Begin parsing '"2"'
[clap_builder::parser::arg_matcher]ArgMatcher::needs_more_vals: o=baz, pending=2
[clap_builder::parser::arg_matcher]ArgMatcher::needs_more_vals: expected=1..=18446744073709551615, actual=2
[clap_builder::parser::parser]Parser::resolve_pending: id="baz"
[clap_builder::parser::parser]Parser::react action=Append, identifier=Some(Short), source=CommandLine
[clap_builder::parser::parser]Parser::react: cur_idx:=3
[clap_builder::parser::parser]Parser::remove_overrides: id="baz"
[clap_builder::parser::arg_matcher]ArgMatcher::start_custom_arg: id="baz", source=CommandLine
[clap_builder::builder::command]Command::groups_for_arg: id="baz"
[clap_builder::parser::parser]Parser::push_arg_values: ["1", "2"]
[clap_builder::parser::parser]Parser::add_single_val_to_arg: cur_idx:=4
[clap_builder::parser::parser]Parser::add_single_val_to_arg: cur_idx:=5
[clap_builder::parser::arg_matcher]ArgMatcher::needs_more_vals: o=baz, pending=0
[clap_builder::parser::arg_matcher]ArgMatcher::needs_more_vals: expected=1..=18446744073709551615, actual=0
[clap_builder::parser::parser]Parser::react not enough values passed in, leaving it to the validator to complain
[clap_builder::parser::parser]Parser::add_defaults
[clap_builder::parser::parser]Parser::add_defaults:iter:baz:
[clap_builder::parser::parser]Parser::add_default_value: doesn't have conditional defaults
[clap_builder::parser::parser]Parser::add_default_value:iter:baz: doesn't have default vals
[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="baz"
[clap_builder::parser::validator]Conflicts::gather_direct_conflicts id="baz", conflicts=[]
[clap_builder::parser::validator]Validator::validate: needs_val_of="baz"
[clap_builder::parser::validator]Validator::validate_conflicts
[clap_builder::parser::validator]Validator::validate_exclusive
[clap_builder::parser::validator]Validator::validate_conflicts::iter: id="baz"
[clap_builder::parser::validator]Conflicts::gather_conflicts: arg="baz"
[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:"baz"
[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:foo:
[clap_builder::parser::parser]Parser::add_default_value: doesn't have conditional defaults
[clap_builder::parser::parser]Parser::add_default_value:iter:foo: has default vals
[clap_builder::parser::parser]Parser::add_default_value:iter:foo: 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="foo"
[clap_builder::parser::validator]Conflicts::gather_direct_conflicts id="foo", conflicts=[]
[clap_builder::parser::validator]Validator::validate_conflicts
[clap_builder::parser::validator]Validator::validate_exclusive
[clap_builder::parser::validator]Validator::validate_conflicts::iter: id="foo"
[clap_builder::parser::validator]Conflicts::gather_conflicts: arg="foo"
[clap_builder::parser::validator]Conflicts::gather_conflicts: conflicts=[]
[clap_builder::parser::arg_matcher]ArgMatcher::get_global_values: global_arg_vec=[]
The text was updated successfully, but these errors were encountered:
epage
changed the title
Argument doesn't conflict with subcommand even if it's set
Subcommand flags can't conflict with arguments
Jan 10, 2024
epage
added
A-parsing
Area: Parser's logic and needs it changed somehow.
E-medium
Call for participation: Experience needed to fix: Medium / intermediate
labels
Jan 10, 2024
As noted in #5294, there is likely a similar bug with subcommand_precedence_over_arg because we only check for conflicts if the argument doesn't exist.
epage
added a commit
to epage/clap
that referenced
this issue
Jan 11, 2024
A-parsingArea: Parser's logic and needs it changed somehow.C-bugCategory: Updating dependenciesE-mediumCall for participation: Experience needed to fix: Medium / intermediate
Please complete the following tasks
Rust Version
1.75.0
Clap Version
4.4.14
Minimal reproducible code
Steps to reproduce the bug with the above code
cargo run -- -f -Bb 1 2
Actual Behaviour
Expected Behaviour
Additional Context
Using it with/without
.subcommand_precedence_over_arg(true)
won't make any differenceDebug Output
The text was updated successfully, but these errors were encountered: