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"]] }

See Per-target configuration.