RFC: Cargo feature descriptions
RFC for feature-documentation
RFC goals: add a way to write feature descriptions in Cargo.toml
This was split from https://github.com/rust-lang/rfcs/pull/3416
[features]
# current configuration
foo = []
# Add a description to the feature
bar = { enables = ["foo"], doc = "simple docstring here"}
# Features can also be full tables if descriptions are longer
[features.qux]
enables = ["bar", "baz"]
doc = """
# qux
This could be a longer description of this feature
"""
This would resolve https://github.com/rust-lang/cargo/issues/4956
@rustbot label +t-cargo
Error: Label t-cargo can only be set by Rust team members
Please file an issue on GitHub at triagebot if there's a problem with this bot, or reach out on #t-infra on Zulip.
@tgross35 thanks for the access. Definitely makes it handy for the more trivial feedback.
Since RFC 3416 is in FCP, that unblocks this feature.
I'm going to go ahead and propose FCP here, and see how close we are to consensus.
Personally, I do think we should use markdown here. Markdown already looks reasonable in plain text, by design, and it gives crates.io and docs.rs and rustdoc something nicer to work with.
@rfcbot merge
Team member @joshtriplett has proposed to merge this. The next step is review by the rest of the tagged team members:
- [x] @Eh2406
- [x] @Muscraft
- [x] @arlosi
- [x] @ehuss
- [x] @epage
- [x] @joshtriplett
- [x] @weihanglo
Concerns:
- cargo-metadata (https://github.com/rust-lang/rfcs/pull/3485#issuecomment-2229243153)
- ~~docs-included-in-design~~ resolved by https://github.com/rust-lang/rfcs/pull/3485#issuecomment-2228610289
- naming (https://github.com/rust-lang/rfcs/pull/3485#issuecomment-2218338583)
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
@rfcbot reviewed
Though I still want to call out that intra-doc links are important https://github.com/rust-lang/rfcs/pull/3416#pullrequestreview-1486325528. CC @GuillaumeGomez if they have any opinion on this.
This is a very good point. Thanks for the ping!
This technically avoids promising work from the rustdoc and docs.rs teams, but that seems like a technicality. The obvious follow-up is for those teams to do something with this information. I have been in adequately following the conversation here. Have they been consulted? Given that none of the technical details have been decided, I don't think their checkboxes should be required, but I also don't want this to be a surprise to them.
@rfcbot concern docs-included-in-design
(Anyone should feel free to resolve this concern if members of those teams have been consulted.)
In the case of docs.rs, it has access to more information so it's not really an issue. The big unknown here is how this information could be given to rustdoc. I suppose through a command-line argument. My only worry about this solution is about the command-line argument size limitation. However, it can be completely nullified by using an @ argument. So I don't see any blocker from rustdoc side either (on how to provide this information).
The big discussion will actually be: how do we display this information in the generated documentation?
This technically avoids promising work from the
rustdocanddocs.rsteams, but that seems like a technicality. The obvious follow-up is for those teams to do something with this information. I have been in adequately following the conversation here. Have they been consulted? Given that none of the technical details have been decided, I don't think their checkboxes should be required, but I also don't want this to be a surprise to them.
I do follow this PR from the sidelines, though not all the discussion on here.
( also, @GuillaumeGomez already said what I wanted to say)
@rfcbot resolve docs-included-in-design
The big discussion will actually be: how do we display this information in the generated documentation?
Tangentially: I hope this information might also become available in rustdoc JSON one day, for the benefit of tools like cargo-semver-checks. It's possible to cause semver breakage by changing crate features, and right now, detecting such breakage requires parsing the Cargo.toml file which can be trickier than it may seem at first.
You can ping me directly if it's not there but it's present in the HTML doc. I'll add it as fast as I can if I forgot. ;)
The big discussion will actually be: how do we display this information in the generated documentation?
and following from there, what happens to the docs.rs view, especially since we also have https://github.com/rust-lang/docs.rs/issues/2530 and https://github.com/rust-lang/docs.rs/issues/2531
In the case of
docs.rs, it has access to more information so it's not really an issue. The big unknown here is how this information could be given torustdoc. I suppose through a command-line argument. My only worry about this solution is about the command-line argument size limitation. However, it can be completely nullified by using an@argument. So I don't see any blocker fromrustdocside either (on how to provide this information).
Does rustdoc already have access to the output of cargo metadata? If so, I think this should eventually wind up there even though I didn't mention it in this RFC (@epage does it seem reasonable to add it?).
I had a draft RFC for a schema to give rustdoc this information if some non-Cargo tool wants to make use of the features display, but would probably need to rework it a ton at this point https://github.com/rust-lang/rfcs/pull/3421
The big discussion will actually be: how do we display this information in the generated documentation?
I preemptively opened a tracking issue for rustdoc support and will put some ideas there (I am sure you have some already too :) ) https://github.com/rust-lang/rust/issues/127771. Also noted JSON support as something to consider from @obi1kenobi's comment.
The big discussion will actually be: how do we display this information in the generated documentation?
and following from there, what happens to the docs.rs view, especially since we also have rust-lang/docs.rs#2530 and rust-lang/docs.rs#2531
I don't know what would happen to the docs.rs view; there doesn't seem to be much harm in keeping it but maybe also not much sense in augmenting it much further if rustdoc will begin to cover it? Those issues could likely be addressed in whatever rustdoc winds up generating here.
In the case of
docs.rs, it has access to more information so it's not really an issue. The big unknown here is how this information could be given torustdoc. I suppose through a command-line argument. My only worry about this solution is about the command-line argument size limitation. However, it can be completely nullified by using an@argument. So I don't see any blocker fromrustdocside either (on how to provide this information).Does
rustdocalready have access to the output ofcargo metadata? If so, I think this should eventually wind up there even though I didn't mention it in this RFC (@epage does it seem reasonable to add it?).
Easy answer: same as rustc (so no as far as I know).
The big discussion will actually be: how do we display this information in the generated documentation?
I preemptively opened a tracking issue for
rustdocsupport and will put some ideas there (I am sure you have some already too :) ) rust-lang/rust#127771. Also noted JSON support as something to consider from @obi1kenobi's comment.
👍
The big discussion will actually be: how do we display this information in the generated documentation?
and following from there, what happens to the docs.rs view, especially since we also have rust-lang/docs.rs#2530 and rust-lang/docs.rs#2531
I don't know what would happen to the
docs.rsview; there doesn't seem to be much harm in keeping it but maybe also not much sense in augmenting it much further ifrustdocwill begin to cover it? Those issues could likely be addressed in whateverrustdocwinds up generating here.
docs.rs and rustdoc are tangent. They can both provide an information in different ways.
I think this should eventually wind up [in cargo metadata] even though I didn't mention it in this RFC (@epage does it seem reasonable to add it?).
So while this isn't relevant for #3421, this is a good point more generally and one we overlooked in #3416. We need to decide if we want to include this in cargo metadata and what that schema would look like. Would we need a parallel structure? Update the format version?
@rfcbot concern cargo-metadata
I think this should eventually wind up [in cargo metadata] even though I didn't mention it in this RFC (@epage does it seem reasonable to add it?).
So while this isn't relevant for #3421, this is a good point more generally and one we overlooked in #3416. We need to decide if we want to include this in
cargo metadataand what that schema would look like. Would we need a parallel structure? Update the format version?@rfcbot concern cargo-metadata
The most elegant schema would be to mirror these tables directly into metadata. That is, update:
"features": {
"foo": ["bar"],
"bar": [],
"baz": []
}
To be something like:
"features": {
"foo": { "enables": ["bar"], "doc": "Enable wxyz" },
// ^ bikeshed still being built
"bar": { "enables": [], "doc": "Make use of ..." },
"baz": { "enables": [] } // < only having one serialization seems easier than allowing
// `"bar": []`, but doesn't matter much
}
However; being that Cargo needs to support all possible schema versions forever (as I understand it), it seems like the barrier for a breaking schema change is quite high. So maybe we should add a new features_metadata object next to features that adds this information in a redundant but backward-compatible way. And then just put replacing features with features_metadata on a "wanted for v2" list for whenever there is enough to justify the new version.
why is this PR still open if the parent is closed?
why is this PR still open if the parent is closed?
The RFC you linked only establishes a format for adding more metadata to features, it doesn't actually confirm that we want to add anything specific. This RFC is about adding documentation as part of metadata, but needs resolution to the two listed concerns.
@epage does https://github.com/rust-lang/rfcs/pull/3485#issuecomment-2229613051 sound reasonable? If so, I will update the RFC.
If accepted here we may want to consider updating https://github.com/rust-lang/rfcs/pull/3416 so that the feature schema isn't provided only in the documentation RFC - obviously up to you to weigh that vs. updating an accepted RFC.
@tgross35
The most elegant schema would be to mirror these tables directly into metadata. That is, update:
<simple form>To be something like:
<detailed form>However; being that Cargo needs to support all possible schema versions forever (as I understand it), it seems like the barrier for a breaking schema change is quite high.
As these details seem to be implicit, you are saying this would be a new --format-version <VERSION>?
Yes, 'wed need to support generating data for all possible schemas for ever.
Pulled in your ideas and added some more. Mind adding this to the RFC alternatives and documenting which you think we should go with and why? We can then discuss it in a cargo team meeting.
A new message format version
We either deprecate the current version, making new features all-or-nothing, or need to add features to both versions
As the format-version is defaulted (with a warning), we'd need to consider what the migration path would be to v2.
A parallel table for just this
This is your features_metadata.
We need to do this for every new field. While #3663 was closed, doing something like that would put coupled data in parallel tables.
A new features2 or features-detailed
Automatically gets new data.
Seems inelegant but that isn't necessarily a blocker.
Use simple form where possible
Technically, this gets us into the territory of "forwards compatibility" rather than "backwards compatibility", ie things break when new features are used with old tools rather than breaking existing features on new tools.
We'd need to make sure we render in the "simple" format whenever we can.
This can still be disruptive to the ecosystem. serde handles adding of new fields well (ignore) but not changing of data types (error). Most people go through cargo_metadata so we'd likely only need to implement things once and then people just need to update.
@rfcbotconcern cargo-metadata
During RustConf 2025 UnConf this RFC has been brought up again.
I wonder whether cargo metadata integration is really a hard blocker.
- Without the integration, tools may need to use
cargo-util-schemasto get the value of feature doc, though that is not too terrible. - Stabilizing the new manifest field itself won't block any future compatibility of
cargo metadadtaschema, as the feature doc field schema is pretty much settled. -
cargo metadataJSON schema is a broader topic than feature description/documentation. If needed, we should break it out to its own issue or RFC.
The cargo_metadata crate could add support for the new layout easily. It could even translate the new layout to old structs (serde has a try_from indirection), so gracefully-degraded support can be added without a semver-major bump, easing update across the ecosystem.
Users parsing JSON directly will be affected only if they parse the features. Projects that only need a subset of the information (like workspace root or package IDs) wouldn't need to define serde structs for features, so they're likely to ignore changes to the features.
So from compatibility perspective, I think Cargo could get away with simply mirroring the features layout from Cargo.toml in the metadata JSON. It's not a bigger deal than changing Cargo.toml itself which also requires tools to update their parsers (I've already made my cargo_toml crate transparently translate the new layout to the old format).
An interesting alternative would be if cargo metadata --format-version=2 only used the new layout, even for crates that use the old one in Cargo.toml. This would make life easier for consumers of the metadata who would need to parse only one layout.
Having both layouts in parallel in the JSON (adding features2 or such) seems least attractive to me. It wouldn't save Cargo the hassle of converting feature layouts for backwards compatibility, but it would add bloat to the JSON. For tools, parsing the metadata is often on the critical path (discovering the workspace to operate on), so smaller JSON is better.
Even if it's convenient now to add a parallel features2 key to the v1 JSON, when v2 happens eventually, I assume Cargo would make it an opportunity to clean up the features layout. So long-term Cargo would end up supporting the two alternative layouts anyway, and taking a shortcut now won't avoid the work long term.
@weihanglo and @kornelski I moved your conversation into a thread in the hopes that it will make it easier to follow
FYI I removed T-rustdoc from this RFC because this is the Cargo portion split out of #3421 which is now just T-rustdoc's side. T-rustdoc's input in this RFC is still important for how viable this is for allowing #3421 but I expect we'll have other clients of this as well, including ourselves. I was just thinking the other day how having the feature descriptions would be nice for cargo's new completions.
Sounds good to me at least, thanks!