Rust has a useful concept of “features” baked into its packaging tool cargo which allows developers to optionally toggle functionality on and off. In a simple project features are simple, as you would expect. In more complex projects which use cargo workspaces the behavior of features becomes much more complicated and in some cases..surprising!

This morning I was cutting a new release of the deltalake crate and was surprised to find one of our sub-crates wouldn’t publish!

error[E0609]: no field `retry` on type `&StorageConfig`
  --> crates/gcp/src/lib.rs:46:45
   |
46 |         builder = builder.with_retry(config.retry.clone());
   |                                             ^^^^^ unknown field
   |
   = note: available fields are: `runtime`, `limit`, `unknown_properties`, `raw`

Much to my chagrin.

This was a build failure in our main branch and was only discovered when I executed a cargo publish -p deltalake-gcp --dry-run.

We build on every pull request. Heck, we even build with a whole bunch of variations of feature flags! How did this get through?

In a workspace project features on the same dependency will be smooshed together.

Our workspace has multiple sub-crates all pointing to the same dependency on deltalake-core which is in the tree as:

deltalake-core = { path = "../core" }

Some of our crates need features enabled on core such as cloud, some don’t. When a cargo build is executed in the root of the workspace the deltalake-core dependency in the workspace’s dependency tree is smooshed down, carrying whatever features are defined in the workspace dependency definitions along with it.

In this scenario the gcp/Cargo.toml included the deltalake-core dependency without the necessary cloud feature. When building as part of a workspace wide cargo build invocation the features from other crates smooshed together on the common deltalake-core dependency.

When publishing the deltalake-gcp crate on its own, the build failure appeared!

This is a “known issue” with cargo workspaces insofar that I knew of it before this failure and recall seeing a GitHub issue once upon a time. It’s a little confusing for end-users, but kind of makes sense in the context of cargo workspace builds.

Still, it’s always surprising when it pops up!