cargo icon indicating copy to clipboard operation
cargo copied to clipboard

Support inheriting `metadata` from workspace `Cargo.toml`

Open jhpratt opened this issue 2 months ago • 3 comments

Problem

I tried adding this to my workspace Cargo.toml

[workspace.package.metadata.docs.rs]
all-features = true
targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = ["--generate-link-to-definition"]

and inheriting it in a package

[package]
# ...
metadata.docs.rs.workspace = true

This did not work, though to Cargo's credit it does provide a warning!

warning: …/Cargo.toml: unused manifest key: workspace.package.metadata

After searching, I found that metadata is not permitted to be inherited (from the Cargo reference).

Proposed Solution

This should "just work" in the same manner as other inherited fields/tables. While this could conceivably cause issues with third-party metadata, the same could be true for a number of other tables that can already be inherited (such as categories, include, keywords, etc.)

Notes

No response

jhpratt avatar Oct 31 '25 03:10 jhpratt

Currently Cargo sees the entire metadata table opaque. It doesn't know package.metadata.workspace = true means either workspace inheritance or there is really a field workspace = true.

I don't see a backwards compatible way to support this without introducing new inheritance syntax. Especially like docs.rs that is nested and Cargo needs to check every field recursively, which is a bit awkward.

weihanglo avatar Oct 31 '25 03:10 weihanglo

Hm, that's true. The well-known docs.rs bit should still be able to use it, though, no? I can't imagine anyone would expect there to be a package.metadata.docs.rs.workspace key.

jhpratt avatar Oct 31 '25 04:10 jhpratt

In addition to metadata being opaque to us (and changing that is a breaking change), how inheritance functions is also application-specific, including

  • can't override inherited values
  • can only inherit selected values
  • full merging
  • which side gets precedence when merging

docs.rs is an interesting case in that the workspace is no longer available and so it can't be handled on the application side.

epage avatar Oct 31 '25 11:10 epage

We talked about this in today's Cargo team meeting.

The opaqueness of workspace.metadata and package.metadata is a problem but there are potential ways to bypass these

I'm going to move this to S-needs-design to work out the remaining details:

Preserve workspace.metadata on publish

Tools could implement whatever logic they want to read workspace.metadata, allowing for a seamless experience for users.

This would mean that every .crate would be its own workspace. I'm unsure of any negative ramifications of that (since workspaces only have an impact when that is the top-level package).

Sideband information

Add a new field that directs cargo to copy fields over from workspace.metadata to package.metadata on load, ensuring the information is available even in cargo metadata.

This creates a third-way of inheriting within Cargo (field.workspace = true, profiles) rather than allowing tools to imitate cargo's existing forms of inheritance.

This could look something like

[package]
workspace-metadata = [
    ["docs", "rs"],
    ["release"],
]
  • We could support "docs.rs" but then we'd have to have escaping rules for when a . means a . or means a key separator
  • However, this could be confusing translating between the two but at least we could report error messages

Another idea could be

[package.workspace-metadata]
docs.rs = true
release = true

This could even allow for alternative policies in the future (e.g. true meaning "overwrite", merge being an alternative).

We could also leverage the package.workspace field

[package.workspace.metadata]
docs.rs = true
release = true

(with package.workspace being a shorthand for package.workspace.path)

epage avatar Dec 09 '25 16:12 epage