@@ -7,11 +7,38 @@ pub type FeaturesMap = BTreeMap<String, Vec<String>>;
7
7
///
8
8
/// See <https://rust-lang.github.io/rfcs/3143-cargo-weak-namespaced-features.html>.
9
9
pub 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)
15
42
}
16
43
17
44
#[ cfg( test) ]
@@ -93,8 +120,8 @@ mod tests {
93
120
94
121
let ( features, features2) = split_features ( features) ;
95
122
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"]}"# ) ;
98
125
}
99
126
100
127
#[ test]
0 commit comments