Support inheriting `metadata` from workspace `Cargo.toml`
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
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.
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.
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.
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)