@@ -13,7 +13,12 @@ use lexopt::{
1313 ValueExt as _,
1414} ;
1515
16- use crate :: { Feature , LogGroup , Partition , Rustup , term, version:: VersionRange } ;
16+ use crate :: {
17+ Feature , LogGroup , Partition , Rustup ,
18+ features:: { FeatureRequirement , parse_feature_requires} ,
19+ term,
20+ version:: VersionRange ,
21+ } ;
1722
1823pub ( crate ) struct Args {
1924 pub ( crate ) leading_args : Vec < String > ,
@@ -91,6 +96,8 @@ pub(crate) struct Args {
9196 /// --at-least-one-of <FEATURES>...
9297 /// Implies --exclude-no-default-features. Can be specified multiple times.
9398 pub ( crate ) at_least_one_of : Vec < Feature > ,
99+ /// --feature-requires <CONSTRAINTS>...
100+ pub ( crate ) feature_requires : Vec < FeatureRequirement > ,
94101
95102 // options that will be propagated to cargo
96103 /// --features <FEATURES>...
@@ -179,6 +186,7 @@ impl Args {
179186
180187 let mut group_features: Vec < String > = vec ! [ ] ;
181188 let mut mutually_exclusive_features: Vec < String > = vec ! [ ] ;
189+ let mut feature_requires: Vec < String > = vec ! [ ] ;
182190 let mut depth = None ;
183191
184192 let mut verbose = 0 ;
@@ -304,6 +312,7 @@ impl Args {
304312 Long ( "each-feature" ) => parse_flag ! ( each_feature) ,
305313 Long ( "feature-powerset" ) => parse_flag ! ( feature_powerset) ,
306314 Long ( "at-least-one-of" ) => at_least_one_of. push ( parser. value ( ) ?. parse ( ) ?) ,
315+ Long ( "feature-requires" ) => feature_requires. push ( parser. value ( ) ?. parse ( ) ?) ,
307316 Long ( "no-private" ) => parse_flag ! ( no_private) ,
308317 Long ( "ignore-private" ) => parse_flag ! ( ignore_private) ,
309318 Long ( "exclude-no-default-features" ) => parse_flag ! ( exclude_no_default_features) ,
@@ -429,6 +438,8 @@ impl Args {
429438 requires ( "--mutually-exclusive-features" , & [ "--feature-powerset" ] ) ?;
430439 } else if !at_least_one_of. is_empty ( ) {
431440 requires ( "--at-least-one-of" , & [ "--feature-powerset" ] ) ?;
441+ } else if !feature_requires. is_empty ( ) {
442+ requires ( "--feature-requires" , & [ "--feature-powerset" ] ) ?;
432443 }
433444 }
434445
@@ -437,6 +448,14 @@ impl Args {
437448 let mutually_exclusive_features =
438449 parse_grouped_features ( & mutually_exclusive_features, "mutually-exclusive-features" ) ?;
439450 let at_least_one_of = parse_grouped_features ( & at_least_one_of, "at-least-one-of" ) ?;
451+ let feature_requires: Vec < FeatureRequirement > = feature_requires
452+ . iter ( )
453+ . map ( |s| parse_feature_requires ( s) )
454+ . collect :: < Result < Vec < _ > , _ > > ( )
455+ . map_err ( |e| format_err ! ( "{e}" ) ) ?
456+ . into_iter ( )
457+ . flatten ( )
458+ . collect ( ) ;
440459
441460 if let Some ( subcommand) = subcommand. as_deref ( ) {
442461 match subcommand {
@@ -637,6 +656,7 @@ impl Args {
637656 depth,
638657 group_features,
639658 mutually_exclusive_features,
659+ feature_requires,
640660
641661 exclude_features,
642662 exclude_no_default_features,
@@ -779,6 +799,21 @@ const HELP: &[HelpText<'_>] = &[
779799 "This flag can only be used together with --feature-powerset flag." ,
780800 ] ,
781801 ) ,
802+ (
803+ "" ,
804+ "--feature-requires" ,
805+ "<CONSTRAINTS>..." ,
806+ "Comma separated list of feature dependency constraints" ,
807+ & [
808+ "Each constraint has the form `FEATURE:EXPR` where EXPR is a boolean expression \
809+ using AND, OR, and parentheses. AND binds tighter than OR.",
810+ "Example: `--feature-requires \" c:a OR b\" ` means feature c requires at least \
811+ one of a or b.",
812+ "To specify multiple constraints, separate with commas or use this option multiple times: \
813+ `--feature-requires \" c:a OR b,d:e AND f\" `",
814+ "This flag can only be used together with --feature-powerset flag." ,
815+ ] ,
816+ ) ,
782817 (
783818 "" ,
784819 "--include-features" ,
@@ -998,6 +1033,7 @@ fn similar_flags(flag: &str, subcommand: Option<&str>) -> Result<()> {
9981033 "--include-deps-features"
9991034 }
10001035 "ignore-unknown-feature" => "--ignore-unknown-features" ,
1036+ "feature-require" | "features-requires" | "features-require" => "--feature-requires" ,
10011037 _ => return Ok ( ( ) ) ,
10021038 } ;
10031039 similar_arg ( & Long ( flag) , subcommand, expected)
0 commit comments