From d58366d18adc06efc53f55445e0eb8f6b01356ce Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 14 Apr 2023 21:19:28 -0400 Subject: [PATCH 01/45] Added feature-descriptions-doc-cfg RFC --- text/0000-feature-descriptions-doc-cfg.md | 202 ++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 text/0000-feature-descriptions-doc-cfg.md diff --git a/text/0000-feature-descriptions-doc-cfg.md b/text/0000-feature-descriptions-doc-cfg.md new file mode 100644 index 00000000000..e009f23dd91 --- /dev/null +++ b/text/0000-feature-descriptions-doc-cfg.md @@ -0,0 +1,202 @@ +- Feature Name: feature-descriptions-doc-cfg +- Start Date: 2023-04-14 +- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) +- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) + +# Summary +[summary]: #summary + +This RFC has three simple goals: + +1. Allow adding descriptions to features in `Cargo.toml` +2. Allow specifying additional `rustdoc` configuration (favicon URL, playground + URL, etc) in either `Cargo.toml` or a new `rustdoc.toml` +3. By combining the two, allow `rustdoc` will be able to document cargo + features, and have room to expand its configuratino options. + +# Motivation +[motivation]: #motivation + +Currently, provides a simple view of available feature flags on a +rather simple page: for example, . +It is helpful as a quick overview of available features, but means that users +must manually maintain a feature table if they want them to be documented +somehow. + +The second problem is that `rustdoc` has some per-crate configuration settings, +such as relevant URLs, that are awkward to define in Rust source files using +attributes. It is expected that there may be further configuration options in +the future. + +This RFC provides a way to solve both problems: it will give `rustdoc` the +ability to document features, and provide room to grow with more configration... + +# Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +Usage is simple: features will be able to be specified in a table (inline or +separate) with the keys `doc`, `public`, and `requires`. Sample `Cargo.toml`: + +```toml +# Cargo.toml + +[features] +# current configuration +foo = [] +# Add a description to the feature +bar = { requires = ["foo"], doc = "simple docstring here"} +# `public` indicates whether or not the feature should be visible in +# documentation, and defaults to true +baz = { requires = ["foo"], public = false } + +# Features can also be full tables if descriptions are longer +[features.qux] +requires = ["bar", "baz"] +doc = """ +# qux + +This could be a longer description of this feature +""" +``` + +This RFC will also enable a `[tools.rustdoc]` table where existing configuration +can be specified + +```toml +# Cargo.toml + +[tools.rustdoc] +html-logo-url = "https://example.com/logo.jpg" +issue-tracker-base-url = "https://github.com/rust-lang/rust/issues/" +``` + +For projects that do not use cargo or want separate configuration, these options +can also be specified in a `rustdoc.toml` file + +```toml +# rustdoc.toml containing the same information as above + +html-logo-url = "https://example.com/logo.jpg" +issue-tracker-base-url = "https://github.com/rust-lang/rust/issues/" + +[features] +# current configuration +foo = [] +# Add a description to the feature +bar = { requires = ["foo"], doc = "simple docstring here"} + +# (baz and qux features clipped) +``` + +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation + +What exactly `rustdoc` does with the information is TBD. There are two options + +## JSON Configuration + +`rustdoc` will gain a `--json-config` argument that allows passing a +JSON-serialized string of the TOML configuration. It is likely that this is what +Cargo can use when it invokes `rustdoc`: all that is needed is to parse the +`features` and `tools.rustdoc` table from `Cargo.toml`, serialize to JSON, and +pass as an argument. + +```sh +rustdoc --argfoo --argbar . --json-config '{"html-logo-url": +"https://example.com/logo.jpg","issue-tracker-base-url": +"https://github.com/rust-lang/rust/issues/","features":{"foo":[],"bar":{"doc": +"simple docstring here","requires":["foo"]},"baz":{"public":false,"requires": +["foo"]},"qux":{"doc":"# qux\n\nThis could be a longer description of this feature\n" +,"requires":["bar","baz"]}}}' +``` + +This sort of format has two distinct advantages: + +1. Build systems other than `cargo` can easily make use of the configuration +2. `rustdoc` does not need to be aware of `cargo`, workspaces, etc. + +- Question: could/should this work from stdin? +- Note: there is a possible precedent to set here that could make it easy for + other tools. `cargo-foobar` could receive the JSON-serialized string of the + `[tools.foobar]` section. + +## Configuration file argument + +`rustdoc` will gain the `--config-file` argument that can point to a +`rustdoc.toml` formatted file. The name `rustdoc.toml` is not required. + +If argument length would be exceeded with the `--json-config` option, `Cargo` +can create a temporary `rustdoc.toml` in the target build folder and point +`rustdoc` to it. + +The arguments `--json-config` and `--config-file` can be specified more than +once, later invocations will just overwrite previous configuration. + +- Question: should rustdoc look for config if it isn't specified? + + +**rest of this RFC todo** + +--- + +# Drawbacks +[drawbacks]: #drawbacks + +Why should we *not* do this? + +- It is work + +# Rationale and alternatives +[rationale-and-alternatives]: #rationale-and-alternatives + +- Why is this design the best in the space of possible designs? +- What other designs have been considered and what is the rationale for not choosing them? +- What is the impact of not doing this? +- If this is a language proposal, could this be done in a library or macro instead? Does the proposed change make Rust code easier or harder to read, understand, and maintain? + +# Prior art +[prior-art]: #prior-art + +Discuss prior art, both the good and the bad, in relation to this proposal. +A few examples of what this can include are: + +- For language, library, cargo, tools, and compiler proposals: Does this feature exist in other programming languages and what experience have their community had? +- For community proposals: Is this done by some other community and what were their experiences with it? +- For other teams: What lessons can we learn from what other communities have done here? +- Papers: Are there any published papers or great posts that discuss this? If you have some relevant papers to refer to, this can serve as a more detailed theoretical background. + +This section is intended to encourage you as an author to think about the lessons from other languages, provide readers of your RFC with a fuller picture. +If there is no prior art, that is fine - your ideas are interesting to us whether they are brand new or if it is an adaptation from other languages. + +Note that while precedent set by other languages is some motivation, it does not on its own motivate an RFC. +Please also take into consideration that rust sometimes intentionally diverges from common language features. + +# Unresolved questions +[unresolved-questions]: #unresolved-questions + +- Anything special for workspaces? + +- What parts of the design do you expect to resolve through the RFC process before this gets merged? +- What parts of the design do you expect to resolve through the implementation of this feature before stabilization? +- What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC? + +# Future possibilities +[future-possibilities]: #future-possibilities + +Think about what the natural extension and evolution of your proposal would +be and how it would affect the language and project as a whole in a holistic +way. Try to use this section as a tool to more fully consider all possible +interactions with the project and language in your proposal. +Also consider how this all fits into the roadmap for the project +and of the relevant sub-team. + +This is also a good place to "dump ideas", if they are out of scope for the +RFC you are writing but otherwise related. + +If you have tried and cannot think of any future possibilities, +you may simply state that you cannot think of anything. + +Note that having something written down in the future-possibilities section +is not a reason to accept the current or a future RFC; such notes should be +in the section on motivation or rationale in this or subsequent RFCs. +The section merely provides additional information. From c9a98744d3e9dd42ff92ea54d3cfd4892cf57530 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 14 Apr 2023 21:23:34 -0400 Subject: [PATCH 02/45] Update docs.rs link --- text/0000-feature-descriptions-doc-cfg.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/text/0000-feature-descriptions-doc-cfg.md b/text/0000-feature-descriptions-doc-cfg.md index e009f23dd91..f2767b39eae 100644 --- a/text/0000-feature-descriptions-doc-cfg.md +++ b/text/0000-feature-descriptions-doc-cfg.md @@ -1,6 +1,6 @@ - Feature Name: feature-descriptions-doc-cfg - Start Date: 2023-04-14 -- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) +- 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 @@ -17,11 +17,11 @@ This RFC has three simple goals: # Motivation [motivation]: #motivation -Currently, provides a simple view of available feature flags on a -rather simple page: for example, . -It is helpful as a quick overview of available features, but means that users -must manually maintain a feature table if they want them to be documented -somehow. +Currently, provides a simple view of available feature flags on +a rather simple page: for example, +. It is helpful as a quick overview +of available features, but means that users must manually maintain a feature +table if they want them to be documented somehow. The second problem is that `rustdoc` has some per-crate configuration settings, such as relevant URLs, that are awkward to define in Rust source files using @@ -118,7 +118,7 @@ This sort of format has two distinct advantages: - Question: could/should this work from stdin? - Note: there is a possible precedent to set here that could make it easy for other tools. `cargo-foobar` could receive the JSON-serialized string of the - `[tools.foobar]` section. + `[tools.foobar]` section. Maybe this would also work for `rustfmt`? ## Configuration file argument From 37058e19c9c7303d63e22fb366a463ba6a565bdc Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 14 Apr 2023 21:26:22 -0400 Subject: [PATCH 03/45] Add note about argfile --- text/0000-feature-descriptions-doc-cfg.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/text/0000-feature-descriptions-doc-cfg.md b/text/0000-feature-descriptions-doc-cfg.md index f2767b39eae..bebb7e06be8 100644 --- a/text/0000-feature-descriptions-doc-cfg.md +++ b/text/0000-feature-descriptions-doc-cfg.md @@ -113,7 +113,10 @@ rustdoc --argfoo --argbar . --json-config '{"html-logo-url": This sort of format has two distinct advantages: 1. Build systems other than `cargo` can easily make use of the configuration -2. `rustdoc` does not need to be aware of `cargo`, workspaces, etc. +2. `rustdoc` does not need to be aware of `cargo`, paths, workspaces, etc. + +Arguments longer than the allowed limit (8000ish on Windows I think) can use +`@argfile`. - Question: could/should this work from stdin? - Note: there is a possible precedent to set here that could make it easy for @@ -125,9 +128,8 @@ This sort of format has two distinct advantages: `rustdoc` will gain the `--config-file` argument that can point to a `rustdoc.toml` formatted file. The name `rustdoc.toml` is not required. -If argument length would be exceeded with the `--json-config` option, `Cargo` -can create a temporary `rustdoc.toml` in the target build folder and point -`rustdoc` to it. +Alternative for long args: `Cargo` could create a temporary `rustdoc.toml` in +the target build folder and point `rustdoc` to it. The arguments `--json-config` and `--config-file` can be specified more than once, later invocations will just overwrite previous configuration. From d461faf1e829514e40c7bc6bd460fedbe303b043 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 14 Apr 2023 21:27:45 -0400 Subject: [PATCH 04/45] Add note about serde --- text/0000-feature-descriptions-doc-cfg.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/text/0000-feature-descriptions-doc-cfg.md b/text/0000-feature-descriptions-doc-cfg.md index bebb7e06be8..7761f202e48 100644 --- a/text/0000-feature-descriptions-doc-cfg.md +++ b/text/0000-feature-descriptions-doc-cfg.md @@ -114,6 +114,8 @@ This sort of format has two distinct advantages: 1. Build systems other than `cargo` can easily make use of the configuration 2. `rustdoc` does not need to be aware of `cargo`, paths, workspaces, etc. +3. `rustdoc` can share the same `serde` structs to parse both `rustdoc.toml` or + this JSON configuration Arguments longer than the allowed limit (8000ish on Windows I think) can use `@argfile`. From 65615b2cdbdaaa66dce010cb8b0baeac96f666c7 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 14 Apr 2023 21:29:27 -0400 Subject: [PATCH 05/45] Add note on build system tools --- text/0000-feature-descriptions-doc-cfg.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/text/0000-feature-descriptions-doc-cfg.md b/text/0000-feature-descriptions-doc-cfg.md index 7761f202e48..be969951443 100644 --- a/text/0000-feature-descriptions-doc-cfg.md +++ b/text/0000-feature-descriptions-doc-cfg.md @@ -112,7 +112,9 @@ rustdoc --argfoo --argbar . --json-config '{"html-logo-url": This sort of format has two distinct advantages: -1. Build systems other than `cargo` can easily make use of the configuration +1. Build systems other than `cargo` can easily make use of the configuration, + and a `rustdoc.toml` file isn't required (e.g. if the build system has a + single configuration file for all tools) 2. `rustdoc` does not need to be aware of `cargo`, paths, workspaces, etc. 3. `rustdoc` can share the same `serde` structs to parse both `rustdoc.toml` or this JSON configuration From 35ca77093c748fa0e6efbd647d1081d0f86cfb31 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 14 Apr 2023 21:45:05 -0400 Subject: [PATCH 06/45] Rename json-config -> config-json --- text/0000-feature-descriptions-doc-cfg.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/0000-feature-descriptions-doc-cfg.md b/text/0000-feature-descriptions-doc-cfg.md index be969951443..34b3dd23510 100644 --- a/text/0000-feature-descriptions-doc-cfg.md +++ b/text/0000-feature-descriptions-doc-cfg.md @@ -95,14 +95,14 @@ What exactly `rustdoc` does with the information is TBD. There are two options ## JSON Configuration -`rustdoc` will gain a `--json-config` argument that allows passing a +`rustdoc` will gain a `--config-json` argument that allows passing a JSON-serialized string of the TOML configuration. It is likely that this is what Cargo can use when it invokes `rustdoc`: all that is needed is to parse the `features` and `tools.rustdoc` table from `Cargo.toml`, serialize to JSON, and pass as an argument. ```sh -rustdoc --argfoo --argbar . --json-config '{"html-logo-url": +rustdoc --argfoo --argbar . --config-json '{"html-logo-url": "https://example.com/logo.jpg","issue-tracker-base-url": "https://github.com/rust-lang/rust/issues/","features":{"foo":[],"bar":{"doc": "simple docstring here","requires":["foo"]},"baz":{"public":false,"requires": @@ -135,7 +135,7 @@ Arguments longer than the allowed limit (8000ish on Windows I think) can use Alternative for long args: `Cargo` could create a temporary `rustdoc.toml` in the target build folder and point `rustdoc` to it. -The arguments `--json-config` and `--config-file` can be specified more than +The arguments `--config-json` and `--config-file` can be specified more than once, later invocations will just overwrite previous configuration. - Question: should rustdoc look for config if it isn't specified? From be9b7c27566cb895571f1b6a687f61e62f554d7c Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 15 Apr 2023 17:02:35 -0400 Subject: [PATCH 07/45] Complete all RFC sections --- text/0000-feature-descriptions-doc-cfg.md | 336 ++++++++++++++-------- 1 file changed, 221 insertions(+), 115 deletions(-) diff --git a/text/0000-feature-descriptions-doc-cfg.md b/text/0000-feature-descriptions-doc-cfg.md index 34b3dd23510..051791abd15 100644 --- a/text/0000-feature-descriptions-doc-cfg.md +++ b/text/0000-feature-descriptions-doc-cfg.md @@ -4,50 +4,66 @@ - Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) # Summary + [summary]: #summary This RFC has three simple goals: -1. Allow adding descriptions to features in `Cargo.toml` -2. Allow specifying additional `rustdoc` configuration (favicon URL, playground - URL, etc) in either `Cargo.toml` or a new `rustdoc.toml` -3. By combining the two, allow `rustdoc` will be able to document cargo - features, and have room to expand its configuratino options. +1. Add a way to write feature descriptions in `Cargo.toml` +2. Establish a way for Cargo or other build systems to easily pass advanced + configuration information to `rustdoc` (e.g., favicon or playground URLs from + `Cargo.toml`) +3. Allow `rustdoc` to accept this information either from the CLI or from a new + `rustdoc.toml` file. + +The outcome is that `rustdoc` will gain the ability to document cargo features +and get its configuration from `Cargo.toml`, without having any awareness of +Cargo project structure itself. There will also be room to grow for more +advanced configuration options. # Motivation + [motivation]: #motivation -Currently, provides a simple view of available feature flags on +Currently, provides a basic view of available feature flags on a rather simple page: for example, . It is helpful as a quick overview -of available features, but means that users must manually maintain a feature -table if they want them to be documented somehow. +of available features, but it is not managed by `rustdoc` (i.e., is not +available on local) and there is no way to specify a description or other useful +information. The second problem is that `rustdoc` has some per-crate configuration settings, such as relevant URLs, that are awkward to define in Rust source files using attributes. It is expected that there may be further configuration options in -the future. +the future, for specifying things like: -This RFC provides a way to solve both problems: it will give `rustdoc` the -ability to document features, and provide room to grow with more configration... +1. Resource manifests (paths to assets, such as `KaTeX` for math rendering) +2. Non-code instructional pages (such as `clap`'s [derive information] + (https://docs.rs/clap/4.2.2/clap/_derive/index.html)) + +This RFC provides a way to solve both problems: it specifies a way to add +user-facing metadata to cargo features, and specifies how that and other +information should be passed to `rustdoc`. # Guide-level explanation + [guide-level-explanation]: #guide-level-explanation Usage is simple: features will be able to be specified in a table (inline or -separate) with the keys `doc`, `public`, and `requires`. Sample `Cargo.toml`: +separate) with the keys `doc`, `public`, `deprecated`, and `requires`. Sample +`Cargo.toml`: ```toml # Cargo.toml [features] -# current configuration +# current configuration will continue to work foo = [] -# Add a description to the feature +# Add a description to the feature. Equivalent to today's `bar = ["foo"]` bar = { requires = ["foo"], doc = "simple docstring here"} -# `public` indicates whether or not the feature should be visible in -# documentation, and defaults to true -baz = { requires = ["foo"], public = false } +# `public` indicates whether or not the feature should be public in +# documentation and usable by downstream users; defaults to `true`. +baz = { requires = ["foo"], public = false, deprecated = true } # Features can also be full tables if descriptions are longer [features.qux] @@ -70,139 +86,229 @@ html-logo-url = "https://example.com/logo.jpg" issue-tracker-base-url = "https://github.com/rust-lang/rust/issues/" ``` -For projects that do not use cargo or want separate configuration, these options -can also be specified in a `rustdoc.toml` file +For projects that do not use Cargo or want separate configuration, these options +can also be specified in a `rustdoc.toml` file using an identical schema ```toml # rustdoc.toml containing the same information as above - +# the only difference is that [tools.rustdoc] has become top level html-logo-url = "https://example.com/logo.jpg" issue-tracker-base-url = "https://github.com/rust-lang/rust/issues/" [features] -# current configuration foo = [] -# Add a description to the feature -bar = { requires = ["foo"], doc = "simple docstring here"} - -# (baz and qux features clipped) +bar = { requires = ["foo"], doc = "simple docstring here" } +# ... ``` # Reference-level explanation -[reference-level-explanation]: #reference-level-explanation -What exactly `rustdoc` does with the information is TBD. There are two options - -## JSON Configuration - -`rustdoc` will gain a `--config-json` argument that allows passing a -JSON-serialized string of the TOML configuration. It is likely that this is what -Cargo can use when it invokes `rustdoc`: all that is needed is to parse the -`features` and `tools.rustdoc` table from `Cargo.toml`, serialize to JSON, and -pass as an argument. +[reference-level-explanation]: #reference-level-explanation -```sh -rustdoc --argfoo --argbar . --config-json '{"html-logo-url": -"https://example.com/logo.jpg","issue-tracker-base-url": -"https://github.com/rust-lang/rust/issues/","features":{"foo":[],"bar":{"doc": -"simple docstring here","requires":["foo"]},"baz":{"public":false,"requires": -["foo"]},"qux":{"doc":"# qux\n\nThis could be a longer description of this feature\n" -,"requires":["bar","baz"]}}}' +At a high level, the following changes will be necessary + +1. Cargo will change its parsing to accept the new format for `features` +2. `rustdoc` will gain two optional arguments: `--config-file` (for specifying + `rustdoc.toml`-style files), and `--config-json` (for specifying the same + information via JSON text, or a path to a JSON file). These arguments can be + specified more than once +3. Cargo will naively serialize some information from `Cargo.toml` to pass to + `rustdoc`, and make `rustdoc` aware of any `rustdoc.toml` files. +4. `rustdoc` will parse each of the `--config-*` arguments to create its + internal configuration. + +This is described in more detail in the following sections. + +## Changes to Cargo + +Cargo will need to parse the new format for `[features]`. For its internal use, it +can discard all new information. + +The `cargo doc` invocation will need to do two new things: + +1. Reserialize the `[features]` and `[tools.rustdoc]` tables from any + `Cargo.toml` file to JSON. This can be naive, i.e., Cargo does not need to + validate the contained information in any way. +2. Pass this information as a string via `--config-json`. If string length + exceeds a limit (e.g., 2000 characters), write this configuration instead to + a temporary build JSON file. (this also helps to avoid maximum argument + length restrictions). +3. Find any `rustdoc.toml` files and pass their paths to `rustdoc` using + `--config-toml` + +Cargo should use the following precedence (later items take priority over +earlier items): + +1. Workspace `Cargo.toml` +2. Workspace root `rustdoc.toml` +3. Crate `Cargo.toml` +4. Crate root `rustdoc.toml` + +## Changes to `rustdoc` + +`rustdoc` must be aware of two new arguments: `--config-json` and +`--config-file`. `--config-json` accepts either a JSON file path or a JSON +string, `--config-file` accepts a path to a TOML file. The JSON and TOML +share an identical schema: + +```json5 +{ + "html-logo-url": "https://example.com/logo.jpg", + "issue-tracker-base-url": "https://github.com/rust-lang/rust/issues/", + features: { + foo: [], + bar: { doc: "simple docstring here", requires: ["foo"] }, + baz: { public: false, requires: ["bar"] }, + qux: { + doc: "# corge\n\nThis could be a longer description of this feature\n", + requires: ["bar", "baz"], + }, + }, +} ``` -This sort of format has two distinct advantages: - -1. Build systems other than `cargo` can easily make use of the configuration, - and a `rustdoc.toml` file isn't required (e.g. if the build system has a - single configuration file for all tools) -2. `rustdoc` does not need to be aware of `cargo`, paths, workspaces, etc. -3. `rustdoc` can share the same `serde` structs to parse both `rustdoc.toml` or - this JSON configuration - -Arguments longer than the allowed limit (8000ish on Windows I think) can use -`@argfile`. - -- Question: could/should this work from stdin? -- Note: there is a possible precedent to set here that could make it easy for - other tools. `cargo-foobar` could receive the JSON-serialized string of the - `[tools.foobar]` section. Maybe this would also work for `rustfmt`? - -## Configuration file argument - -`rustdoc` will gain the `--config-file` argument that can point to a -`rustdoc.toml` formatted file. The name `rustdoc.toml` is not required. - -Alternative for long args: `Cargo` could create a temporary `rustdoc.toml` in -the target build folder and point `rustdoc` to it. - -The arguments `--config-json` and `--config-file` can be specified more than -once, later invocations will just overwrite previous configuration. - -- Question: should rustdoc look for config if it isn't specified? - - -**rest of this RFC todo** +Spans can also be specified for JSON files for better diagnostics. It is +expected that Cargo could maintain span information for data extracted from +`Cargo.toml`, but it is not required that other build systems or handwritten +configurationĀ provide this information. This is also not required for a minimum +viable product. + +```json5 +{ + "_root-span-path": "/path/to/Cargo.TOML", + "html-logo-url": { + data: "https://example.com/logo.jpg", + start: 100, + end: 123, + }, + features: { + data: { + foo: { data: [], start: 10, end: 15 }, + bar: { + data: { + doc: { data: "simple docstring here", start: 15, end: 20 }, + requires: { data: ["foo"], start: 20, end: 25 }, + }, + start: 15, + end: 30, + }, + }, + start: 10, + end: 100, + }, +} +``` ---- +`rustdoc` should start with a default configuration and update/overwrite it with +each `--config-file` or `--config-json` argument. Configuration specified in +rust source files (e.g. `#![doc(html_favicon_url ="foo.com/favicon")]`) take the +highest priority. # Drawbacks -[drawbacks]: #drawbacks -Why should we *not* do this? +[drawbacks]: #drawbacks -- It is work +- This adds complexity to `rustdoc`. In this case, it does seem like it is + justified. +- This adds noise to the Cargo manifest that is not relevant to Cargo itself. + This RFC seeks to provide a good middle ground: overly complex configuration + or feature descriptions can exist in a separate `rustdoc.toml`, but a separate + file also isn't required for simple configuration. +- If a user chooses to maintain feature descriptions in `rustdoc.toml` instead + of `Cargo.toml`, it does add multiple sources of truth for feature data. # Rationale and alternatives + [rationale-and-alternatives]: #rationale-and-alternatives -- Why is this design the best in the space of possible designs? -- What other designs have been considered and what is the rationale for not choosing them? -- What is the impact of not doing this? -- If this is a language proposal, could this be done in a library or macro instead? Does the proposed change make Rust code easier or harder to read, understand, and maintain? +- `rustdoc` could accept something like `--cargo-config Cargo.toml` and parse + the `Cargo.toml` itself. This is still possible, but there are a couple + reasons to prefer this RFC's suggestions: + - Cargo will have the discretion for what exactly data to send. For example, + `cargo doc --no-default-features` could strip all features that aren't + default + - Documentation systems other than Cargo maintain flexibility. For example, + `doxygen` could invoke `rustdoc` and pass a favicon URL that doesn't need to + come from `rustdoc.toml` or `Cargo.toml`. + - Reserializing relevant sections of `Cargo.toml` is easy for Cargo to do, as + it doesn't have to validate anything. +- JSON configuration could be skipped entirely, only using TOML. This RFC + proposes JSON because: + - It is easier to make CLI-safe than TOML + - TOML->JSON serialization is trivial. `rustdoc` can also easily handle both + schemas using the same serde structures. + - Build systems other than Cargo can make use of it easier: plenty of tools + are available to serialize JSON, but serializing TOML is less common (e.g. + Python's `tomllib` can parse TOML but not recreate it) +- No information could be provided in `Cargo.toml`, only allowing + `rustdoc.toml`. For features, keeping descriptions in `Cargo.toml` is + preferable because it provides a single source of truth for all things feature + related, rather than requiring that a user maintain two separate files (which + is more or less the current status quo). +- Feature descriptions could be specified somewhere in Rust source files. Like + the above, this has the downside of having multiple sources of truth on + features. # Prior art -[prior-art]: #prior-art -Discuss prior art, both the good and the bad, in relation to this proposal. -A few examples of what this can include are: - -- For language, library, cargo, tools, and compiler proposals: Does this feature exist in other programming languages and what experience have their community had? -- For community proposals: Is this done by some other community and what were their experiences with it? -- For other teams: What lessons can we learn from what other communities have done here? -- Papers: Are there any published papers or great posts that discuss this? If you have some relevant papers to refer to, this can serve as a more detailed theoretical background. - -This section is intended to encourage you as an author to think about the lessons from other languages, provide readers of your RFC with a fuller picture. -If there is no prior art, that is fine - your ideas are interesting to us whether they are brand new or if it is an adaptation from other languages. +[prior-art]: #prior-art -Note that while precedent set by other languages is some motivation, it does not on its own motivate an RFC. -Please also take into consideration that rust sometimes intentionally diverges from common language features. +- There is an existing crate that uses TOML comments to create a features table: + +- `docs.rs` displays a feature table, but it is fairly limited # Unresolved questions + [unresolved-questions]: #unresolved-questions -- Anything special for workspaces? +Implementation blocking: -- What parts of the design do you expect to resolve through the RFC process before this gets merged? -- What parts of the design do you expect to resolve through the implementation of this feature before stabilization? -- What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC? +- Should `cargo` use the `public` flag to disallow downstream crates from using + features (for e.g., functions that provide unstable features or benchmark-only + functions). Must be adopted as the same time as parsing, as enabling this + later would break compatibility. +- If the answer to the above is "yes", does it make sense to have separate + `hidden` (not documented) and `public` flags (not allowed downstream) flags? -# Future possibilities -[future-possibilities]: #future-possibilities +Nonblocking: -Think about what the natural extension and evolution of your proposal would -be and how it would affect the language and project as a whole in a holistic -way. Try to use this section as a tool to more fully consider all possible -interactions with the project and language in your proposal. -Also consider how this all fits into the roadmap for the project -and of the relevant sub-team. +- How exactly will `rustdoc` present the feature information? A new section on + the module's top-level could be reasonable. +- Should `rustdoc` allow a header/overview for the features section? This can be + done in the future with e.g. a `tools.rustdoc.features-doc` key in TOML. -This is also a good place to "dump ideas", if they are out of scope for the -RFC you are writing but otherwise related. +# Future possibilities -If you have tried and cannot think of any future possibilities, -you may simply state that you cannot think of anything. +[future-possibilities]: #future-possibilities -Note that having something written down in the future-possibilities section -is not a reason to accept the current or a future RFC; such notes should be -in the section on motivation or rationale in this or subsequent RFCs. -The section merely provides additional information. +- Cargo could parse doc comments in `Cargo.toml`, like the above linked + `document-features` crate. This adds some complexity to TOML parsing, but + `rustdoc` would not need to do anything different as long as a parser could + make the two below examples equivalent: + + ```toml + [features] + foo = { requires = [], doc = "foo feature" } + ## foo feature + foo = [] + ``` +- The `deprecated` flag would allow Cargo to warn downstream crates using the + feature +- `[tools.rustdoc]` can grow to hold a resources manifest. For example: + ```toml + [tools.rustdoc] + # cargo would likely have to canonicalize this path + resource-root: "../static" + + [resources] + # .rs files can refer to this asset as "intro-video", located at "../static/sample.mp4" + intro-video = "sample.mp4" + header-include = ["js/katex.js", "js/render-output-graphs.js", "mytheme.css"] + ``` +- This could set a precedent for tools receiving information from `Cargo.toml`. + For example, the tool `cargo-foo-all-bars` could have a `[tools.foo-all-bars]` + table in `Cargo.toml`. Upon `cargo foo-all-bars` invocation, Cargo could pass + the contents of this tools table. + + The ideas in this RFC could also eventually allow `[tools.clippy]`and + `[tools.rustfmt]` tables to simplify configuration for other builtin tools. From a0966abf86ae28b40ff1ef1fe17d15acbf09e1f1 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 15 Apr 2023 17:12:38 -0400 Subject: [PATCH 08/45] Rename feature, update related links --- ...fg.md => 0000-feature-metadata-doc-cfg.md} | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) rename text/{0000-feature-descriptions-doc-cfg.md => 0000-feature-metadata-doc-cfg.md} (91%) diff --git a/text/0000-feature-descriptions-doc-cfg.md b/text/0000-feature-metadata-doc-cfg.md similarity index 91% rename from text/0000-feature-descriptions-doc-cfg.md rename to text/0000-feature-metadata-doc-cfg.md index 051791abd15..66280656f5e 100644 --- a/text/0000-feature-descriptions-doc-cfg.md +++ b/text/0000-feature-metadata-doc-cfg.md @@ -1,4 +1,4 @@ -- Feature Name: feature-descriptions-doc-cfg +- Feature Name: feature-metadata-doc-cfg - 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) @@ -9,7 +9,8 @@ This RFC has three simple goals: -1. Add a way to write feature descriptions in `Cargo.toml` +1. Add a way to write feature descriptions in `Cargo.toml`, as well some other + simple feature attributes. 2. Establish a way for Cargo or other build systems to easily pass advanced configuration information to `rustdoc` (e.g., favicon or playground URLs from `Cargo.toml`) @@ -256,6 +257,10 @@ highest priority. - There is an existing crate that uses TOML comments to create a features table: - `docs.rs` displays a feature table, but it is fairly limited +- Ivy has a [visibility attribute] for its configuration (mentioned in [cargo #10882]) + +[visibility attribute]: https://ant.apache.org/ivy/history/latest-milestone/ivyfile/conf.html +[cargo #10882]: https://github.com/rust-lang/cargo/issues/10882 # Unresolved questions @@ -263,12 +268,14 @@ highest priority. Implementation blocking: -- Should `cargo` use the `public` flag to disallow downstream crates from using - features (for e.g., functions that provide unstable features or benchmark-only - functions). Must be adopted as the same time as parsing, as enabling this - later would break compatibility. +- Should `cargo` use the `public` attribute to disallow downstream crates from + using features (for e.g., functions that provide unstable features or + benchmark-only functions). Must be adopted as the same time as parsing, as + enabling this later would break compatibility. See also: + - If the answer to the above is "yes", does it make sense to have separate - `hidden` (not documented) and `public` flags (not allowed downstream) flags? + `hidden` (not documented) and `public` attribute (not allowed downstream) + attribute? Nonblocking: @@ -292,8 +299,11 @@ Nonblocking: ## foo feature foo = [] ``` -- The `deprecated` flag would allow Cargo to warn downstream crates using the - feature +- The `deprecated` attribute would allow Cargo to warn downstream crates using + the feature +- `unstable` or `nightly` attributes for features could provide further + informations or restriction on use (see + ) - `[tools.rustdoc]` can grow to hold a resources manifest. For example: ```toml [tools.rustdoc] From c5ab8095229427d79610476fd6568a537091f8ef Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 15 Apr 2023 17:19:22 -0400 Subject: [PATCH 09/45] Add note about overrides --- text/0000-feature-metadata-doc-cfg.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/text/0000-feature-metadata-doc-cfg.md b/text/0000-feature-metadata-doc-cfg.md index 66280656f5e..db238deba3c 100644 --- a/text/0000-feature-metadata-doc-cfg.md +++ b/text/0000-feature-metadata-doc-cfg.md @@ -145,6 +145,10 @@ earlier items): 3. Crate `Cargo.toml` 4. Crate root `rustdoc.toml` +`rustdoc` will be in charge of handling configuration merging. This should +create an intuitive layering of global options and overrides while keeping +`rustdoc` and `Cargo` reasonably separate. + ## Changes to `rustdoc` `rustdoc` must be aware of two new arguments: `--config-json` and From 11f696e835ac5bb1cf69690307b3e237400ffd83 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 15 Apr 2023 17:27:01 -0400 Subject: [PATCH 10/45] Correct toml mistake --- text/0000-feature-metadata-doc-cfg.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-feature-metadata-doc-cfg.md b/text/0000-feature-metadata-doc-cfg.md index db238deba3c..e71fdaec8cc 100644 --- a/text/0000-feature-metadata-doc-cfg.md +++ b/text/0000-feature-metadata-doc-cfg.md @@ -312,7 +312,7 @@ Nonblocking: ```toml [tools.rustdoc] # cargo would likely have to canonicalize this path - resource-root: "../static" + resource-root = "../static" [resources] # .rs files can refer to this asset as "intro-video", located at "../static/sample.mp4" From 381afba820090a6633c27b22f825f3b333f341af Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 15 Apr 2023 17:31:26 -0400 Subject: [PATCH 11/45] Fix links --- text/0000-feature-metadata-doc-cfg.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/text/0000-feature-metadata-doc-cfg.md b/text/0000-feature-metadata-doc-cfg.md index e71fdaec8cc..160818fbc70 100644 --- a/text/0000-feature-metadata-doc-cfg.md +++ b/text/0000-feature-metadata-doc-cfg.md @@ -27,8 +27,7 @@ advanced configuration options. [motivation]: #motivation Currently, provides a basic view of available feature flags on -a rather simple page: for example, -. It is helpful as a quick overview +a rather simple page: for example, [`tokio`]. It is helpful as a quick overview of available features, but it is not managed by `rustdoc` (i.e., is not available on local) and there is no way to specify a description or other useful information. @@ -39,13 +38,15 @@ attributes. It is expected that there may be further configuration options in the future, for specifying things like: 1. Resource manifests (paths to assets, such as `KaTeX` for math rendering) -2. Non-code instructional pages (such as `clap`'s [derive information] - (https://docs.rs/clap/4.2.2/clap/_derive/index.html)) +2. Non-code instructional pages (such as [`clap`'s derive information]) This RFC provides a way to solve both problems: it specifies a way to add user-facing metadata to cargo features, and specifies how that and other information should be passed to `rustdoc`. +[`tokio`]: https://docs.rs/crate/tokio/latest/features +[`clap`'s derive information]: https://docs.rs/clap/4.2.2/clap/_derive/index.html + # Guide-level explanation [guide-level-explanation]: #guide-level-explanation From 64ce8ca994f7b647b8145d4ff91c2a2217c0307a Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 15 Apr 2023 17:43:57 -0400 Subject: [PATCH 12/45] Clean up clean up everybody everywhere --- text/0000-feature-metadata-doc-cfg.md | 102 +++++++++++++------------- 1 file changed, 52 insertions(+), 50 deletions(-) diff --git a/text/0000-feature-metadata-doc-cfg.md b/text/0000-feature-metadata-doc-cfg.md index 160818fbc70..c4e2c964d67 100644 --- a/text/0000-feature-metadata-doc-cfg.md +++ b/text/0000-feature-metadata-doc-cfg.md @@ -26,10 +26,10 @@ advanced configuration options. [motivation]: #motivation -Currently, provides a basic view of available feature flags on -a rather simple page: for example, [`tokio`]. It is helpful as a quick overview -of available features, but it is not managed by `rustdoc` (i.e., is not -available on local) and there is no way to specify a description or other useful +Currently, `docs.rs` provides a basic view of available feature flags on a +rather simple page: for example, [`tokio`]. It is helpful as a quick overview of +available features, but it is not managed by `rustdoc` (i.e., is not available +on local) and there is no way to specify a description or other useful information. The second problem is that `rustdoc` has some per-crate configuration settings, @@ -37,8 +37,9 @@ such as relevant URLs, that are awkward to define in Rust source files using attributes. It is expected that there may be further configuration options in the future, for specifying things like: -1. Resource manifests (paths to assets, such as `KaTeX` for math rendering) -2. Non-code instructional pages (such as [`clap`'s derive information]) +1. Resource manifests (paths to assets, such as `KaTeX` for math rendering or + non-image files) +2. Non-code informational pages (such as [`clap`'s derive information]) This RFC provides a way to solve both problems: it specifies a way to add user-facing metadata to cargo features, and specifies how that and other @@ -77,8 +78,8 @@ This could be a longer description of this feature """ ``` -This RFC will also enable a `[tools.rustdoc]` table where existing configuration -can be specified +This RFC will also allow a `[tools.rustdoc]` table where existing configuration +can be specified: ```toml # Cargo.toml @@ -89,7 +90,7 @@ issue-tracker-base-url = "https://github.com/rust-lang/rust/issues/" ``` For projects that do not use Cargo or want separate configuration, these options -can also be specified in a `rustdoc.toml` file using an identical schema +can also be specified in a `rustdoc.toml` file using an identical schema: ```toml # rustdoc.toml containing the same information as above @@ -107,9 +108,9 @@ bar = { requires = ["foo"], doc = "simple docstring here" } [reference-level-explanation]: #reference-level-explanation -At a high level, the following changes will be necessary +At a high level, the following changes will be necessary: -1. Cargo will change its parsing to accept the new format for `features` +1. Cargo will change its parsing to accept the new format for `[features]` 2. `rustdoc` will gain two optional arguments: `--config-file` (for specifying `rustdoc.toml`-style files), and `--config-json` (for specifying the same information via JSON text, or a path to a JSON file). These arguments can be @@ -123,8 +124,8 @@ This is described in more detail in the following sections. ## Changes to Cargo -Cargo will need to parse the new format for `[features]`. For its internal use, it -can discard all new information. +Cargo will need to parse the new format for `[features]`. For its non-rustdoc +use, it can discard all new information. The `cargo doc` invocation will need to do two new things: @@ -133,10 +134,10 @@ The `cargo doc` invocation will need to do two new things: validate the contained information in any way. 2. Pass this information as a string via `--config-json`. If string length exceeds a limit (e.g., 2000 characters), write this configuration instead to - a temporary build JSON file. (this also helps to avoid maximum argument - length restrictions). -3. Find any `rustdoc.toml` files and pass their paths to `rustdoc` using - `--config-toml` + a temporary build JSON file. (to avoid maximum argument length restrictions + and keep verbose output concise). +3. Find files named `rustdoc.toml` and pass their paths to `rustdoc` using + `--config-toml`; no parsing of these files is necessary. Cargo should use the following precedence (later items take priority over earlier items): @@ -155,21 +156,21 @@ create an intuitive layering of global options and overrides while keeping `rustdoc` must be aware of two new arguments: `--config-json` and `--config-file`. `--config-json` accepts either a JSON file path or a JSON string, `--config-file` accepts a path to a TOML file. The JSON and TOML -share an identical schema: +share an identical schema to what is shown above: ```json5 { "html-logo-url": "https://example.com/logo.jpg", "issue-tracker-base-url": "https://github.com/rust-lang/rust/issues/", - features: { - foo: [], - bar: { doc: "simple docstring here", requires: ["foo"] }, - baz: { public: false, requires: ["bar"] }, - qux: { - doc: "# corge\n\nThis could be a longer description of this feature\n", - requires: ["bar", "baz"], - }, - }, + "features": { + "foo": [], + "bar": { "doc": "simple docstring here", "requires": ["foo"] }, + "baz": { "public": false, "requires": ["bar"] }, + "qux": { + "doc": "# corge\n\nThis could be a longer description of this feature\n", + "requires": ["bar", "baz"] + } + } } ``` @@ -181,27 +182,28 @@ viable product. ```json5 { + // Indicate the source file that spans are based on "_root-span-path": "/path/to/Cargo.TOML", "html-logo-url": { - data: "https://example.com/logo.jpg", - start: 100, - end: 123, + "data": "https://example.com/logo.jpg", + "start": 100, + "end": 123 }, - features: { - data: { - foo: { data: [], start: 10, end: 15 }, - bar: { - data: { - doc: { data: "simple docstring here", start: 15, end: 20 }, - requires: { data: ["foo"], start: 20, end: 25 }, + "features": { + "data": { + "foo": { "data": [], "start": 10, "end": 15 }, + "bar": { + "data": { + "doc": { "data": "simple docstring here", "start": 15, "end": 20 }, + "requires": { "data": ["foo"], "start": 20, "end": 25 } }, - start: 15, - end: 30, - }, + "start": 15, + "end": 30 + } }, - start: 10, - end: 100, - }, + "start": 10, + "end": 100 + } } ``` @@ -217,9 +219,9 @@ highest priority. - This adds complexity to `rustdoc`. In this case, it does seem like it is justified. - This adds noise to the Cargo manifest that is not relevant to Cargo itself. - This RFC seeks to provide a good middle ground: overly complex configuration - or feature descriptions can exist in a separate `rustdoc.toml`, but a separate - file also isn't required for simple configuration. + This RFC seeks to provide a good middle ground: lengthy or complex + configuration or feature descriptions can exist in a separate `rustdoc.toml`, + but a separate file also isn't required for simple configuration. - If a user chooses to maintain feature descriptions in `rustdoc.toml` instead of `Cargo.toml`, it does add multiple sources of truth for feature data. @@ -228,11 +230,11 @@ highest priority. [rationale-and-alternatives]: #rationale-and-alternatives - `rustdoc` could accept something like `--cargo-config Cargo.toml` and parse - the `Cargo.toml` itself. This is still possible, but there are a couple - reasons to prefer this RFC's suggestions: + the `Cargo.toml` itself. This is possible, but there are a couple reasons to + prefer this RFC's suggestions: - Cargo will have the discretion for what exactly data to send. For example, `cargo doc --no-default-features` could strip all features that aren't - default + default, without `rustdoc` needing to be aware of the argument. - Documentation systems other than Cargo maintain flexibility. For example, `doxygen` could invoke `rustdoc` and pass a favicon URL that doesn't need to come from `rustdoc.toml` or `Cargo.toml`. @@ -326,4 +328,4 @@ Nonblocking: the contents of this tools table. The ideas in this RFC could also eventually allow `[tools.clippy]`and - `[tools.rustfmt]` tables to simplify configuration for other builtin tools. + `[tools.rustfmt]` tables to simplify configuration of those tools. From 47ad04e61621b954505309147ef995392018d694 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 16 Apr 2023 04:23:19 -0400 Subject: [PATCH 13/45] Add note about dependencies --- text/0000-feature-metadata-doc-cfg.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/text/0000-feature-metadata-doc-cfg.md b/text/0000-feature-metadata-doc-cfg.md index c4e2c964d67..5c094d3d3cf 100644 --- a/text/0000-feature-metadata-doc-cfg.md +++ b/text/0000-feature-metadata-doc-cfg.md @@ -290,6 +290,9 @@ Nonblocking: the module's top-level could be reasonable. - Should `rustdoc` allow a header/overview for the features section? This can be done in the future with e.g. a `tools.rustdoc.features-doc` key in TOML. +- Should Cargo also send the contents of the `[dependencies]` table or other + information? This could be used to give `rustdoc` a dependencies viewer, like + `docs.rs` currently displays in the top bar. # Future possibilities From 6c6ad6d31b4b8bb33daa32fd4c54918eb9413c21 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 20 Apr 2023 05:11:29 -0400 Subject: [PATCH 14/45] Split feature-metadata-doc-config into feature-metadata and rustdoc-cargo-configuration RFCs --- text/0000-feature-metadata-doc-cfg.md | 334 -------------------------- text/0000-feature-metadata.md | 275 +++++++++++++++++++++ 2 files changed, 275 insertions(+), 334 deletions(-) delete mode 100644 text/0000-feature-metadata-doc-cfg.md create mode 100644 text/0000-feature-metadata.md diff --git a/text/0000-feature-metadata-doc-cfg.md b/text/0000-feature-metadata-doc-cfg.md deleted file mode 100644 index 5c094d3d3cf..00000000000 --- a/text/0000-feature-metadata-doc-cfg.md +++ /dev/null @@ -1,334 +0,0 @@ -- Feature Name: feature-metadata-doc-cfg -- 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 - -This RFC has three simple goals: - -1. Add a way to write feature descriptions in `Cargo.toml`, as well some other - simple feature attributes. -2. Establish a way for Cargo or other build systems to easily pass advanced - configuration information to `rustdoc` (e.g., favicon or playground URLs from - `Cargo.toml`) -3. Allow `rustdoc` to accept this information either from the CLI or from a new - `rustdoc.toml` file. - -The outcome is that `rustdoc` will gain the ability to document cargo features -and get its configuration from `Cargo.toml`, without having any awareness of -Cargo project structure itself. There will also be room to grow for more -advanced configuration options. - -# Motivation - -[motivation]: #motivation - -Currently, `docs.rs` provides a basic view of available feature flags on a -rather simple page: for example, [`tokio`]. It is helpful as a quick overview of -available features, but it is not managed by `rustdoc` (i.e., is not available -on local) and there is no way to specify a description or other useful -information. - -The second problem is that `rustdoc` has some per-crate configuration settings, -such as relevant URLs, that are awkward to define in Rust source files using -attributes. It is expected that there may be further configuration options in -the future, for specifying things like: - -1. Resource manifests (paths to assets, such as `KaTeX` for math rendering or - non-image files) -2. Non-code informational pages (such as [`clap`'s derive information]) - -This RFC provides a way to solve both problems: it specifies a way to add -user-facing metadata to cargo features, and specifies how that and other -information should be passed to `rustdoc`. - -[`tokio`]: https://docs.rs/crate/tokio/latest/features -[`clap`'s derive information]: https://docs.rs/clap/4.2.2/clap/_derive/index.html - -# Guide-level explanation - -[guide-level-explanation]: #guide-level-explanation - -Usage is simple: features will be able to be specified in a table (inline or -separate) with the keys `doc`, `public`, `deprecated`, and `requires`. Sample -`Cargo.toml`: - -```toml -# Cargo.toml - -[features] -# current configuration will continue to work -foo = [] -# Add a description to the feature. Equivalent to today's `bar = ["foo"]` -bar = { requires = ["foo"], doc = "simple docstring here"} -# `public` indicates whether or not the feature should be public in -# documentation and usable by downstream users; defaults to `true`. -baz = { requires = ["foo"], public = false, deprecated = true } - -# Features can also be full tables if descriptions are longer -[features.qux] -requires = ["bar", "baz"] -doc = """ -# qux - -This could be a longer description of this feature -""" -``` - -This RFC will also allow a `[tools.rustdoc]` table where existing configuration -can be specified: - -```toml -# Cargo.toml - -[tools.rustdoc] -html-logo-url = "https://example.com/logo.jpg" -issue-tracker-base-url = "https://github.com/rust-lang/rust/issues/" -``` - -For projects that do not use Cargo or want separate configuration, these options -can also be specified in a `rustdoc.toml` file using an identical schema: - -```toml -# rustdoc.toml containing the same information as above -# the only difference is that [tools.rustdoc] has become top level -html-logo-url = "https://example.com/logo.jpg" -issue-tracker-base-url = "https://github.com/rust-lang/rust/issues/" - -[features] -foo = [] -bar = { requires = ["foo"], doc = "simple docstring here" } -# ... -``` - -# Reference-level explanation - -[reference-level-explanation]: #reference-level-explanation - -At a high level, the following changes will be necessary: - -1. Cargo will change its parsing to accept the new format for `[features]` -2. `rustdoc` will gain two optional arguments: `--config-file` (for specifying - `rustdoc.toml`-style files), and `--config-json` (for specifying the same - information via JSON text, or a path to a JSON file). These arguments can be - specified more than once -3. Cargo will naively serialize some information from `Cargo.toml` to pass to - `rustdoc`, and make `rustdoc` aware of any `rustdoc.toml` files. -4. `rustdoc` will parse each of the `--config-*` arguments to create its - internal configuration. - -This is described in more detail in the following sections. - -## Changes to Cargo - -Cargo will need to parse the new format for `[features]`. For its non-rustdoc -use, it can discard all new information. - -The `cargo doc` invocation will need to do two new things: - -1. Reserialize the `[features]` and `[tools.rustdoc]` tables from any - `Cargo.toml` file to JSON. This can be naive, i.e., Cargo does not need to - validate the contained information in any way. -2. Pass this information as a string via `--config-json`. If string length - exceeds a limit (e.g., 2000 characters), write this configuration instead to - a temporary build JSON file. (to avoid maximum argument length restrictions - and keep verbose output concise). -3. Find files named `rustdoc.toml` and pass their paths to `rustdoc` using - `--config-toml`; no parsing of these files is necessary. - -Cargo should use the following precedence (later items take priority over -earlier items): - -1. Workspace `Cargo.toml` -2. Workspace root `rustdoc.toml` -3. Crate `Cargo.toml` -4. Crate root `rustdoc.toml` - -`rustdoc` will be in charge of handling configuration merging. This should -create an intuitive layering of global options and overrides while keeping -`rustdoc` and `Cargo` reasonably separate. - -## Changes to `rustdoc` - -`rustdoc` must be aware of two new arguments: `--config-json` and -`--config-file`. `--config-json` accepts either a JSON file path or a JSON -string, `--config-file` accepts a path to a TOML file. The JSON and TOML -share an identical schema to what is shown above: - -```json5 -{ - "html-logo-url": "https://example.com/logo.jpg", - "issue-tracker-base-url": "https://github.com/rust-lang/rust/issues/", - "features": { - "foo": [], - "bar": { "doc": "simple docstring here", "requires": ["foo"] }, - "baz": { "public": false, "requires": ["bar"] }, - "qux": { - "doc": "# corge\n\nThis could be a longer description of this feature\n", - "requires": ["bar", "baz"] - } - } -} -``` - -Spans can also be specified for JSON files for better diagnostics. It is -expected that Cargo could maintain span information for data extracted from -`Cargo.toml`, but it is not required that other build systems or handwritten -configurationĀ provide this information. This is also not required for a minimum -viable product. - -```json5 -{ - // Indicate the source file that spans are based on - "_root-span-path": "/path/to/Cargo.TOML", - "html-logo-url": { - "data": "https://example.com/logo.jpg", - "start": 100, - "end": 123 - }, - "features": { - "data": { - "foo": { "data": [], "start": 10, "end": 15 }, - "bar": { - "data": { - "doc": { "data": "simple docstring here", "start": 15, "end": 20 }, - "requires": { "data": ["foo"], "start": 20, "end": 25 } - }, - "start": 15, - "end": 30 - } - }, - "start": 10, - "end": 100 - } -} -``` - -`rustdoc` should start with a default configuration and update/overwrite it with -each `--config-file` or `--config-json` argument. Configuration specified in -rust source files (e.g. `#![doc(html_favicon_url ="foo.com/favicon")]`) take the -highest priority. - -# Drawbacks - -[drawbacks]: #drawbacks - -- This adds complexity to `rustdoc`. In this case, it does seem like it is - justified. -- This adds noise to the Cargo manifest that is not relevant to Cargo itself. - This RFC seeks to provide a good middle ground: lengthy or complex - configuration or feature descriptions can exist in a separate `rustdoc.toml`, - but a separate file also isn't required for simple configuration. -- If a user chooses to maintain feature descriptions in `rustdoc.toml` instead - of `Cargo.toml`, it does add multiple sources of truth for feature data. - -# Rationale and alternatives - -[rationale-and-alternatives]: #rationale-and-alternatives - -- `rustdoc` could accept something like `--cargo-config Cargo.toml` and parse - the `Cargo.toml` itself. This is possible, but there are a couple reasons to - prefer this RFC's suggestions: - - Cargo will have the discretion for what exactly data to send. For example, - `cargo doc --no-default-features` could strip all features that aren't - default, without `rustdoc` needing to be aware of the argument. - - Documentation systems other than Cargo maintain flexibility. For example, - `doxygen` could invoke `rustdoc` and pass a favicon URL that doesn't need to - come from `rustdoc.toml` or `Cargo.toml`. - - Reserializing relevant sections of `Cargo.toml` is easy for Cargo to do, as - it doesn't have to validate anything. -- JSON configuration could be skipped entirely, only using TOML. This RFC - proposes JSON because: - - It is easier to make CLI-safe than TOML - - TOML->JSON serialization is trivial. `rustdoc` can also easily handle both - schemas using the same serde structures. - - Build systems other than Cargo can make use of it easier: plenty of tools - are available to serialize JSON, but serializing TOML is less common (e.g. - Python's `tomllib` can parse TOML but not recreate it) -- No information could be provided in `Cargo.toml`, only allowing - `rustdoc.toml`. For features, keeping descriptions in `Cargo.toml` is - preferable because it provides a single source of truth for all things feature - related, rather than requiring that a user maintain two separate files (which - is more or less the current status quo). -- Feature descriptions could be specified somewhere in Rust source files. Like - the above, this has the downside of having 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: - -- `docs.rs` displays a feature table, but it is fairly limited -- Ivy has a [visibility attribute] for its configuration (mentioned in [cargo #10882]) - -[visibility attribute]: https://ant.apache.org/ivy/history/latest-milestone/ivyfile/conf.html -[cargo #10882]: https://github.com/rust-lang/cargo/issues/10882 - -# Unresolved questions - -[unresolved-questions]: #unresolved-questions - -Implementation blocking: - -- Should `cargo` use the `public` attribute to disallow downstream crates from - using features (for e.g., functions that provide unstable features or - benchmark-only functions). Must be adopted as the same time as parsing, as - enabling this later would break compatibility. See also: - -- If the answer to the above is "yes", does it make sense to have separate - `hidden` (not documented) and `public` attribute (not allowed downstream) - attribute? - -Nonblocking: - -- How exactly will `rustdoc` present the feature information? A new section on - the module's top-level could be reasonable. -- Should `rustdoc` allow a header/overview for the features section? This can be - done in the future with e.g. a `tools.rustdoc.features-doc` key in TOML. -- Should Cargo also send the contents of the `[dependencies]` table or other - information? This could be used to give `rustdoc` a dependencies viewer, like - `docs.rs` currently displays in the top bar. - -# Future possibilities - -[future-possibilities]: #future-possibilities - -- Cargo could parse doc comments in `Cargo.toml`, like the above linked - `document-features` crate. This adds some complexity to TOML parsing, but - `rustdoc` would not need to do anything different as long as a parser could - make the two below examples equivalent: - - ```toml - [features] - foo = { requires = [], doc = "foo feature" } - ## foo feature - foo = [] - ``` -- The `deprecated` attribute would allow Cargo to warn downstream crates using - the feature -- `unstable` or `nightly` attributes for features could provide further - informations or restriction on use (see - ) -- `[tools.rustdoc]` can grow to hold a resources manifest. For example: - ```toml - [tools.rustdoc] - # cargo would likely have to canonicalize this path - resource-root = "../static" - - [resources] - # .rs files can refer to this asset as "intro-video", located at "../static/sample.mp4" - intro-video = "sample.mp4" - header-include = ["js/katex.js", "js/render-output-graphs.js", "mytheme.css"] - ``` -- This could set a precedent for tools receiving information from `Cargo.toml`. - For example, the tool `cargo-foo-all-bars` could have a `[tools.foo-all-bars]` - table in `Cargo.toml`. Upon `cargo foo-all-bars` invocation, Cargo could pass - the contents of this tools table. - - The ideas in this RFC could also eventually allow `[tools.clippy]`and - `[tools.rustfmt]` tables to simplify configuration of those tools. diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md new file mode 100644 index 00000000000..9ff28239f25 --- /dev/null +++ b/text/0000-feature-metadata.md @@ -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 +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: + +- If a boolean value, `false` indicates not deprecated and `true` indicates + deprecated +- If an object, the keys `since` and/or `note` can be specified +- 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. + +## `public` + +`public` is a boolean value that defaults to `true`. It can be thought of as +`pub` in Rust source files, with the exception of being true by default. If set +to `false`, Cargo should forbid its use with an error message on any downstream +crates. + +There needs to be an escape hatch for this for things like benchmarks - RFC TBD +on how this works. + +## `unstable` + +`unstable` is a boolean value that defaults to `false`. It should indicate that +a feature gates something that is not API-stable, or can only be built using +`nightly` Rust. + +--- + +Use cases for this information will likely develop with time, but one of the +simplest applications is for information output 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 + - 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 + +[drawbacks]: #drawbacks + +- 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 + to parse standard TOML. +- 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: + +- `docs.rs` displays a feature table, but it is fairly limited +- 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. + +- Do we want all the proposed keys? Specifically, `public` and `unstable` may be + more than what is needed. + + See also: + + - + - + +- 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? + +It is worth noting that simpler keys (`requires`, `doc`, `deprecated`) could be +stabilized immediately and other features could be postponed. + +# Future possibilities + +[future-possibilities]: #future-possibilities + +- Rustdoc will gain the ability to document features. This is planned in an + associated RFC. +- 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 + `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 From 4dd05e31b6408b1f050284770db0d1c1dbcfb628 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 20 Apr 2023 12:33:50 -0400 Subject: [PATCH 15/45] Initial updates based on review --- text/0000-feature-metadata.md | 38 ++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index 9ff28239f25..c71e54ea09e 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -127,7 +127,8 @@ attribute in Rust source. The value can be a boolean, string, or an object with - If not specified, the default is `false` If a downstream crate attempts to use a feature marked `deprecated`, Cargo -should produce a warning. +should produce a warning. However, if a `since` is specified that is later than +the crate's current version, this warning should be ignored. ## `public` @@ -183,6 +184,9 @@ false` since they aren't listed on the crate landing page. - 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 +- A markdown parser will eventaully be required to properly parse the `doc` + field. Cargo can likely get away without one for basic functionality, such + as printing the summary with `cargo add`. # Rationale and alternatives @@ -194,6 +198,18 @@ false` since they aren't listed on the crate landing page. to parse standard TOML. - 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 + [features] + foo = { requires = [], doc = "foo feature" } + ## foo feature + foo = [] + ``` + + This was decided against as part of this RFC because it would mean that + standard TOML parsers cannot extract all the information in `Cargo.toml`. # Prior art @@ -245,6 +261,13 @@ stabilized immediately and other features could be postponed. - Rustdoc will gain the ability to document features. This is planned in an associated RFC. +- Somehow inform users if they are using to-be-deprecated features, i.e., + deprecated `since` is set but is later than the current dependancy version. +- `cargo add` can show the `doc` and `deprecated` summary with the listed + features. +- [`cargo-info`] can use this information to provide feature descriptions. +- `deprecated` could take a `replace-with` key that indicates features have + moved to a different name - 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. @@ -254,19 +277,6 @@ stabilized immediately and other features could be postponed. bar = { requires = [], doc-file = "features.md#bar" } ``` -- Cargo could parse doc comments in `Cargo.toml`, like the above linked - `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 From cea7180acc15344f3492fb07a3921601f33e8361 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 20 Apr 2023 12:54:18 -0400 Subject: [PATCH 16/45] Update two from the review round --- text/0000-feature-metadata.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index c71e54ea09e..88c04a7cbe9 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -137,6 +137,17 @@ the crate's current version, this warning should be ignored. to `false`, Cargo should forbid its use with an error message on any downstream crates. +In general, marking a feature `public = false` should make tooling treat the +feature as non-public API. That includes: + +- The feature should not be accepted by `cargo add --features` +- The feature should not be reported from the feature output report of `cargo + add` +- In the future, `rustdoc` should not document these features unless + `--document-private-items` is specified +- A future tool like `cargo info` shouldn't display information about these + features + There needs to be an escape hatch for this for things like benchmarks - RFC TBD on how this works. @@ -187,6 +198,8 @@ false` since they aren't listed on the crate landing page. - A markdown parser will eventaully be required to properly parse the `doc` field. Cargo can likely get away without one for basic functionality, such as printing the summary with `cargo add`. +- This RFC does not provide any way for `rustdoc` to get the information it + requires. This will require separate design work. # Rationale and alternatives From 4ab3a6f7d3a3b6ceef68c48edba446292ac63791 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 20 Apr 2023 13:12:17 -0400 Subject: [PATCH 17/45] Updates round three from review --- text/0000-feature-metadata.md | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index 88c04a7cbe9..79dd207f6f8 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -99,6 +99,8 @@ following sections: `requires` will take the place of the feature dependency array that currently exists. Semantics will remain unchanged. +This is a required key. + ## `doc` `doc` is the most straightforward: it accepts markdown-flavored text, and should @@ -127,8 +129,15 @@ attribute in Rust source. The value can be a boolean, string, or an object with - If not specified, the default is `false` If a downstream crate attempts to use a feature marked `deprecated`, Cargo -should produce a warning. However, if a `since` is specified that is later than -the crate's current version, this warning should be ignored. +should produce a warning. There are two exceptions to this: + +- If a `since` is specified that is later than the crate's current version, + this warning should not be emitted. +- This warning should not be emitted for crates that reexport the feature + under a feature also marked deprecated. For example: crate `foo` exports + feature `phooey`, and crate `bar` exports feature `barred = ["foo/phooey"]`. + If `foo` markes `bar` as deprecated, checking `bar` will emit a warning + unless `barred` is also marked `deprecated. ## `public` @@ -230,26 +239,14 @@ false` since they aren't listed on the crate landing page. - There is an existing crate that uses TOML comments to create a features table: -- `docs.rs` displays a feature table, but it is fairly limited +- `docs.rs` displays a feature table, but it is fairly limited. If features + start with `_`, they are hidden from this table. - 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. - - Do we want all the proposed keys? Specifically, `public` and `unstable` may be more than what is needed. @@ -272,8 +269,8 @@ stabilized immediately and other features could be postponed. [future-possibilities]: #future-possibilities -- Rustdoc will gain the ability to document features. This is planned in an - associated RFC. +- Rustdoc will gain the ability to document features. This is planned in the + [`rustdoc-cargo-configuration`] RFC. - Somehow inform users if they are using to-be-deprecated features, i.e., deprecated `since` is set but is later than the current dependancy version. - `cargo add` can show the `doc` and `deprecated` summary with the listed @@ -291,6 +288,7 @@ stabilized immediately and other features could be postponed. ``` +[`rustdoc-cargo-configuration`]: https://github.com/rust-lang/rfcs/pull/3421 [`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 From 5f48f2d5881869f1cd576b6acbbd92ed1dca7d97 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 20 Apr 2023 13:38:17 -0400 Subject: [PATCH 18/45] Updates round four --- text/0000-feature-metadata.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index 79dd207f6f8..d7adc76dd3f 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -151,7 +151,7 @@ feature as non-public API. That includes: - The feature should not be accepted by `cargo add --features` - The feature should not be reported from the feature output report of `cargo - add` +add` - In the future, `rustdoc` should not document these features unless `--document-private-items` is specified - A future tool like `cargo info` shouldn't display information about these @@ -194,6 +194,16 @@ crab@rust foobar % cargo add regex Features like `aho-corasick`, `memchr`, or `use_std` would likely be `public = false` since they aren't listed on the crate landing page. +Another thing to note is sort order. In general, any tool that renders features +(`rustdoc`, `cargo add`) should attempt to present them in the following way: + +- Display default features first +- Display non-default but stable features next (can be in a separate section) +- Display unstable or deprecated features last (can be in a separate section) +- Do not display private features unless receiving a flag saying to do so (e.g. + `--document-private-items` with `rustdoc`) +- If ordering is not preserved, present the features alphabetically + # Drawbacks [drawbacks]: #drawbacks @@ -209,15 +219,13 @@ false` since they aren't listed on the crate landing page. as printing the summary with `cargo add`. - This RFC does not provide 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, unlike with the `document-features` crate. # 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 - to parse standard TOML. - 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` @@ -287,7 +295,6 @@ stabilized immediately and other features could be postponed. bar = { requires = [], doc-file = "features.md#bar" } ``` - [`rustdoc-cargo-configuration`]: https://github.com/rust-lang/rfcs/pull/3421 [`tokio`]: https://docs.rs/crate/tokio/latest/features [`cargo-info`]: https://github.com/rust-lang/cargo/issues/948 From 19c3521a15cfe4956e602eaaf990f6820418a334 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 20 Apr 2023 13:51:04 -0400 Subject: [PATCH 19/45] Updates round five --- text/0000-feature-metadata.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index d7adc76dd3f..8e05d5d09aa 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -215,12 +215,13 @@ Another thing to note is sort order. In general, any tool that renders features potentially be solved with the below mentioned `doc-file` key. - `unstable` and `public` uses may not be common enough to be worth including - A markdown parser will eventaully be required to properly parse the `doc` - field. Cargo can likely get away without one for basic functionality, such - as printing the summary with `cargo add`. + field. Presenting unrendered markdown is likely suitable as a first step, + but in general, markdown is required to fully interpret the field. - This RFC does not provide 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, unlike with the `document-features` crate. +- Features cannot be ordered since the TOML specification does not allow it. # Rationale and alternatives @@ -269,6 +270,8 @@ Another thing to note is sort order. In general, any tool that renders features - 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? +- The Cargo index may need a way to be aware of deprecated features, so it can + properly report them during resolution. What would be needed here? It is worth noting that simpler keys (`requires`, `doc`, `deprecated`) could be stabilized immediately and other features could be postponed. From 32174e8020bd54754ab14c3431c3e63ee9504168 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 20 Apr 2023 13:56:56 -0400 Subject: [PATCH 20/45] Updates round six --- text/0000-feature-metadata.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index 8e05d5d09aa..bc5b72644ec 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -240,7 +240,10 @@ Another thing to note is sort order. In general, any tool that renders features ``` This was decided against as part of this RFC because it would mean that - standard TOML parsers cannot extract all the information in `Cargo.toml`. + standard TOML parsers (including anything `serde`-based) cannot extract all + the information in `Cargo.toml` - a format-preserving parser would be + required. This differs from documentation in Rust source, where a custom + parser already has to be used. # Prior art From cbc31d55f5b6dbc26895043831949786e29471c7 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 10 Jun 2023 01:26:37 -0400 Subject: [PATCH 21/45] Updates regarding parser --- text/0000-feature-metadata.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index bc5b72644ec..c6d367a8a60 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -220,7 +220,8 @@ Another thing to note is sort order. In general, any tool that renders features - This RFC does not provide 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, unlike with the `document-features` crate. + 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 @@ -240,10 +241,12 @@ Another thing to note is sort order. In general, any tool that renders features ``` This was decided against as part of this RFC because it would mean that - standard TOML parsers (including anything `serde`-based) cannot extract all - the information in `Cargo.toml` - a format-preserving parser would be - required. This differs from documentation in Rust source, where a custom - parser already has to be used. + 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 From 97e8301d9f1340be5a05003fb090ad7c7849c971 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 10 Jun 2023 01:38:07 -0400 Subject: [PATCH 22/45] Clarify markdown status for documentation --- text/0000-feature-metadata.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index c6d367a8a60..fd13e72c3f5 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -99,18 +99,19 @@ following sections: `requires` will take the place of the feature dependency array that currently exists. Semantics will remain unchanged. -This is a required key. +This is a required key. If there are no requirements, an empty list should be +provided (`requires = []`). ## `doc` `doc` is the most straightforward: it accepts markdown-flavored text, and should 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. +the first line should be treated as a summary. 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. +be used for general diagnostic information such as during `cargo add` or +a possible `cargo info` command. ## `deprecated` @@ -214,9 +215,7 @@ Another thing to note is sort order. In general, any tool that renders features - 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 -- A markdown parser will eventaully be required to properly parse the `doc` - field. Presenting unrendered markdown is likely suitable as a first step, - but in general, markdown is required to fully interpret the field. +- A markdown parser is required to properly parse the `doc` field. - This RFC does not provide 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 From fff9af1744999c5409e55e23873d54ff19023f2a Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 10 Jun 2023 02:01:10 -0400 Subject: [PATCH 23/45] Add note about optional dev dependencies --- text/0000-feature-metadata.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index fd13e72c3f5..1a40ac73f14 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -289,6 +289,8 @@ stabilized immediately and other features could be postponed. [`rustdoc-cargo-configuration`] RFC. - Somehow inform users if they are using to-be-deprecated features, i.e., deprecated `since` is set but is later than the current dependancy version. +- `unstable` or `private` feature flags could be used to allow optional dev + dependencies. See: - `cargo add` can show the `doc` and `deprecated` summary with the listed features. - [`cargo-info`] can use this information to provide feature descriptions. From f1fb220ddff01ec8835cda06199ff29605f8489f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 10 Jun 2023 02:10:04 -0400 Subject: [PATCH 24/45] Remove unstable flag --- text/0000-feature-metadata.md | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index 1a40ac73f14..77d7cc6f996 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -19,7 +19,7 @@ information is in a separate RFC. [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 +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: @@ -48,7 +48,7 @@ foo = [] # New configurations bar = { requires = ["foo"], doc = "simple docstring here"} baz = { requires = ["foo"], public = false} -qux = { requires = [], deprecated = true, unstable = true } +qux = { requires = [], deprecated = true } quux = { requires = [], deprecated = { since = "1.2.3", note = "don't use this!" } } # Features can also be full tables if descriptions are longer @@ -72,8 +72,6 @@ The following keys would be allowed in a feature table: 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: @@ -161,12 +159,6 @@ add` There needs to be an escape hatch for this for things like benchmarks - RFC TBD on how this works. -## `unstable` - -`unstable` is a boolean value that defaults to `false`. It should indicate that -a feature gates something that is not API-stable, or can only be built using -`nightly` Rust. - --- Use cases for this information will likely develop with time, but one of the @@ -186,7 +178,6 @@ crab@rust foobar % cargo add regex + 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 @@ -200,7 +191,7 @@ Another thing to note is sort order. In general, any tool that renders features - Display default features first - Display non-default but stable features next (can be in a separate section) -- Display unstable or deprecated features last (can be in a separate section) +- Display deprecated features last (can be in a separate section) - Do not display private features unless receiving a flag saying to do so (e.g. `--document-private-items` with `rustdoc`) - If ordering is not preserved, present the features alphabetically @@ -211,10 +202,10 @@ Another thing to note is sort order. In general, any tool that renders features - 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 +- Added Cargo arguments if escape hatches for `public` 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 +- `public` uses may not be common enough to be worth including - A markdown parser is required to properly parse the `doc` field. - This RFC does not provide any way for `rustdoc` to get the information it requires. This will require separate design work. @@ -261,8 +252,8 @@ Another thing to note is sort order. In general, any tool that renders features [unresolved-questions]: #unresolved-questions -- Do we want all the proposed keys? Specifically, `public` and `unstable` may be - more than what is needed. +- Do we want all the proposed keys? Specifically, `public` may be more than + what is needed. See also: @@ -270,8 +261,7 @@ Another thing to note is sort order. In general, any tool that renders features - - 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? + `--allow-private-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? @@ -289,6 +279,8 @@ stabilized immediately and other features could be postponed. [`rustdoc-cargo-configuration`] RFC. - Somehow inform users if they are using to-be-deprecated features, i.e., deprecated `since` is set but is later than the current dependancy version. +- An `unstable` feature flag that indicates API-unstable or nightly-only + features. - `unstable` or `private` feature flags could be used to allow optional dev dependencies. See: - `cargo add` can show the `doc` and `deprecated` summary with the listed From 98dbaa1f21a9466ab329ac285c4ec0df19a5f6b9 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 10 Jun 2023 02:34:54 -0400 Subject: [PATCH 25/45] Add suggestion about rust-version flag --- text/0000-feature-metadata.md | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index 77d7cc6f996..34e4dcc4a89 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -242,11 +242,12 @@ Another thing to note is sort order. In general, any tool that renders features [prior-art]: #prior-art -- There is an existing crate that uses TOML comments to create a features table: - +- There is an existing crate that uses TOML comments to create a features + table: - `docs.rs` displays a feature table, but it is fairly limited. If features start with `_`, they are hidden from this table. -- Ivy has a [visibility attribute] for its configuration (mentioned in [cargo #10882]) +- Ivy has a [visibility attribute] for its configuration (mentioned in + [cargo #10882]) # Unresolved questions @@ -279,17 +280,20 @@ stabilized immediately and other features could be postponed. [`rustdoc-cargo-configuration`] RFC. - Somehow inform users if they are using to-be-deprecated features, i.e., deprecated `since` is set but is later than the current dependancy version. -- An `unstable` feature flag that indicates API-unstable or nightly-only - features. +- An `unstable` field that indicates API-unstable or nightly-only features. +- A `rust-version` field that could indicate e.g. `rust-version = "nightly"` + or `rust-version = "1.65"` to specify a MSRV for that feature. See: + - `unstable` or `private` feature flags could be used to allow optional dev dependencies. See: - `cargo add` can show the `doc` and `deprecated` summary with the listed features. - [`cargo-info`] can use this information to provide feature descriptions. -- `deprecated` could take a `replace-with` key that indicates features have - moved to a different name -- 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 +- `deprecated` could take a `suggestion` key that indicates features have + moved to a different name (as with the [`deprecated-suggestions`] feature) +- 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 @@ -297,9 +301,10 @@ stabilized immediately and other features could be postponed. bar = { requires = [], doc-file = "features.md#bar" } ``` +[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#issuecomment-1579349116 [`rustdoc-cargo-configuration`]: https://github.com/rust-lang/rfcs/pull/3421 [`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 From 8cab2f0a38655585d4165c5bd39f273df650677b Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 30 Jun 2023 03:25:13 -0400 Subject: [PATCH 26/45] Move deny deprecated features to future possibilities --- text/0000-feature-metadata.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index 34e4dcc4a89..723a5871768 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -265,7 +265,6 @@ Another thing to note is sort order. In general, any tool that renders features `--allow-private-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? - The Cargo index may need a way to be aware of deprecated features, so it can properly report them during resolution. What would be needed here? @@ -280,6 +279,8 @@ stabilized immediately and other features could be postponed. [`rustdoc-cargo-configuration`] RFC. - Somehow inform users if they are using to-be-deprecated features, i.e., deprecated `since` is set but is later than the current dependancy version. +- Via the `manifest-lint` RFC, a user could specify that deprecated crates + should be denied. - An `unstable` field that indicates API-unstable or nightly-only features. - A `rust-version` field that could indicate e.g. `rust-version = "nightly"` or `rust-version = "1.65"` to specify a MSRV for that feature. See: From fe7767be35e24ab43d1fe3f9205cf7d916a34900 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 30 Jun 2023 03:44:14 -0400 Subject: [PATCH 27/45] Adjust mentions of 'unstable' to 'stable', refactpr sections --- text/0000-feature-metadata.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index 723a5871768..6c23ec35809 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -159,7 +159,7 @@ add` There needs to be an escape hatch for this for things like benchmarks - RFC TBD on how this works. ---- +# Implementation & Usage Use cases for this information will likely develop with time, but one of the simplest applications is for information output with `cargo add`: @@ -186,7 +186,9 @@ crab@rust foobar % cargo add regex Features like `aho-corasick`, `memchr`, or `use_std` would likely be `public = false` since they aren't listed on the crate landing page. -Another thing to note is sort order. In general, any tool that renders features +## Implementation notes + +One item of note is sort order. In general, any tool that renders features (`rustdoc`, `cargo add`) should attempt to present them in the following way: - Display default features first @@ -196,6 +198,7 @@ Another thing to note is sort order. In general, any tool that renders features `--document-private-items` with `rustdoc`) - If ordering is not preserved, present the features alphabetically + # Drawbacks [drawbacks]: #drawbacks @@ -281,12 +284,14 @@ stabilized immediately and other features could be postponed. deprecated `since` is set but is later than the current dependancy version. - Via the `manifest-lint` RFC, a user could specify that deprecated crates should be denied. -- An `unstable` field that indicates API-unstable or nightly-only features. +- An `stable` field can be set false to indicate API-unstable or nightly-only + features (somethign such as `stable = 3.2` could be used to indicate when a + feature was stabilized) - A `rust-version` field that could indicate e.g. `rust-version = "nightly"` or `rust-version = "1.65"` to specify a MSRV for that feature. See: -- `unstable` or `private` feature flags could be used to allow optional dev - dependencies. See: +- The `public` feature flags could be used to allow optional dev dependencies. + See: - `cargo add` can show the `doc` and `deprecated` summary with the listed features. - [`cargo-info`] can use this information to provide feature descriptions. From b952ce17d9db3303e006a77ccc9628e2a19c430b Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 30 Jun 2023 03:48:23 -0400 Subject: [PATCH 28/45] Update some links --- text/0000-feature-metadata.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index 6c23ec35809..bae88752265 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -210,8 +210,9 @@ One item of note is sort order. In general, any tool that renders features potentially be solved with the below mentioned `doc-file` key. - `public` uses may not be common enough to be worth including - A markdown parser is required to properly parse the `doc` field. -- This RFC does not provide any way for `rustdoc` to get the information it - requires. This will require separate design work. +- 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. @@ -283,10 +284,11 @@ stabilized immediately and other features could be postponed. - Somehow inform users if they are using to-be-deprecated features, i.e., deprecated `since` is set but is later than the current dependancy version. - Via the `manifest-lint` RFC, a user could specify that deprecated crates - should be denied. -- An `stable` field can be set false to indicate API-unstable or nightly-only + should be denied. This would, however, be blocked by [cargo #12335]. +- A `stable` field can be set false to indicate API-unstable or nightly-only features (somethign such as `stable = 3.2` could be used to indicate when a - feature was stabilized) + feature was stabilized). See also: + - A `rust-version` field that could indicate e.g. `rust-version = "nightly"` or `rust-version = "1.65"` to specify a MSRV for that feature. See: @@ -307,6 +309,7 @@ stabilized immediately and other features could be postponed. bar = { requires = [], 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 From 9b2a04446255016e00d054ea88aecb1f166b8c77 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 30 Jun 2023 04:16:20 -0400 Subject: [PATCH 29/45] Add notes about public=true default and index changes --- text/0000-feature-metadata.md | 42 ++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index bae88752265..deec0779860 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -111,6 +111,11 @@ 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. +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]. + ## `deprecated` `deprecated` should be thought of as the equivalent of the [`deprecated`] @@ -138,6 +143,8 @@ should produce a warning. There are two exceptions to this: If `foo` markes `bar` as deprecated, checking `bar` will emit a warning unless `barred` is also marked `deprecated. +Accessing this information will require access to the manifest. + ## `public` `public` is a boolean value that defaults to `true`. It can be thought of as @@ -145,6 +152,11 @@ should produce a warning. There are two exceptions to this: to `false`, Cargo should forbid its use with an error message on any downstream crates. +The default `true` is not consistent with [`public_private_dependencies`] or +Rust's `pub`, but is a reasonable default to be consistent with the current +behavior so that either `feature = []` or `feature = { "requires" = [] }` will +return the same result. + In general, marking a feature `public = false` should make tooling treat the feature as non-public API. That includes: @@ -156,10 +168,19 @@ add` - A future tool like `cargo info` shouldn't display information about these features -There needs to be an escape hatch for this for things like benchmarks - RFC TBD -on how this works. +There likely needs to be an escape hatch for this for things like benchmarks - +RFC TBD on how this works. + +This feature would require adjustments to the index for full support. This RFC +proposes that it would be acceptable for the first implementation to simply +strip private features from the manifest; this meanss that there will be no way +to `cfg` based on these features. -# Implementation & Usage +Full support does not need to happen immediately, since it will require this +information be present in the index. [Index changes] describes how this can take +place. + +# General Implementation & Usage Use cases for this information will likely develop with time, but one of the simplest applications is for information output with `cargo add`: @@ -186,10 +207,10 @@ crab@rust foobar % cargo add regex Features like `aho-corasick`, `memchr`, or `use_std` would likely be `public = false` since they aren't listed on the crate landing page. -## Implementation notes +## Implementation note: sort order -One item of note is sort order. In general, any tool that renders features -(`rustdoc`, `cargo add`) should attempt to present them in the following way: +In general, any tool that renders features (`rustdoc`, `cargo add`) should +attempt to present them in the following way: - Display default features first - Display non-default but stable features next (can be in a separate section) @@ -198,6 +219,14 @@ One item of note is sort order. In general, any tool that renders features `--document-private-items` with `rustdoc`) - If ordering is not preserved, present the features alphabetically +## Index changes + +[index changes]: #index-changes + +For features that require new information in the index, it should be possible to +add this information under a `features3` key. Older versions of Cargo will +ignore this key, newer Cargo would be able to merge `features`, `features2`, and +`features3`. # Drawbacks @@ -314,6 +343,7 @@ stabilized immediately and other features could be postponed. [`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#issuecomment-1579349116 +[`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 From 15a2432e024acbe2037b31d7202f810be2f636a0 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 30 Jun 2023 04:19:40 -0400 Subject: [PATCH 30/45] Add note about doc in index --- text/0000-feature-metadata.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index deec0779860..58ded4f3c0c 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -321,6 +321,9 @@ stabilized immediately and other features could be postponed. - A `rust-version` field that could indicate e.g. `rust-version = "nightly"` or `rust-version = "1.65"` to specify a MSRV for that feature. See: +- 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. - The `public` feature flags could be used to allow optional dev dependencies. See: - `cargo add` can show the `doc` and `deprecated` summary with the listed From 88a34470f0c0911f45fa0e276cadebbada20bec2 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 2 Jul 2023 06:51:24 -0400 Subject: [PATCH 31/45] Add note about naming choice --- text/0000-feature-metadata.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index 58ded4f3c0c..00619deb7c5 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -157,14 +157,17 @@ Rust's `pub`, but is a reasonable default to be consistent with the current behavior so that either `feature = []` or `feature = { "requires" = [] }` will return the same result. +The name `public` was chosen in favor of `pub` to be consistent with the +[`public_private_dependencies`] RFC, and to match the existing style of using +non-truncated words as keys. + In general, marking a feature `public = false` should make tooling treat the feature as non-public API. That includes: - The feature should not be accepted by `cargo add --features` -- The feature should not be reported from the feature output report of `cargo -add` -- In the future, `rustdoc` should not document these features unless - `--document-private-items` is specified +- The feature should not be reported from `cargo add`'s feature output report +- Once `rustdoc` is able to consume feature metadata, `rustdoc` should not + document these features unless `--document-private-items` is specified - A future tool like `cargo info` shouldn't display information about these features From e36b1559413347634652dc8d4d67a8a03ffe1459 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 2 Jul 2023 07:15:42 -0400 Subject: [PATCH 32/45] Add markdown vs. plaintext as an unresolved question --- text/0000-feature-metadata.md | 39 +++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index 00619deb7c5..37252627c15 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -69,9 +69,10 @@ The following keys would be allowed in a feature table: - `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 + with `since` and/or `note` keys. Cargo will warn downstream crates using + this feature. - `public`: A boolean flag defaulting to `true` that indicates whether or not - downstream crates should be allowed to use this feature + downstream crates should be allowed to use this feature. If a downstream crate attempts to use the features `baz` and `qux`, they will see messages like the following: @@ -104,7 +105,8 @@ provided (`requires = []`). `doc` is the most straightforward: it 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. +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 @@ -183,6 +185,12 @@ Full support does not need to happen immediately, since it will require this information be present in the index. [Index changes] describes how this can take place. +Two sample use cases for `public = false` include: + +- `docs.rs` having a way to know which features should be hidden +- Features that are included in feature chains (feature `a` enables feature + `b`) but not meant for public consumption could be marked not public + # General Implementation & Usage Use cases for this information will likely develop with time, but one of the @@ -284,28 +292,23 @@ ignore this key, newer Cargo would be able to merge `features`, `features2`, and start with `_`, they are hidden from this table. - Ivy has a [visibility attribute] for its configuration (mentioned in [cargo #10882]) +- Discussion on stable/unstable/nightly-only features + # Unresolved questions [unresolved-questions]: #unresolved-questions -- Do we want all the proposed keys? Specifically, `public` may be more than - what is needed. - - See also: - - - - - - - If we use the semantics as-written, should there be a `--allow-private-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 -- The Cargo index may need a way to be aware of deprecated features, so it can - properly report them during resolution. What would be needed here? - -It is worth noting that simpler keys (`requires`, `doc`, `deprecated`) could be -stabilized immediately and other features could be postponed. +- 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. + +It is worth noting that not all of these feature flags need to be made available +at once. `requires` needs to be implemented first, but support for all others +could be added over time. # Future possibilities From 397d47e34567548b49b69d8232d231b577610738 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 2 Jul 2023 07:19:44 -0400 Subject: [PATCH 33/45] Rename 'requires' to 'enables' --- text/0000-feature-metadata.md | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index 37252627c15..51589eb69f9 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -46,14 +46,14 @@ possibilities: # 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 } -quux = { requires = [], deprecated = { since = "1.2.3", note = "don't use this!" } } +bar = { enables = ["foo"], doc = "simple docstring here"} +baz = { enables = ["foo"], public = false} +qux = { enables = [], deprecated = true } +quux = { enables = [], 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"] +enables = ["bar", "baz"] doc = """ # corge @@ -63,9 +63,10 @@ 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"] }` +- `enables`: This is synonymous with the existing array describing what + features are enabled by the described feature features. For example, `foo = + ["dep:serde", "otherfeat"]` will be identical to `foo = { enables = + ["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 @@ -93,13 +94,13 @@ 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` +## `enables` -`requires` will take the place of the feature dependency array that currently +`enables` will take the place of the feature dependency array that currently exists. Semantics will remain unchanged. This is a required key. If there are no requirements, an empty list should be -provided (`requires = []`). +provided (`enables = []`). ## `doc` @@ -156,7 +157,7 @@ crates. The default `true` is not consistent with [`public_private_dependencies`] or Rust's `pub`, but is a reasonable default to be consistent with the current -behavior so that either `feature = []` or `feature = { "requires" = [] }` will +behavior so that either `feature = []` or `feature = { "enables" = [] }` will return the same result. The name `public` was chosen in favor of `pub` to be consistent with the @@ -269,7 +270,7 @@ ignore this key, newer Cargo would be able to merge `features`, `features2`, and ```toml [features] - foo = { requires = [], doc = "foo feature" } + foo = { enables = [], doc = "foo feature" } ## foo feature foo = [] ``` @@ -307,7 +308,7 @@ ignore this key, newer Cargo would be able to merge `features`, `features2`, and implementation, the challenges of supporting markdown are better understood. It is worth noting that not all of these feature flags need to be made available -at once. `requires` needs to be implemented first, but support for all others +at once. `enables` needs to be implemented first, but support for all others could be added over time. # Future possibilities @@ -343,8 +344,8 @@ could be added over time. features requiring long descriptions. ```toml - foo = { requires = [], doc-file = "features.md#foo" } - bar = { requires = [], doc-file = "features.md#bar" } + foo = { enables = [], doc-file = "features.md#foo" } + bar = { enables = [], doc-file = "features.md#bar" } ``` [cargo #12335]: https://github.com/rust-lang/cargo/issues/12235 From f3b862b6591fca64fef38bb282910c9d49747d94 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 2 Jul 2023 07:53:40 -0400 Subject: [PATCH 34/45] Update documentation about private feature usage --- text/0000-feature-metadata.md | 75 ++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index 51589eb69f9..06c650a50fb 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -75,13 +75,10 @@ The following keys would be allowed in a feature table: - `public`: A boolean flag defaulting to `true` that indicates whether or not downstream crates should be allowed to use this feature. -If a downstream crate attempts to use the features `baz` and `qux`, they will -see messages like the following: +Attempting to use a private feature on a downstream crate will result in +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 ``` @@ -136,15 +133,12 @@ attribute in Rust source. The value can be a boolean, string, or an object with - If not specified, the default is `false` If a downstream crate attempts to use a feature marked `deprecated`, Cargo -should produce a warning. There are two exceptions to this: - -- If a `since` is specified that is later than the crate's current version, - this warning should not be emitted. -- This warning should not be emitted for crates that reexport the feature - under a feature also marked deprecated. For example: crate `foo` exports - feature `phooey`, and crate `bar` exports feature `barred = ["foo/phooey"]`. - If `foo` markes `bar` as deprecated, checking `bar` will emit a warning - unless `barred` is also marked `deprecated. +should produce a warning. This warning should not be emitted for crates that +reexport the feature under a feature also marked deprecated. For example: crate +`foo` exports feature `phooey`, and crate `bar` exports feature +`barred = ["foo/phooey"]`. If `foo` markes `bar` as deprecated, running any +cargo action on `bar` will emit a warning unless `barred` is also marked +`deprecated. Accessing this information will require access to the manifest. @@ -158,26 +152,41 @@ crates. The default `true` is not consistent with [`public_private_dependencies`] or Rust's `pub`, but is a reasonable default to be consistent with the current behavior so that either `feature = []` or `feature = { "enables" = [] }` will -return the same result. +result in the same configuration. The name `public` was chosen in favor of `pub` to be consistent with the [`public_private_dependencies`] RFC, and to match the existing style of using non-truncated words as keys. In general, marking a feature `public = false` should make tooling treat the -feature as non-public API. That includes: +feature as non-public API. This is described as the following: +- The feature is always usable within the same crate: + - Enablement by other features, e.g. `foo = { enables = + [some-private-feature] }`, is allowed + - Using the feature in integration tests is allowed + - Using the feature in benchmarks is allowed - The feature should not be accepted by `cargo add --features` - The feature should not be reported from `cargo add`'s feature output report - Once `rustdoc` is able to consume feature metadata, `rustdoc` should not document these features unless `--document-private-items` is specified - A future tool like `cargo info` shouldn't display information about these features +- Explicitly specifying the feature via `--features somecrate/private-feature` + will allow enabling a private feature that would otherwise be forbidden + +Attempting to use a private feature in any of the forbidden cases should result +in an error. Exact details of how features work will likely be refined during +implementation and experimentation. + +Two sample use cases for `public = false` include: + +- `docs.rs` having a way to know which features should be hidden +- Features that are included in feature chains (feature `a` enables feature + `b`) but not meant for public consumption could be marked not public -There likely needs to be an escape hatch for this for things like benchmarks - -RFC TBD on how this works. -This feature would require adjustments to the index for full support. This RFC +This feature requires adjustments to the index for full support. This RFC proposes that it would be acceptable for the first implementation to simply strip private features from the manifest; this meanss that there will be no way to `cfg` based on these features. @@ -186,12 +195,6 @@ Full support does not need to happen immediately, since it will require this information be present in the index. [Index changes] describes how this can take place. -Two sample use cases for `public = false` include: - -- `docs.rs` having a way to know which features should be hidden -- Features that are included in feature chains (feature `a` enables feature - `b`) but not meant for public consumption could be marked not public - # General Implementation & Usage Use cases for this information will likely develop with time, but one of the @@ -300,16 +303,22 @@ ignore this key, newer Cargo would be able to merge `features`, `features2`, and [unresolved-questions]: #unresolved-questions -- If we use the semantics as-written, should there be a - `--allow-private-features` flag? Or how should a user opt in? - 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. - -It is worth noting that not all of these feature flags need to be made available -at once. `enables` needs to be implemented first, but support for all others -could be added over time. +- Are the semantics of `public` proposed in this RFC suitable? Should private + features be usable in examples or integration tests without a `--features` + argument? +- Should there be a simple `--allow-private-features` flag that allows using + all features, such as for crater runs? This can be decided during + implementation. +- How should `since` work with the `deprecated` key? This can be decided + during implementation or droped entirely. + +It is worth noting that not all of these new keys need to be made available at +once. `enables` needs to be implemented first, but support for all others could +be added over time. # Future possibilities @@ -331,8 +340,8 @@ could be added over time. - 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. -- The `public` feature flags could be used to allow optional dev dependencies. - See: +- The `public` option could be used to allow optional dev dependencies. See: + - `cargo add` can show the `doc` and `deprecated` summary with the listed features. - [`cargo-info`] can use this information to provide feature descriptions. From 0c1a00fbafc3915170f562a7498416fa60f70234 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 2 Jul 2023 23:17:11 -0400 Subject: [PATCH 35/45] Update documentation of the 'since' deprecated key --- text/0000-feature-metadata.md | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index 06c650a50fb..76f147e86c9 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -133,15 +133,28 @@ attribute in Rust source. The value can be a boolean, string, or an object with - If not specified, the default is `false` If a downstream crate attempts to use a feature marked `deprecated`, Cargo -should produce a warning. This warning should not be emitted for crates that -reexport the feature under a feature also marked deprecated. For example: crate -`foo` exports feature `phooey`, and crate `bar` exports feature -`barred = ["foo/phooey"]`. If `foo` markes `bar` as deprecated, running any -cargo action on `bar` will emit a warning unless `barred` is also marked -`deprecated. +should produce a warning that contains the `note`. This warning should not be +emitted for crates that reexport the feature under a feature also marked +deprecated. For example: crate `foo` exports feature `phooey`, and crate `bar` +exports feature `barred = ["foo/phooey"]`. If `foo` markes `bar` as deprecated, +running any cargo action on `bar` will emit a warning unless `barred` is also +marked `deprecated. Accessing this information will require access to the manifest. +### A note on `since` + +The exact behavior of the `since` key is not provided in this RFC as there are +decisions related to resolution that need to be made. The generally accepted +concept is that there should be a warning if a deprecated feature is used _and_ +there is something actionable to resolve this issue for all downstream crates - +but the details of how best to do this are not yet clear. Please see [discussion +on since]. + +If the exact behavior of `since` does not reach consensus before `deprecated` is +nearing stabilization, this key can stabilized separately or dropped entirely. + + ## `public` `public` is a boolean value that defaults to `true`. It can be thought of as @@ -313,8 +326,8 @@ ignore this key, newer Cargo would be able to merge `features`, `features2`, and - Should there be a simple `--allow-private-features` flag that allows using all features, such as for crater runs? This can be decided during implementation. -- How should `since` work with the `deprecated` key? This can be decided - during implementation or droped entirely. +- How should `since` work with the `deprecated` key? See + [a note on `since`](#a-note-on-since) for further information. It is worth noting that not all of these new keys need to be made available at once. `enables` needs to be implemented first, but support for all others could @@ -361,7 +374,8 @@ be added over time. [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#issuecomment-1579349116 +[`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 From 8ad6c66d5c364c6d8e4c213879876c0c252b3683 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 2 Jul 2023 23:24:52 -0400 Subject: [PATCH 36/45] Add another note about the index --- text/0000-feature-metadata.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/text/0000-feature-metadata.md b/text/0000-feature-metadata.md index 76f147e86c9..9cdb219155a 100644 --- a/text/0000-feature-metadata.md +++ b/text/0000-feature-metadata.md @@ -89,7 +89,10 @@ error: feature `baz` on crate `mycrate` is private and cannot be used by 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: +below sections. + +It is worth noting that none of these keys depend on any others, so they can be +implemented and stabilized individually. ## `enables` @@ -140,7 +143,8 @@ exports feature `barred = ["foo/phooey"]`. If `foo` markes `bar` as deprecated, running any cargo action on `bar` will emit a warning unless `barred` is also marked `deprecated. -Accessing this information will require access to the manifest. +Accessing this information will require access to the manifest as it will not be +in the index. ### A note on `since` From 21b4be2e66017c69a5062f2d3bf8c81ec57c4991 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 2 Jul 2023 23:27:11 -0400 Subject: [PATCH 37/45] Rename RFC file --- text/{0000-feature-metadata.md => 3416-feature-metadata.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename text/{0000-feature-metadata.md => 3416-feature-metadata.md} (99%) diff --git a/text/0000-feature-metadata.md b/text/3416-feature-metadata.md similarity index 99% rename from text/0000-feature-metadata.md rename to text/3416-feature-metadata.md index 9cdb219155a..ded4d63dbe6 100644 --- a/text/0000-feature-metadata.md +++ b/text/3416-feature-metadata.md @@ -1,6 +1,6 @@ - Feature Name: feature-metadata - Start Date: 2023-04-14 -- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/3416) +- 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 From a390e5c717ea3d071854f0b37f744f961473f61a Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 2 Jul 2023 23:36:47 -0400 Subject: [PATCH 38/45] Update index comment --- text/3416-feature-metadata.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/text/3416-feature-metadata.md b/text/3416-feature-metadata.md index ded4d63dbe6..6828f5af521 100644 --- a/text/3416-feature-metadata.md +++ b/text/3416-feature-metadata.md @@ -100,7 +100,7 @@ implemented and stabilized individually. exists. Semantics will remain unchanged. This is a required key. If there are no requirements, an empty list should be -provided (`enables = []`). +provided (`enables = []`). This content is already in the index. ## `doc` @@ -158,7 +158,6 @@ on since]. If the exact behavior of `since` does not reach consensus before `deprecated` is nearing stabilization, this key can stabilized separately or dropped entirely. - ## `public` `public` is a boolean value that defaults to `true`. It can be thought of as From a0f6b0a2ec037536afc64b02057e1fa47897aa70 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 2 Jul 2023 23:43:41 -0400 Subject: [PATCH 39/45] More info about the index --- text/3416-feature-metadata.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/text/3416-feature-metadata.md b/text/3416-feature-metadata.md index 6828f5af521..55a313ce233 100644 --- a/text/3416-feature-metadata.md +++ b/text/3416-feature-metadata.md @@ -257,7 +257,21 @@ attempt to present them in the following way: For features that require new information in the index, it should be possible to add this information under a `features3` key. Older versions of Cargo will ignore this key, newer Cargo would be able to merge `features`, `features2`, and -`features3`. +`features3`. `features3` should mirror the most complete syntax of the +`[features]` table, i.e.: + +```json5 +"features3": { + "bar": { + enables: ["foo"], + deprecated = { since = "1.2.3", note = "don't use this" } + } +} +``` + +In order to conserve index space, default keys should be omitted. `Cargo` should +ignore unrecognized keys within a feature, to allow for future additions without +needing a new `features` section. # Drawbacks From b1e9656291a23a3cf13131b9d6e1cc40c192555f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 2 Jul 2023 23:46:28 -0400 Subject: [PATCH 40/45] Features/2/3 information added --- text/3416-feature-metadata.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/3416-feature-metadata.md b/text/3416-feature-metadata.md index 55a313ce233..fd5115fa093 100644 --- a/text/3416-feature-metadata.md +++ b/text/3416-feature-metadata.md @@ -257,13 +257,12 @@ attempt to present them in the following way: For features that require new information in the index, it should be possible to add this information under a `features3` key. Older versions of Cargo will ignore this key, newer Cargo would be able to merge `features`, `features2`, and -`features3`. `features3` should mirror the most complete syntax of the -`[features]` table, i.e.: +`features3`. `features3` should mirror the most complete syntax of the relevant +keys from the `[features]` table. Currently this is only `deprecated`, i.e.: ```json5 "features3": { "bar": { - enables: ["foo"], deprecated = { since = "1.2.3", note = "don't use this" } } } @@ -271,7 +270,8 @@ ignore this key, newer Cargo would be able to merge `features`, `features2`, and In order to conserve index space, default keys should be omitted. `Cargo` should ignore unrecognized keys within a feature, to allow for future additions without -needing a new `features` section. +needing a new `features` section. `enables` may be specified in this section, +but is preferred to use `features` or `features2` to avoid duplication. # Drawbacks From 244e9a7f031a9e4ed1f4abffdbeb8b980d001a97 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 2 Jul 2023 23:48:49 -0400 Subject: [PATCH 41/45] Clarify doc comment example --- text/3416-feature-metadata.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/text/3416-feature-metadata.md b/text/3416-feature-metadata.md index fd5115fa093..9560d7c5cf1 100644 --- a/text/3416-feature-metadata.md +++ b/text/3416-feature-metadata.md @@ -302,8 +302,10 @@ but is preferred to use `features` or `features2` to avoid duplication. crate (linked below). ```toml - [features] + # RFC proposal foo = { enables = [], doc = "foo feature" } + + # Alternative equivalent using doc comments ## foo feature foo = [] ``` From fcdb26bd81388ada40f146d934c84fd71e899d8a Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 9 Sep 2023 19:25:32 -0400 Subject: [PATCH 42/45] Empty content from this RFC that was moved to one of the others --- text/3416-feature-metadata.md | 312 ++++------------------------------ 1 file changed, 35 insertions(+), 277 deletions(-) diff --git a/text/3416-feature-metadata.md b/text/3416-feature-metadata.md index 9560d7c5cf1..5cedabf4ee5 100644 --- a/text/3416-feature-metadata.md +++ b/text/3416-feature-metadata.md @@ -1,18 +1,18 @@ -- Feature Name: feature-metadata -- Start Date: 2023-04-14 -- 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) +- Feature Name: feature-metadata +- Start Date: 2023-04-14 +- 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 -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 is just meta tracking information for the three following RFCs: -This RFC only describes a new `Cargo.toml` schema; `rustdoc`'s handling of this -information is in a separate RFC. +- [Cargo feature descriptions](https://github.com/rust-lang/rfcs/pull/3485) +- [Cargo feature deprecation](https://github.com/rust-lang/rfcs/pull/3486) +- [Cargo feature visibility](https://github.com/rust-lang/rfcs/pull/3487) # Motivation @@ -24,11 +24,11 @@ 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 +- 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. @@ -61,156 +61,23 @@ This could be a longer description of this feature """ ``` -The following keys would be allowed in a feature table: +The `enables` key is synonymous with the existing array, describing what other +features are enabled by a given feature. For example, +`foo = ["dep:serde", "otherfeat"]` will be identical to +`foo = { enables = ["dep:serde", "otherfeat"] }` -- `enables`: This is synonymous with the existing array describing what - features are enabled by the described feature features. For example, `foo = - ["dep:serde", "otherfeat"]` will be identical to `foo = { enables = - ["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 feature. -- `public`: A boolean flag defaulting to `true` that indicates whether or not - downstream crates should be allowed to use this feature. - -Attempting to use a private feature on a downstream crate will result in -messages like the following: - -``` -error: feature `baz` on crate `mycrate` is private and cannot be used by - downstream crates -``` +All other keys are described in their individual RFCs. # 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 -below sections. - -It is worth noting that none of these keys depend on any others, so they can be -implemented and stabilized individually. - -## `enables` - `enables` will take the place of the feature dependency array that currently exists. Semantics will remain unchanged. This is a required key. If there are no requirements, an empty list should be provided (`enables = []`). This content is already in the index. -## `doc` - -`doc` is the most straightforward: it 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. - -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]. - -## `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: - -- If a boolean value, `false` indicates not deprecated and `true` indicates - deprecated -- If an object, the keys `since` and/or `note` can be specified -- 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 that contains the `note`. This warning should not be -emitted for crates that reexport the feature under a feature also marked -deprecated. For example: crate `foo` exports feature `phooey`, and crate `bar` -exports feature `barred = ["foo/phooey"]`. If `foo` markes `bar` as deprecated, -running any cargo action on `bar` will emit a warning unless `barred` is also -marked `deprecated. - -Accessing this information will require access to the manifest as it will not be -in the index. - -### A note on `since` - -The exact behavior of the `since` key is not provided in this RFC as there are -decisions related to resolution that need to be made. The generally accepted -concept is that there should be a warning if a deprecated feature is used _and_ -there is something actionable to resolve this issue for all downstream crates - -but the details of how best to do this are not yet clear. Please see [discussion -on since]. - -If the exact behavior of `since` does not reach consensus before `deprecated` is -nearing stabilization, this key can stabilized separately or dropped entirely. - -## `public` - -`public` is a boolean value that defaults to `true`. It can be thought of as -`pub` in Rust source files, with the exception of being true by default. If set -to `false`, Cargo should forbid its use with an error message on any downstream -crates. - -The default `true` is not consistent with [`public_private_dependencies`] or -Rust's `pub`, but is a reasonable default to be consistent with the current -behavior so that either `feature = []` or `feature = { "enables" = [] }` will -result in the same configuration. - -The name `public` was chosen in favor of `pub` to be consistent with the -[`public_private_dependencies`] RFC, and to match the existing style of using -non-truncated words as keys. - -In general, marking a feature `public = false` should make tooling treat the -feature as non-public API. This is described as the following: - -- The feature is always usable within the same crate: - - Enablement by other features, e.g. `foo = { enables = - [some-private-feature] }`, is allowed - - Using the feature in integration tests is allowed - - Using the feature in benchmarks is allowed -- The feature should not be accepted by `cargo add --features` -- The feature should not be reported from `cargo add`'s feature output report -- Once `rustdoc` is able to consume feature metadata, `rustdoc` should not - document these features unless `--document-private-items` is specified -- A future tool like `cargo info` shouldn't display information about these - features -- Explicitly specifying the feature via `--features somecrate/private-feature` - will allow enabling a private feature that would otherwise be forbidden - -Attempting to use a private feature in any of the forbidden cases should result -in an error. Exact details of how features work will likely be refined during -implementation and experimentation. - -Two sample use cases for `public = false` include: - -- `docs.rs` having a way to know which features should be hidden -- Features that are included in feature chains (feature `a` enables feature - `b`) but not meant for public consumption could be marked not public - - -This feature requires adjustments to the index for full support. This RFC -proposes that it would be acceptable for the first implementation to simply -strip private features from the manifest; this meanss that there will be no way -to `cfg` based on these features. - -Full support does not need to happen immediately, since it will require this -information be present in the index. [Index changes] describes how this can take -place. - # General Implementation & Usage Use cases for this information will likely develop with time, but one of the @@ -235,159 +102,50 @@ crab@rust foobar % cargo add regex 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. +Features like `aho-corasick`, `memchr`, or `use_std` would likely be +`public = false` since they aren't listed on the crate landing page. ## Implementation note: sort order In general, any tool that renders features (`rustdoc`, `cargo add`) should attempt to present them in the following way: -- Display default features first -- Display non-default but stable features next (can be in a separate section) -- Display deprecated features last (can be in a separate section) -- Do not display private features unless receiving a flag saying to do so (e.g. - `--document-private-items` with `rustdoc`) -- If ordering is not preserved, present the features alphabetically - -## Index changes - -[index changes]: #index-changes - -For features that require new information in the index, it should be possible to -add this information under a `features3` key. Older versions of Cargo will -ignore this key, newer Cargo would be able to merge `features`, `features2`, and -`features3`. `features3` should mirror the most complete syntax of the relevant -keys from the `[features]` table. Currently this is only `deprecated`, i.e.: - -```json5 -"features3": { - "bar": { - deprecated = { since = "1.2.3", note = "don't use this" } - } -} -``` - -In order to conserve index space, default keys should be omitted. `Cargo` should -ignore unrecognized keys within a feature, to allow for future additions without -needing a new `features` section. `enables` may be specified in this section, -but is preferred to use `features` or `features2` to avoid duplication. +- Display default features first +- Display non-default but stable features next (can be in a separate section) +- Display deprecated features last (can be in a separate section) +- Do not display private features unless receiving a flag saying to do so (e.g. + `--document-private-items` with `rustdoc`) +- If ordering is not preserved, present the features alphabetically # Drawbacks [drawbacks]: #drawbacks -- Added complexity to Cargo. Parsing is trivial, but exact implementation - details do add test surface area -- Added Cargo arguments if escape hatches for `public` are created -- Docstrings can be lengthy, adding noise to `Cargo.toml`. This could - potentially be solved with the below mentioned `doc-file` key. -- `public` uses may not be common enough to be worth including -- 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. +- Added complexity to Cargo. Parsing is trivial, but exact implementation + details do add test surface area # 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: -- `docs.rs` displays a feature table, but it is fairly limited. If features - start with `_`, they are hidden from this table. -- Ivy has a [visibility attribute] for its configuration (mentioned in - [cargo #10882]) -- Discussion on stable/unstable/nightly-only features - - # 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. -- Are the semantics of `public` proposed in this RFC suitable? Should private - features be usable in examples or integration tests without a `--features` - argument? -- Should there be a simple `--allow-private-features` flag that allows using - all features, such as for crater runs? This can be decided during - implementation. -- How should `since` work with the `deprecated` key? See - [a note on `since`](#a-note-on-since) for further information. - -It is worth noting that not all of these new keys need to be made available at -once. `enables` needs to be implemented first, but support for all others could -be added over time. - # Future possibilities [future-possibilities]: #future-possibilities -- Rustdoc will gain the ability to document features. This is planned in the - [`rustdoc-cargo-configuration`] RFC. -- Somehow inform users if they are using to-be-deprecated features, i.e., - deprecated `since` is set but is later than the current dependancy version. -- Via the `manifest-lint` RFC, a user could specify that deprecated crates - should be denied. This would, however, be blocked by [cargo #12335]. -- A `stable` field can be set false to indicate API-unstable or nightly-only - features (somethign such as `stable = 3.2` could be used to indicate when a - feature was stabilized). See also: - -- A `rust-version` field that could indicate e.g. `rust-version = "nightly"` - or `rust-version = "1.65"` to specify a MSRV for that feature. See: - -- 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. -- The `public` option could be used to allow optional dev dependencies. See: - -- `cargo add` can show the `doc` and `deprecated` summary with the listed - features. -- [`cargo-info`] can use this information to provide feature descriptions. -- `deprecated` could take a `suggestion` key that indicates features have - moved to a different name (as with the [`deprecated-suggestions`] feature) -- 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" } - ``` +- A `rust-version` field that could indicate e.g. `rust-version = "nightly"` or + `rust-version = "1.65"` to specify a MSRV for that feature. See: + +- `cargo add` can show the `doc` and `deprecated` summary with the listed + features. +- [`cargo-info`] can use this information to provide feature descriptions. [cargo #12335]: https://github.com/rust-lang/cargo/issues/12235 [cargo #10882]: https://github.com/rust-lang/cargo/issues/10882 From f38d7dc4f66719259d3f5a81f83456b754065d75 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 11 Jun 2024 10:14:42 -0500 Subject: [PATCH 43/45] Capture cargo team meeting notes and clean up --- text/3416-feature-metadata.md | 77 ++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/text/3416-feature-metadata.md b/text/3416-feature-metadata.md index 5cedabf4ee5..b29f9bd6a45 100644 --- a/text/3416-feature-metadata.md +++ b/text/3416-feature-metadata.md @@ -8,7 +8,14 @@ [summary]: #summary -This RFC is just meta tracking information for the three following RFCs: +This RFC adds a "detailed" feature definition: +```toml +[features] +# same as `foo = []` +foo = { enables = [] } +``` + +This is to unblock the following RFCs: - [Cargo feature descriptions](https://github.com/rust-lang/rfcs/pull/3485) - [Cargo feature deprecation](https://github.com/rust-lang/rfcs/pull/3486) @@ -68,20 +75,11 @@ features are enabled by a given feature. For example, All other keys are described in their individual RFCs. -# Reference-level explanation +## General Implementation & Usage -[reference-level-explanation]: #reference-level-explanation - -`enables` will take the place of the feature dependency array that currently -exists. Semantics will remain unchanged. - -This is a required key. If there are no requirements, an empty list should be -provided (`enables = []`). This content is already in the index. - -# General Implementation & Usage - -Use cases for this information will likely develop with time, but one of the -simplest applications is for information output with `cargo add`: +Use cases for these new keys will likely develop with time, +but one of the simplest applications is for information output with `cargo +add`: ```text crab@rust foobar % cargo add regex @@ -105,17 +103,23 @@ crab@rust foobar % cargo add regex Features like `aho-corasick`, `memchr`, or `use_std` would likely be `public = false` since they aren't listed on the crate landing page. -## Implementation note: sort order +# Reference-level explanation + +[reference-level-explanation]: #reference-level-explanation + +`enables` will take the place of the feature dependency array that currently +exists. Semantics will remain unchanged. -In general, any tool that renders features (`rustdoc`, `cargo add`) should -attempt to present them in the following way: +This is a required key. If there are no requirements, an empty list should be +provided (`enables = []`). This content is already in the index. -- Display default features first -- Display non-default but stable features next (can be in a separate section) -- Display deprecated features last (can be in a separate section) -- Do not display private features unless receiving a flag saying to do so (e.g. - `--document-private-items` with `rustdoc`) -- If ordering is not preserved, present the features alphabetically +The availability of this new syntax should not require an MSRV bump. +This means we need to make sure that if you use `feature_name = []` in your `Cargo.toml`, +then the published `Cargo.toml` should as well. +However, we leave it as an implementation detail whether using `feature_name = { enables =[] }` +requires an MSRV bump for users of your published package as we have not been +actively streamlining the workflow for maintaining separate development and +published MSRVs. # Drawbacks @@ -128,6 +132,23 @@ attempt to present them in the following way: [rationale-and-alternatives]: #rationale-and-alternatives +This RFC has no impact on the Index Summaries. +Future RFCs will need to work with that. + +## Naming + +- `enables` reads better on the line than `enable` +- `enables` is likely an easier word for non-native speakers than `activates` +- `required` is used elsewhere to say "this should automatically be available if requirements are met" + +## Schema + +We could split the special feature syntax (`dep:`, etc) as distinct fields +but we'd prefer trivial conversion from the "simple" schema to the "detailed" schema, +like `dependencies`. +However, we likely would want to prefer using new fields over adding more syntax, +like with [disabling default features](https://github.com/rust-lang/cargo/issues/3126). + # Prior art [prior-art]: #prior-art @@ -140,12 +161,10 @@ attempt to present them in the following way: [future-possibilities]: #future-possibilities -- A `rust-version` field that could indicate e.g. `rust-version = "nightly"` or - `rust-version = "1.65"` to specify a MSRV for that feature. See: - -- `cargo add` can show the `doc` and `deprecated` summary with the listed - features. -- [`cargo-info`] can use this information to provide feature descriptions. +- [Cargo feature descriptions](https://github.com/rust-lang/rfcs/pull/3485) +- [Cargo feature deprecation](https://github.com/rust-lang/rfcs/pull/3486) +- [Cargo feature visibility](https://github.com/rust-lang/rfcs/pull/3487) +- [Cargo feature stability](https://github.com/rust-lang/cargo/issues/10881) [cargo #12335]: https://github.com/rust-lang/cargo/issues/12235 [cargo #10882]: https://github.com/rust-lang/cargo/issues/10882 From 69026e14d3a9959cc22ea480d18fd1441f05d280 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 11 Jun 2024 10:16:41 -0500 Subject: [PATCH 44/45] Call out impact to third party parsers --- text/3416-feature-metadata.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/text/3416-feature-metadata.md b/text/3416-feature-metadata.md index b29f9bd6a45..712c41d46cf 100644 --- a/text/3416-feature-metadata.md +++ b/text/3416-feature-metadata.md @@ -127,6 +127,8 @@ published MSRVs. - Added complexity to Cargo. Parsing is trivial, but exact implementation details do add test surface area +- Extending the `Cargo.toml` schema, particularly having a field support + additional types, is disruptive to third-party parsers # Rationale and alternatives From a8c6163ff414a0a895324dc2e507838d45abcb89 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 26 Jun 2024 21:36:24 -0500 Subject: [PATCH 45/45] Add tracking issue --- text/3416-feature-metadata.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/3416-feature-metadata.md b/text/3416-feature-metadata.md index 712c41d46cf..ba34ec79a65 100644 --- a/text/3416-feature-metadata.md +++ b/text/3416-feature-metadata.md @@ -2,7 +2,7 @@ - Start Date: 2023-04-14 - 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) + [rust-lang/cargo#13576](https://github.com/rust-lang/cargo/issues/13576) # Summary