@@ -7,11 +7,38 @@ pub type FeaturesMap = BTreeMap<String, Vec<String>>;
77///
88/// See <https://rust-lang.github.io/rfcs/3143-cargo-weak-namespaced-features.html>.
99pub fn split_features ( features : FeaturesMap ) -> ( FeaturesMap , FeaturesMap ) {
10- features. into_iter ( ) . partition ( |( _k, vals) | {
11- !vals
12- . iter ( )
13- . any ( |v| v. starts_with ( "dep:" ) || v. contains ( "?/" ) )
14- } )
10+ const ITERATION_LIMIT : usize = 100 ;
11+
12+ // First, we partition the features into two groups: those that use the new
13+ // features syntax (`features2`) and those that don't (`features`).
14+ let ( mut features, mut features2) =
15+ features
16+ . into_iter ( )
17+ . partition :: < FeaturesMap , _ > ( |( _k, vals) | {
18+ !vals
19+ . iter ( )
20+ . any ( |v| v. starts_with ( "dep:" ) || v. contains ( "?/" ) )
21+ } ) ;
22+
23+ // Then, we recursively move features from `features` to `features2` if they
24+ // depend on features in `features2`.
25+ for _ in 0 ..ITERATION_LIMIT {
26+ let split = features
27+ . into_iter ( )
28+ . partition :: < FeaturesMap , _ > ( |( _k, vals) | {
29+ !vals. iter ( ) . any ( |v| features2. contains_key ( v) )
30+ } ) ;
31+
32+ features = split. 0 ;
33+
34+ if !split. 1 . is_empty ( ) {
35+ features2. extend ( split. 1 ) ;
36+ } else {
37+ break ;
38+ }
39+ }
40+
41+ ( features, features2)
1542}
1643
1744#[ cfg( test) ]
@@ -93,8 +120,8 @@ mod tests {
93120
94121 let ( features, features2) = split_features ( features) ;
95122
96- assert_compact_debug_snapshot ! ( features, @r#"{"feature1": ["feature2"], "feature2": ["feature3"]}"# ) ;
97- assert_compact_debug_snapshot ! ( features2, @r#"{"feature3": ["dep:foo"]}"# ) ;
123+ assert_compact_debug_snapshot ! ( features, @"{}" ) ;
124+ assert_compact_debug_snapshot ! ( features2, @r#"{"feature1": ["feature2"], "feature2": ["feature3"], " feature3": ["dep:foo"]}"# ) ;
98125 }
99126
100127 #[ test]
0 commit comments