TIL: enabling features on transitive dependencies (Rust)

Saturday, January 6, 2024

While pairing on a small Rust program with a friend, I ran into a problem: to compile to WASM, one of my dependencies needed one of its dependencies to turn on a feature. A variation of this that I've run into in other projects is where a transitive dependency has a bug/CVE and I want to upgrade it. So what do you do if a transitive dependency is giving you grief?

What worked for me

I ended up finding that if you add the package as a direct dependency, you can specify the features and then this will be used transitively as well. So I added the transitive dependency with its feature enabled, and compilation worked.

version = "*"
features = ["js"]

I initially added it with no version specifier so that it would never conflict with the transitive version, and just pick that one. This behavior is deprecated, but we can do it with just specifying * as the version, so all is good.

What I don't love here is that now I have another dependency to keep track of. If my transitive dependency (twice removed) ever removes getrandom, then I'm still stuck with it unless I notice that it's not depended on anymore! It would be a lot nicer to have something where we can specify the features, but fortunately we can lint for unused dependencies using cargo-udeps1.

What didn't work

Here are a few other things I tried that didn't work.

Patching the dependency. I tried using the patch section of my Cargo.toml to specify the version and features that would work for WASM. Unfortunately, I got this error:

`cargo metadata` exited with an error: warning: patch for `getrandom` uses the features mechanism. default-features and features will not take effect because the patch dependency does not support this mechanism

Caused by:
  patch for `getrandom` in `https://github.com/rust-lang/crates.io-index` points to the same source, but patches must point to different sources

So two issues with using patch for this, one is that it just plain doesn't support this mechanism, so it won't work for features. And for version upgrades, no dice either, because you can't patch to a different version in the same registry. I don't get why this is the case, and if I'm missing something, I'd love to update this post to reflect a way to do it here.

Enabling the feature on the direct dependency. The crate I depend on did not actually expect to be compiled to WASM, but does work if this one feature is enabled. So this doesn't work, because it wasn't expected!


Thank you to the Recurser who looked this up and found this crate!

If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts and support my work, subscribe to the newsletter. There is also an RSS feed.

Want to become a better programmer? Join the Recurse Center!
Want to hire great programmers? Hire via Recurse Center!