Skip to content
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

RFC: Cargo feature descriptions #3485

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Next Next commit
Add initial feature-documentation RFC split from feature-metadata
  • Loading branch information
tgross35 committed Sep 9, 2023
commit 7aa7df076fede453402444f671005b18571b591f
191 changes: 191 additions & 0 deletions text/0000-feature-documentation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
- Feature Name: feature-documentation
- Start Date: 2023-09-09
- RFC PR: [rust-lang/rfcs#3416](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

This RFC describes a new key to under `features` in `Cargo.toml` for
documentation. This will allow Cargo to display this information to the user and
provide a way for `rustdoc` to eventually render this data (how this is rendered
is outside the scope of this RFC).

Please see the parent meta RFC for background information: [`feature-metadata`].

# Motivation

[motivation]: #motivation

Cargo features have become extremely widely used, with many crates having at
least some level of configuration and larger crates winding up with tens of
gates. Desipte being a first class component of crate structure, they suffer
from a documentation problem: users need to maintain documentation separate from
feature definition, typically a manually-created table within API docs.

This RFC proposes adding feature documentation to `Cargo.toml`, which will allow
for keeping feature definitions and documentation together.

# Guide-level explanation

[guide-level-explanation]: #guide-level-explanation

A new `doc` key will be allowed within a feature's table. This key provides a
markdown docstring describing the feature. Like with `#[doc(...)]`, the first
line will be treated as a summary.

```toml
[features]
# Feature without documentation
foo = []

# Short documentation comment
bar = { enables = ["foo"], doc = "simple docstring here"}

# Tables are preferred for longer descriptions
[features.corge]
enables = ["bar", "baz"]
doc = """
# corge

This could be a longer description of this feature
"""
```

See [`feature-metadata`] for information about `enables`.

# Reference-level explanation

[reference-level-explanation]: #reference-level-explanation

The new `doc` key accepts markdown-flavored text, and should be thought of as
the equivalent to a `#[doc(...)]` attribute. Like doc comments, the first line
should be treated as a summary. Intra-doc link support is not included in this
RFC, so they should not be used.

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 such as during `cargo add` or a
possible `cargo info` command. A sample application with `cargo add`:

```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

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.

Any tools that want the information in `doc` will require access to the
manifest. Adding this information to the index was decided against due to
concerns about bloat, but this is further discussed in
[future possibilities][future-possibilities].

# Drawbacks

[drawbacks]: #drawbacks

- Added complexity to Cargo. Parsing is trivial, but exact implementation
details do add test surface area
- Docstrings can be lengthy, adding noise to `Cargo.toml`. This could
potentially be solved with the below mentioned `doc-file` key.
- A markdown parser is required to properly parse the `doc` field.
- When rendering features in documentation, this RFC does not specify any way
for `rustdoc` to get the information it requires. This will require separate
design work.
- There is no way to structure features in a way that they are split into
sections or have a user-specified layout, unlike with the `document-features`
crate.
- Features cannot be ordered since the TOML specification does not allow it.

# Rationale and alternatives

[rationale-and-alternatives]: #rationale-and-alternatives

- Feature descriptions could be specified somewhere in Rust source files. This
has the downside of creating multiple sources of truth on features.
- Cargo could parse doc comments in `Cargo.toml`, like the `document-features`
crate (linked below).

```toml
# RFC proposal
foo = { enables = [], doc = "foo feature" }

# Alternative equivalent using doc comments
## foo feature
foo = []
```

This was decided against as part of this RFC because it would mean that
TOML-compliant parsers (including anything `serde`-based) would be
insufficient to extract all information in the manifest, requiring custom
deserialization of the fields via a format-preserving parser. This differs
from documentation in Rust source as the doc-comment behavior is described
specified within the grammar with parsers supporting extracting those
elements.

# 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. If features
start with `_`, they are hidden from this table.

# Unresolved questions

[unresolved-questions]: #unresolved-questions

- Rather than being consistent with `rustdoc` and accepting markdown, should the
`doc` key be consistent with `package.description` and only support plain
text? This RFC proposes making this decision at time of implementation, the
challenges of supporting markdown are better understood.

# Future possibilities

[future-possibilities]: #future-possibilities

- Rustdoc will gain the ability to document features.
- At some point, the decision to not include `doc` in the index could be
reevaluated. Including only the first (summary) line of `doc` could be a
possibility.
- `cargo add` can show the `doc` and `deprecated` summary with the listed
features.
- [`cargo-info`] can use this information to provide feature descriptions.
- Feature documentation could be allowed in a separate markdown file. For
convenience, markdown anchors could be used to specify a section, so multiple
features can share the same file. This could be a good option for features
requiring long descriptions.

```toml
foo = { enables = [], doc-file = "features.md#foo" }
bar = { enables = [], doc-file = "features.md#bar" }
```

[cargo #12335]: https://github.com/rust-lang/cargo/issues/12235
[cargo #10882]: https://github.com/rust-lang/cargo/issues/10882
[`cargo-info`]: https://github.com/rust-lang/cargo/issues/948
[`deprecated`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated-attribute
[`deprecated-suggestions`]: https://github.com/rust-lang/rust/issues/94785
[discussion on since]: https://github.com/rust-lang/rfcs/pull/3416#discussion_r1172895497
[`public_private_dependencies`]: https://rust-lang.github.io/rfcs/1977-public-private-dependencies.html
[`rustdoc-cargo-configuration`]: https://github.com/rust-lang/rfcs/pull/3421
[`tokio`]: https://docs.rs/crate/tokio/latest/features
[visibility attribute]: https://ant.apache.org/ivy/history/latest-milestone/ivyfile/conf.html
[`feature-metadata`]: https://github.com/rust-lang/rfcs/pull/3416