-
Notifications
You must be signed in to change notification settings - Fork 1.6k
RFC: Unblock Cargo feature metadata #3416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
epage
merged 45 commits into
rust-lang:master
from
tgross35:feature-descriptions-doc-cfg
Jun 27, 2024
Merged
Changes from 14 commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
d58366d
Added feature-descriptions-doc-cfg RFC
tgross35 c9a9874
Update docs.rs link
tgross35 37058e1
Add note about argfile
tgross35 d461faf
Add note about serde
tgross35 65615b2
Add note on build system tools
tgross35 35ca770
Rename json-config -> config-json
tgross35 be9b7c2
Complete all RFC sections
tgross35 a0966ab
Rename feature, update related links
tgross35 c5ab809
Add note about overrides
tgross35 11f696e
Correct toml mistake
tgross35 381afba
Fix links
tgross35 64ce8ca
Clean up clean up everybody everywhere
tgross35 47ad04e
Add note about dependencies
tgross35 6c6ad6d
Split feature-metadata-doc-config into feature-metadata and rustdoc-c…
tgross35 4dd05e3
Initial updates based on review
tgross35 cea7180
Update two from the review round
tgross35 4ab3a6f
Updates round three from review
tgross35 5f48f2d
Updates round four
tgross35 19c3521
Updates round five
tgross35 32174e8
Updates round six
tgross35 cbc31d5
Updates regarding parser
tgross35 97e8301
Clarify markdown status for documentation
tgross35 fff9af1
Add note about optional dev dependencies
tgross35 f1fb220
Remove unstable flag
tgross35 98dbaa1
Add suggestion about rust-version flag
tgross35 8cab2f0
Move deny deprecated features to future possibilities
tgross35 fe7767b
Adjust mentions of 'unstable' to 'stable', refactpr sections
tgross35 b952ce1
Update some links
tgross35 9b2a044
Add notes about public=true default and index changes
tgross35 15a2432
Add note about doc in index
tgross35 88a3447
Add note about naming choice
tgross35 e36b155
Add markdown vs. plaintext as an unresolved question
tgross35 397d47e
Rename 'requires' to 'enables'
tgross35 f3b862b
Update documentation about private feature usage
tgross35 0c1a00f
Update documentation of the 'since' deprecated key
tgross35 8ad6c66
Add another note about the index
tgross35 21b4be2
Rename RFC file
tgross35 a390e5c
Update index comment
tgross35 a0f6b0a
More info about the index
tgross35 b1e9656
Features/2/3 information added
tgross35 244e9a7
Clarify doc comment example
tgross35 fcdb26b
Empty content from this RFC that was moved to one of the others
tgross35 f38d7dc
Capture cargo team meeting notes and clean up
epage 69026e1
Call out impact to third party parsers
epage a8c6163
Add tracking issue
epage File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,275 @@ | ||
- Feature Name: feature-metadata | ||
- Start Date: 2023-04-14 | ||
- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/3416) | ||
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) | ||
|
||
# Summary | ||
|
||
[summary]: #summary | ||
|
||
The main purpose of this RFC is to define a structured way to add attributes to | ||
features, including documentation (mostly for `rustdoc`), visibility, | ||
deprecation status, and stability. | ||
|
||
This RFC only describes a new `Cargo.toml` schema; `rustdoc`'s handling of this | ||
information is in a separate RFC. | ||
|
||
# Motivation | ||
|
||
[motivation]: #motivation | ||
|
||
Features are widely used as a way to do things like reduce dependency count, | ||
gate std or alloc-dependent parts of code, or hide unstable API. Use is so | ||
common that many larger crates wind up with tens of feature gates, such as | ||
[`tokio`] with 24. Despite being a first class component of crate structure, | ||
there are some limitations that don't have elegant solutions: | ||
|
||
- Documentation is difficult, often requiring library authors to manually manage | ||
a table of descriptions | ||
- There is no way to deprecate old features, as a way to help crates maintain | ||
semvar compliance | ||
- Features cannot be hidden from use in any way | ||
|
||
This RFC proposes a plan that add that information to `Cargo.toml`, solving | ||
these problems. | ||
|
||
# Guide-level explanation | ||
|
||
[guide-level-explanation]: #guide-level-explanation | ||
|
||
Usage is simple: features will be able to be specified as a table, instead of | ||
just a dependency array. This sample section of `Cargo.toml` shows new | ||
possibilities: | ||
|
||
```toml | ||
[features] | ||
# Current configuration will continue to work | ||
foo = [] | ||
# New configurations | ||
bar = { requires = ["foo"], doc = "simple docstring here"} | ||
baz = { requires = ["foo"], public = false} | ||
qux = { requires = [], deprecated = true, unstable = true } | ||
quux = { requires = [], deprecated = { since = "1.2.3", note = "don't use this!" } } | ||
|
||
# Features can also be full tables if descriptions are longer | ||
[features.corge] | ||
requires = ["bar", "baz"] | ||
doc = """ | ||
# corge | ||
|
||
This could be a longer description of this feature | ||
""" | ||
``` | ||
|
||
The following keys would be allowed in a feature table: | ||
|
||
- `requires`: This is synonymous with the existing array describing required | ||
features. For example, `foo = ["dep:serde", "otherfeat"]` will be identical to | ||
`foo = { requires = ["dep:serde", "otherfeat"] }` | ||
- `doc`: A markdown docstring describing the feature. Like with `#[doc(...)]`, | ||
the first line will be treated as a summary. | ||
- `deprecated`: This can be either a simple boolean, a string, or an object | ||
with `since` and/or `note` keys. Cargo will warn downstream crates using this | ||
- `public`: A boolean flag defaulting to `true` that indicates whether or not | ||
downstream crates should be allowed to use this feature | ||
- `unstable`: A boolean flag indicating that the feature is only usable with | ||
nightly Rust, or is otherwise not API-stable | ||
|
||
If a downstream crate attempts to use the features `baz` and `qux`, they will | ||
see messages like the following: | ||
|
||
``` | ||
warning: feature `quux` on crate `mycrate` is deprecated since version | ||
1.2.3: "don't use this!" | ||
|
||
error: feature `baz` on crate `mycrate` is private and cannot be used by | ||
downstream crates | ||
``` | ||
|
||
# Reference-level explanation | ||
|
||
[reference-level-explanation]: #reference-level-explanation | ||
|
||
Validation and parsing of the new schema, described above, shoud be relatively | ||
straightforward. Each of the added keys is discussed individually in the | ||
following sections: | ||
|
||
## `requires` | ||
|
||
`requires` will take the place of the feature dependency array that currently | ||
exists. Semantics will remain unchanged. | ||
|
||
## `doc` | ||
|
||
`doc` is the most straightforward: it accepts markdown-flavored text, and should | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
be thought of as the equivalent to a `#[doc(...)]` attribute. Like doc comments, | ||
the first line should be usable as a summary, though most use cases will only | ||
have one line. | ||
|
||
There is nothing in this RFC that cargo `must` do with this action, since it is | ||
mainly intended for the consumption of `rustdoc` or `docs.rs`. However, it can | ||
be used for general diagnostic information. | ||
|
||
## `deprecated` | ||
|
||
`deprecated` should be thought of as the equivalent of the [`deprecated`] | ||
attribute in Rust source. The value can be a boolean, string, or an object with | ||
`since` or `note` keys. Schema rules are as follows: | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
- If a boolean value, `false` indicates not deprecated and `true` indicates | ||
deprecated | ||
- If an object, the keys `since` and/or `note` can be specified | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- An empty object is not allowed to avoid the ambiguous | ||
`foo = { deprecated = {} }` | ||
- A string `foo = { deprecated = "my msg" }` will be equivalent to if that string | ||
was specified in the `note` field: | ||
`foo = { deprecated = { note = "my msg" } }` | ||
- If not specified, the default is `false` | ||
|
||
If a downstream crate attempts to use a feature marked `deprecated`, Cargo | ||
should produce a warning. | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## `public` | ||
|
||
`public` is a boolean value that defaults to `true`. It can be thought of as | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
`pub` in Rust source files, with the exception of being true by default. If set | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
to `false`, Cargo should forbid its use with an error message on any downstream | ||
crates. | ||
epage marked this conversation as resolved.
Show resolved
Hide resolved
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
There needs to be an escape hatch for this for things like benchmarks - RFC TBD | ||
on how this works. | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## `unstable` | ||
|
||
`unstable` is a boolean value that defaults to `false`. It should indicate that | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
a feature gates something that is not API-stable, or can only be built using | ||
`nightly` Rust. | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
--- | ||
|
||
Use cases for this information will likely develop with time, but one of the | ||
simplest applications is for information output with `cargo add`: | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```text | ||
crab@rust foobar % cargo add regex | ||
Updating crates.io index | ||
Adding regex v1.7.3 to dependencies. | ||
Features: | ||
+ perf Enables all performance related features | ||
+ perf-dfa Enables the use of a lazy DFA for matching | ||
+ perf-inline Enables the use of aggressive inlining inside | ||
match routines | ||
+ perf-literal Enables the use of literal optimizations for | ||
speeding up matches | ||
+ std When enabled, this will cause regex to use the | ||
standard library | ||
+ unicode Enables all Unicode features | ||
- unstable (U) Some unstable features | ||
- deprecated (D) Not a real feature, but it could be | ||
|
||
Updating crates.io index | ||
``` | ||
|
||
Features like `aho-corasick`, `memchr`, or `use_std` would likely be `public = | ||
false` since they aren't listed on the crate landing page. | ||
|
||
# Drawbacks | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
[drawbacks]: #drawbacks | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
- Added complexity to Cargo. Parsing is trivial, but exact implementation | ||
details do add test surface area | ||
- Added Cargo arguments if escape hatches for `public` or `unstable` are created | ||
- Docstrings can be lengthy, adding noise to `Cargo.toml`. This could | ||
potentially be solved with the below mentioned `doc-file` key. | ||
- `unstable` and `public` uses may not be common enough to be worth including | ||
|
||
# Rationale and alternatives | ||
|
||
[rationale-and-alternatives]: #rationale-and-alternatives | ||
|
||
- TOML-docstrings (`## Some doc comment`) and attributes that mimic Rust | ||
docstrings could be used instead of a `doc` key. This is discussed in | ||
[future-possibilities], but decided against to start since it is much simpler | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
to parse standard TOML. | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- Feature descriptions could be specified somewhere in Rust source files. This | ||
has the downside of creating multiple sources of truth on features. | ||
|
||
# Prior art | ||
|
||
[prior-art]: #prior-art | ||
|
||
- There is an existing crate that uses TOML comments to create a features table: | ||
<https://docs.rs/document-features/latest/document_features/> | ||
- `docs.rs` displays a feature table, but it is fairly limited | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- Ivy has a [visibility attribute] for its configuration (mentioned in [cargo #10882]) | ||
|
||
# Unresolved questions | ||
|
||
[unresolved-questions]: #unresolved-questions | ||
|
||
- Should `foo = {}` be allowed, or is `foo = { requires = [] }` the minimum if | ||
only using this field? I am leaning toward having it required to avoid | ||
inconsistency like | ||
|
||
```toml | ||
foo = {} | ||
bar = [] | ||
baz = {} | ||
``` | ||
|
||
However, I would also say that `foo = { deprecated = true }` (no `requires` | ||
key) could be valid. | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
- Do we want all the proposed keys? Specifically, `public` and `unstable` may be | ||
more than what is needed. | ||
|
||
See also: | ||
|
||
- <https://github.com/rust-lang/cargo/issues/10882> | ||
- <https://github.com/rust-lang/cargo/issues/10881> | ||
|
||
- If we use the semantics as-written, should there be a | ||
`--allow-private-features` or `--allow-unstable-features` flag? Or how should | ||
a user opt in? | ||
- Does it make sense to have separate `hidden` (not documented) and `public` | ||
(feature not allowed downstream) attribute? I think probably not | ||
- Should there be a way to deny deprecated features? | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
It is worth noting that simpler keys (`requires`, `doc`, `deprecated`) could be | ||
stabilized immediately and other features could be postponed. | ||
|
||
# Future possibilities | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
[future-possibilities]: #future-possibilities | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
- Rustdoc will gain the ability to document features. This is planned in an | ||
associated RFC. | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- One option is to allow giving the feature documentation in a separate file, | ||
allowing a markdown section specifier. This could be a good option for | ||
features requiring long descriptions. | ||
|
||
```toml | ||
foo = { requires = [], doc-file = "features.md#foo" } | ||
bar = { requires = [], doc-file = "features.md#bar" } | ||
``` | ||
|
||
- Cargo could parse doc comments in `Cargo.toml`, like the above linked | ||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
`document-features` crate. This would add complexity to TOML parsing, so it is | ||
not included as part of the initial proposal. | ||
|
||
```toml | ||
[features] | ||
foo = { requires = [], doc = "foo feature" } | ||
## foo feature | ||
foo = [] | ||
``` | ||
|
||
If this is accepted in the future, any doc comments would simply be | ||
concatenated with the `doc` key. | ||
|
||
[`tokio`]: https://docs.rs/crate/tokio/latest/features | ||
[`cargo-info`]: https://github.com/rust-lang/cargo/issues/948 | ||
[visibility attribute]: https://ant.apache.org/ivy/history/latest-milestone/ivyfile/conf.html | ||
[cargo #10882]: https://github.com/rust-lang/cargo/issues/10882 | ||
[`deprecated`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated-attribute |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.