Repository: taiki-e/cargo-hack (language: rust)

Issue:
--mutually-exclusive-features produces unexpected results
I have four features, for example `A, B, X, Y`.

I want to express either `A,B` or `X,Y`, but never together.

I came up with
```
--mutually-exclusive-features A,X \
--mutually-exclusive-features A,Y \
--mutually-exclusive-features B,X \
--mutually-exclusive-features B,Y
```

But I got none of the A, B, X, Y.

I expected:

```
A, B, AB, X, Y, XY
```

If my expectation of this command is correct, the fix is straightforward.

```diff
 
diff --git a/src/features.rs b/src/features.rs
index 6e3bb11..a7706a9 100644
--- a/src/features.rs
+++ b/src/features.rs
@@ -209,9 +209,9 @@ pub(crate) fn feature_powerset<'a>(
         .filter(move |fs| {
             // Filter any feature set containing more than one feature from the same mutually
             // exclusive group.
-            let mut count = 0;
-            for f in fs.iter().flat_map(|f| f.as_group()) {
-                for group in mutually_exclusive_features {
+            for group in mutually_exclusive_features {
+                let mut count = 0;
+                for f in fs.iter().flat_map(|f| f.as_group()) {
                     if group.matches(f) {
                         count += 1;
                         if count > 1 {
                            return false;
                        }
                    }
                }
            }
```






Discussion / hints:
Ping the original commiter @jhpratt 
I don't have the time at the moment to think about the correctness of the diff. If it works, though, then it's probably correct?
I can create a PR.

Fix patch:
diff --git a/src/features.rs b/src/features.rs
index 6e3bb11..6645cc1 100644
--- a/src/features.rs
+++ b/src/features.rs
@@ -209,9 +209,9 @@ pub(crate) fn feature_powerset<'a>(
         .filter(move |fs| {
             // Filter any feature set containing more than one feature from the same mutually
             // exclusive group.
-            let mut count = 0;
-            for f in fs.iter().flat_map(|f| f.as_group()) {
-                for group in mutually_exclusive_features {
+            for group in mutually_exclusive_features {
+                let mut count = 0;
+                for f in fs.iter().flat_map(|f| f.as_group()) {
                     if group.matches(f) {
                         count += 1;
                         if count > 1 {
@@ -353,8 +353,8 @@ mod tests {
 
         let map = map![("tokio", v![]), ("async-std", v![]), ("a", v![]), ("b", v!["a"])];
         let list = v!["a", "b", "tokio", "async-std"];
-        let filtered =
-            feature_powerset(&list, None, &[], &["tokio".into(), "async-std".into()], &map);
+        let mutually_exclusive_features = [Feature::group(["tokio", "async-std"])];
+        let filtered = feature_powerset(&list, None, &[], &mutually_exclusive_features, &map);
         assert_eq!(filtered, vec![
             vec!["a"],
             vec!["b"],
@@ -365,6 +365,19 @@ mod tests {
             vec!["a", "async-std"],
             vec!["b", "async-std"]
         ]);
+
+        let mutually_exclusive_features =
+            [Feature::group(["tokio", "a"]), Feature::group(["tokio", "async-std"])];
+        let filtered = feature_powerset(&list, None, &[], &mutually_exclusive_features, &map);
+        assert_eq!(filtered, vec![
+            vec!["a"],
+            vec!["b"],
+            vec!["tokio"],
+            vec!["b", "tokio"],
+            vec!["async-std"],
+            vec!["a", "async-std"],
+            vec!["b", "async-std"]
+        ]);
     }
 
     #[test]


Test patch: