Incompatible features#
Scenario: an HTTP client crate offers three TLS backends: native-tls,
rustls, and boring. A consumer picks at most one — enabling multiple
backends is a real conflict (here the code even compile_error!s on it). The
crate also has independent logging and metrics features that should keep
their full powerset.
[package]
name = "http-client"
version = "0.1.0"
edition = "2024"
[features]
native-tls = []
rustls = []
boring = []
logging = []
metrics = []
[package.metadata.cargo-fc]
# These TLS backends are alternatives; logging and metrics remain independent.
mutually_exclusive_features = [["native-tls", "rustls", "boring"]]
[workspace]mutually_exclusive_features keeps zero or one backend in every generated
combination and crosses those four choices with every subset of the two
independent features. cargo fc check therefore visits exactly
(3 + 1) × 2² = 16 combinations, without ever generating a conflicting pair:
$ cargo fc --summary-only check Checking [ 1/16] http-client ( features = [] ) Checking [ 2/16] http-client ( features = [boring] ) Checking [ 3/16] http-client ( features = [boring, logging] ) Checking [ 4/16] http-client ( features = [boring, logging, metrics] ) Checking [ 5/16] http-client ( features = [boring, metrics] ) Checking [ 6/16] http-client ( features = [logging] ) Checking [ 7/16] http-client ( features = [logging, metrics] ) Checking [ 8/16] http-client ( features = [logging, metrics, native-tls] ) Checking [ 9/16] http-client ( features = [logging, metrics, rustls] ) Checking [10/16] http-client ( features = [logging, native-tls] ) Checking [11/16] http-client ( features = [logging, rustls] ) Checking [12/16] http-client ( features = [metrics] ) Checking [13/16] http-client ( features = [metrics, native-tls] ) Checking [14/16] http-client ( features = [metrics, rustls] ) Checking [15/16] http-client ( features = [native-tls] ) Checking [16/16] http-client ( features = [rustls] ) Finished 16 feature combinations for 1 package in 0.00s PASS http-client ( 0 errors, 0 warnings, features = [] ) PASS http-client ( 0 errors, 0 warnings, features = [boring] ) PASS http-client ( 0 errors, 0 warnings, features = [boring, logging] ) PASS http-client ( 0 errors, 0 warnings, features = [boring, logging, metrics] ) PASS http-client ( 0 errors, 0 warnings, features = [boring, metrics] ) PASS http-client ( 0 errors, 0 warnings, features = [logging] ) PASS http-client ( 0 errors, 0 warnings, features = [logging, metrics] ) PASS http-client ( 0 errors, 0 warnings, features = [logging, metrics, native-tls] ) PASS http-client ( 0 errors, 0 warnings, features = [logging, metrics, rustls] ) PASS http-client ( 0 errors, 0 warnings, features = [logging, native-tls] ) PASS http-client ( 0 errors, 0 warnings, features = [logging, rustls] ) PASS http-client ( 0 errors, 0 warnings, features = [metrics] ) PASS http-client ( 0 errors, 0 warnings, features = [metrics, native-tls] ) PASS http-client ( 0 errors, 0 warnings, features = [metrics, rustls] ) PASS http-client ( 0 errors, 0 warnings, features = [native-tls] ) PASS http-client ( 0 errors, 0 warnings, features = [rustls] )
More than one alternative group#
List each disjoint group independently:
[package.metadata.cargo-fc]
mutually_exclusive_features = [
["native-tls", "rustls", "boring"], # TLS backends
["tokio", "async-std"], # async runtimes
]Groups must not overlap. For a non-disjoint constraint such as “not a + b”
and “not b + c,” use the pairwise form:
[package.metadata.cargo-fc]
exclude_feature_sets = [["a", "b"], ["b", "c"]]Only incompatible on some targets#
If alternatives conflict only on one target, add their group there instead of
the base — use add so it extends rather than replaces:
[package.metadata.cargo-fc]
mutually_exclusive_features = [["native-tls", "rustls", "boring"]]
[package.metadata.cargo-fc.target.'cfg(target_os = "windows")']
mutually_exclusive_features = { add = [["metal", "vulkan"]] }