Skip to content

Latest commit

 

History

History
196 lines (152 loc) · 8.02 KB

3485-feature-documentation.md

File metadata and controls

196 lines (152 loc) · 8.02 KB

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

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

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.

[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

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:

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.

Drawbacks

  • Added complexity to Cargo.
    • Exact implementation details do add test surface area
    • A markdown parser is required to properly parse the doc field.
  • Docstrings can be lengthy, adding noise to Cargo.toml. This could potentially be solved with the below mentioned doc-file key.
  • 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.
  • Unlike with the document-features crate there is no way to group features in into sections or have a user-specified layout
  • Users cannot control features ordering in documentation since the TOML specification defines table keys as unordered.

Rationale and alternatives

  • To avoid increasing the size of the registry index, this does not add doc to a package's index entry. This means a .crate file must be downloaded and extracted to access the features.

  • 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).

    # 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

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 when the challenges of supporting markdown are better understood.

Future possibilities

  • Rustdoc can build on this to show feature documentation.

  • 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.

  • crates-io could be updated to render feature documentation

  • 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.

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