1
- - Feature Name: feature-metadata
2
- - Start Date: 2023-04-14
3
- - RFC PR: [ rust-lang/rfcs #3416 ] ( https://github.com/rust-lang/rfcs/pull/3416 )
4
- - Rust Issue: [ rust-lang/rust #0000 ] ( https://github.com/rust-lang/rust/issues/0000 )
1
+ - Feature Name: feature-metadata
2
+ - Start Date: 2023-04-14
3
+ - RFC PR: [ rust-lang/rfcs #3416 ] ( https://github.com/rust-lang/rfcs/pull/3416 )
4
+ - Rust Issue:
5
+ [ rust-lang/rust #0000 ] ( https://github.com/rust-lang/rust/issues/0000 )
5
6
6
7
# Summary
7
8
8
9
[ summary ] : #summary
9
10
10
- The main purpose of this RFC is to define a structured way to add attributes to
11
- features, including documentation (mostly for ` rustdoc ` ), visibility,
12
- deprecation status, and stability.
11
+ This RFC is just meta tracking information for the three following RFCs:
13
12
14
- This RFC only describes a new ` Cargo.toml ` schema; ` rustdoc ` 's handling of this
15
- information is in a separate RFC.
13
+ - [ Cargo feature descriptions] ( https://github.com/rust-lang/rfcs/pull/3485 )
14
+ - [ Cargo feature deprecation] ( https://github.com/rust-lang/rfcs/pull/3486 )
15
+ - [ Cargo feature visibility] ( https://github.com/rust-lang/rfcs/pull/3487 )
16
16
17
17
# Motivation
18
18
@@ -24,11 +24,11 @@ common that many larger crates wind up with tens of feature gates, such as
24
24
[ ` tokio ` ] with 24. Despite being a first class component of crate structure,
25
25
there are some limitations that don't have elegant solutions:
26
26
27
- - Documentation is difficult, often requiring library authors to manually manage
28
- a table of descriptions
29
- - There is no way to deprecate old features, as a way to help crates maintain
30
- semvar compliance
31
- - Features cannot be hidden from use in any way
27
+ - Documentation is difficult, often requiring library authors to manually manage
28
+ a table of descriptions
29
+ - There is no way to deprecate old features, as a way to help crates maintain
30
+ semvar compliance
31
+ - Features cannot be hidden from use in any way
32
32
33
33
This RFC proposes a plan that add that information to ` Cargo.toml ` , solving
34
34
these problems.
@@ -61,156 +61,23 @@ This could be a longer description of this feature
61
61
"""
62
62
```
63
63
64
- The following keys would be allowed in a feature table:
64
+ The ` enables ` key is synonymous with the existing array, describing what other
65
+ features are enabled by a given feature. For example,
66
+ ` foo = ["dep:serde", "otherfeat"] ` will be identical to
67
+ ` foo = { enables = ["dep:serde", "otherfeat"] } `
65
68
66
- - ` enables ` : This is synonymous with the existing array describing what
67
- features are enabled by the described feature features. For example, `foo =
68
- [ "dep: serde ", "otherfeat"] ` will be identical to ` foo = { enables =
69
- [ "dep: serde ", "otherfeat"] }`
70
- - ` doc ` : A markdown docstring describing the feature. Like with ` #[doc(...)] ` ,
71
- the first line will be treated as a summary.
72
- - ` deprecated ` : This can be either a simple boolean, a string, or an object
73
- with ` since ` and/or ` note ` keys. Cargo will warn downstream crates using
74
- this feature.
75
- - ` public ` : A boolean flag defaulting to ` true ` that indicates whether or not
76
- downstream crates should be allowed to use this feature.
77
-
78
- Attempting to use a private feature on a downstream crate will result in
79
- messages like the following:
80
-
81
- ```
82
- error: feature `baz` on crate `mycrate` is private and cannot be used by
83
- downstream crates
84
- ```
69
+ All other keys are described in their individual RFCs.
85
70
86
71
# Reference-level explanation
87
72
88
73
[ reference-level-explanation ] : #reference-level-explanation
89
74
90
- Validation and parsing of the new schema, described above, shoud be relatively
91
- straightforward. Each of the added keys is discussed individually in the
92
- below sections.
93
-
94
- It is worth noting that none of these keys depend on any others, so they can be
95
- implemented and stabilized individually.
96
-
97
- ## ` enables `
98
-
99
75
` enables ` will take the place of the feature dependency array that currently
100
76
exists. Semantics will remain unchanged.
101
77
102
78
This is a required key. If there are no requirements, an empty list should be
103
79
provided (` enables = [] ` ). This content is already in the index.
104
80
105
- ## ` doc `
106
-
107
- ` doc ` is the most straightforward: it accepts markdown-flavored text, and should
108
- be thought of as the equivalent to a ` #[doc(...)] ` attribute. Like doc comments,
109
- the first line should be treated as a summary. Intra-doc link support is not
110
- included in this RFC, so they should not be used.
111
-
112
- There is nothing in this RFC that cargo ` must ` do with this action, since it is
113
- mainly intended for the consumption of ` rustdoc ` or ` docs.rs ` . However, it can
114
- be used for general diagnostic information such as during ` cargo add ` or
115
- a possible ` cargo info ` command.
116
-
117
- Any tools that want the information in ` doc ` will require access to the
118
- manifest. Adding this information to the index was decided against due to
119
- concerns about bloat, but this is further discussed in
120
- [ future possibilities] [ future-possibilities ] .
121
-
122
- ## ` deprecated `
123
-
124
- ` deprecated ` should be thought of as the equivalent of the [ ` deprecated ` ]
125
- attribute in Rust source. The value can be a boolean, string, or an object with
126
- ` since ` or ` note ` keys. Schema rules are as follows:
127
-
128
- - If a boolean value, ` false ` indicates not deprecated and ` true ` indicates
129
- deprecated
130
- - If an object, the keys ` since ` and/or ` note ` can be specified
131
- - An empty object is not allowed to avoid the ambiguous
132
- ` foo = { deprecated = {} } `
133
- - A string ` foo = { deprecated = "my msg" } ` will be equivalent to if that string
134
- was specified in the ` note ` field:
135
- ` foo = { deprecated = { note = "my msg" } } `
136
- - If not specified, the default is ` false `
137
-
138
- If a downstream crate attempts to use a feature marked ` deprecated ` , Cargo
139
- should produce a warning that contains the ` note ` . This warning should not be
140
- emitted for crates that reexport the feature under a feature also marked
141
- deprecated. For example: crate ` foo ` exports feature ` phooey ` , and crate ` bar `
142
- exports feature ` barred = ["foo/phooey"] ` . If ` foo ` markes ` bar ` as deprecated,
143
- running any cargo action on ` bar ` will emit a warning unless ` barred ` is also
144
- marked `deprecated.
145
-
146
- Accessing this information will require access to the manifest as it will not be
147
- in the index.
148
-
149
- ### A note on ` since `
150
-
151
- The exact behavior of the ` since ` key is not provided in this RFC as there are
152
- decisions related to resolution that need to be made. The generally accepted
153
- concept is that there should be a warning if a deprecated feature is used _ and_
154
- there is something actionable to resolve this issue for all downstream crates -
155
- but the details of how best to do this are not yet clear. Please see [ discussion
156
- on since] .
157
-
158
- If the exact behavior of ` since ` does not reach consensus before ` deprecated ` is
159
- nearing stabilization, this key can stabilized separately or dropped entirely.
160
-
161
- ## ` public `
162
-
163
- ` public ` is a boolean value that defaults to ` true ` . It can be thought of as
164
- ` pub ` in Rust source files, with the exception of being true by default. If set
165
- to ` false ` , Cargo should forbid its use with an error message on any downstream
166
- crates.
167
-
168
- The default ` true ` is not consistent with [ ` public_private_dependencies ` ] or
169
- Rust's ` pub ` , but is a reasonable default to be consistent with the current
170
- behavior so that either ` feature = [] ` or ` feature = { "enables" = [] } ` will
171
- result in the same configuration.
172
-
173
- The name ` public ` was chosen in favor of ` pub ` to be consistent with the
174
- [ ` public_private_dependencies ` ] RFC, and to match the existing style of using
175
- non-truncated words as keys.
176
-
177
- In general, marking a feature ` public = false ` should make tooling treat the
178
- feature as non-public API. This is described as the following:
179
-
180
- - The feature is always usable within the same crate:
181
- - Enablement by other features, e.g. `foo = { enables =
182
- [ some-private-feature] }`, is allowed
183
- - Using the feature in integration tests is allowed
184
- - Using the feature in benchmarks is allowed
185
- - The feature should not be accepted by ` cargo add --features `
186
- - The feature should not be reported from ` cargo add ` 's feature output report
187
- - Once ` rustdoc ` is able to consume feature metadata, ` rustdoc ` should not
188
- document these features unless ` --document-private-items ` is specified
189
- - A future tool like ` cargo info ` shouldn't display information about these
190
- features
191
- - Explicitly specifying the feature via ` --features somecrate/private-feature `
192
- will allow enabling a private feature that would otherwise be forbidden
193
-
194
- Attempting to use a private feature in any of the forbidden cases should result
195
- in an error. Exact details of how features work will likely be refined during
196
- implementation and experimentation.
197
-
198
- Two sample use cases for ` public = false ` include:
199
-
200
- - ` docs.rs ` having a way to know which features should be hidden
201
- - Features that are included in feature chains (feature ` a ` enables feature
202
- ` b ` ) but not meant for public consumption could be marked not public
203
-
204
-
205
- This feature requires adjustments to the index for full support. This RFC
206
- proposes that it would be acceptable for the first implementation to simply
207
- strip private features from the manifest; this meanss that there will be no way
208
- to ` cfg ` based on these features.
209
-
210
- Full support does not need to happen immediately, since it will require this
211
- information be present in the index. [ Index changes] describes how this can take
212
- place.
213
-
214
81
# General Implementation & Usage
215
82
216
83
Use cases for this information will likely develop with time, but one of the
@@ -235,159 +102,50 @@ crab@rust foobar % cargo add regex
235
102
Updating crates.io index
236
103
```
237
104
238
- Features like ` aho-corasick ` , ` memchr ` , or ` use_std ` would likely be `public =
239
- false` since they aren't listed on the crate landing page.
105
+ Features like ` aho-corasick ` , ` memchr ` , or ` use_std ` would likely be
106
+ ` public = false` since they aren't listed on the crate landing page.
240
107
241
108
## Implementation note: sort order
242
109
243
110
In general, any tool that renders features (` rustdoc ` , ` cargo add ` ) should
244
111
attempt to present them in the following way:
245
112
246
- - Display default features first
247
- - Display non-default but stable features next (can be in a separate section)
248
- - Display deprecated features last (can be in a separate section)
249
- - Do not display private features unless receiving a flag saying to do so (e.g.
250
- ` --document-private-items ` with ` rustdoc ` )
251
- - If ordering is not preserved, present the features alphabetically
252
-
253
- ## Index changes
254
-
255
- [ index changes ] : #index-changes
256
-
257
- For features that require new information in the index, it should be possible to
258
- add this information under a ` features3 ` key. Older versions of Cargo will
259
- ignore this key, newer Cargo would be able to merge ` features ` , ` features2 ` , and
260
- ` features3 ` . ` features3 ` should mirror the most complete syntax of the relevant
261
- keys from the ` [features] ` table. Currently this is only ` deprecated ` , i.e.:
262
-
263
- ``` json5
264
- " features3" : {
265
- " bar" : {
266
- deprecated = { since = " 1.2.3" , note = " don't use this" }
267
- }
268
- }
269
- ```
270
-
271
- In order to conserve index space, default keys should be omitted. ` Cargo ` should
272
- ignore unrecognized keys within a feature, to allow for future additions without
273
- needing a new ` features ` section. ` enables ` may be specified in this section,
274
- but is preferred to use ` features ` or ` features2 ` to avoid duplication.
113
+ - Display default features first
114
+ - Display non-default but stable features next (can be in a separate section)
115
+ - Display deprecated features last (can be in a separate section)
116
+ - Do not display private features unless receiving a flag saying to do so (e.g.
117
+ ` --document-private-items ` with ` rustdoc ` )
118
+ - If ordering is not preserved, present the features alphabetically
275
119
276
120
# Drawbacks
277
121
278
122
[ drawbacks ] : #drawbacks
279
123
280
- - Added complexity to Cargo. Parsing is trivial, but exact implementation
281
- details do add test surface area
282
- - Added Cargo arguments if escape hatches for ` public ` are created
283
- - Docstrings can be lengthy, adding noise to ` Cargo.toml ` . This could
284
- potentially be solved with the below mentioned ` doc-file ` key.
285
- - ` public ` uses may not be common enough to be worth including
286
- - A markdown parser is required to properly parse the ` doc ` field.
287
- - When rendering features in documentation, this RFC does not specify any way
288
- for ` rustdoc ` to get the information it requires. This will require separate
289
- design work.
290
- - There is no way to structure features in a way that they are split into
291
- sections or have a user-specified layout, unlike with the
292
- ` document-features ` crate.
293
- - Features cannot be ordered since the TOML specification does not allow it.
124
+ - Added complexity to Cargo. Parsing is trivial, but exact implementation
125
+ details do add test surface area
294
126
295
127
# Rationale and alternatives
296
128
297
129
[ rationale-and-alternatives ] : #rationale-and-alternatives
298
130
299
- - Feature descriptions could be specified somewhere in Rust source files. This
300
- has the downside of creating multiple sources of truth on features.
301
- - Cargo could parse doc comments in ` Cargo.toml ` , like the ` document-features `
302
- crate (linked below).
303
-
304
- ``` toml
305
- # RFC proposal
306
- foo = { enables = [], doc = " foo feature" }
307
-
308
- # Alternative equivalent using doc comments
309
- # # foo feature
310
- foo = []
311
- ```
312
-
313
- This was decided against as part of this RFC because it would mean that
314
- TOML-compliant parsers (including anything `serde`-based) would be
315
- insufficient to extract all information in the manifest, requiring custom
316
- deserialization of the fields via a format-preserving parser. This differs
317
- from documentation in Rust source as the doc-comment behavior is described
318
- specified within the grammar with parsers supporting extracting those
319
- elements.
320
-
321
131
# Prior art
322
132
323
133
[ prior-art ] : #prior-art
324
134
325
- - There is an existing crate that uses TOML comments to create a features
326
- table: <https://docs.rs/document-features/latest/document_features/>
327
- - `docs.rs` displays a feature table, but it is fairly limited. If features
328
- start with `_`, they are hidden from this table.
329
- - Ivy has a [visibility attribute] for its configuration (mentioned in
330
- [cargo #10882 ])
331
- - Discussion on stable/unstable/nightly-only features
332
- <https://github.com/rust-lang/cargo/issues/10881>
333
-
334
135
# Unresolved questions
335
136
336
137
[ unresolved-questions ] : #unresolved-questions
337
138
338
- - Rather than being consistent with `rustdoc` and accepting markdown, should
339
- the `doc` key be consistent with `package.description` and only support
340
- plain text? This RFC proposes making this decision at time of
341
- implementation, the challenges of supporting markdown are better understood.
342
- - Are the semantics of `public` proposed in this RFC suitable? Should private
343
- features be usable in examples or integration tests without a `--features`
344
- argument?
345
- - Should there be a simple `--allow-private-features` flag that allows using
346
- all features, such as for crater runs? This can be decided during
347
- implementation.
348
- - How should `since` work with the `deprecated` key? See
349
- [a note on `since` ](#a-note-on-since) for further information.
350
-
351
- It is worth noting that not all of these new keys need to be made available at
352
- once. `enables` needs to be implemented first, but support for all others could
353
- be added over time.
354
-
355
139
# Future possibilities
356
140
357
141
[ future-possibilities ] : #future-possibilities
358
142
359
- - Rustdoc will gain the ability to document features. This is planned in the
360
- [`rustdoc-cargo-configuration` ] RFC.
361
- - Somehow inform users if they are using to-be-deprecated features, i.e.,
362
- deprecated `since` is set but is later than the current dependancy version.
363
- - Via the `manifest-lint` RFC, a user could specify that deprecated crates
364
- should be denied. This would, however, be blocked by [cargo # 12335].
365
- - A `stable` field can be set false to indicate API-unstable or nightly-only
366
- features (somethign such as `stable = 3.2` could be used to indicate when a
367
- feature was stabilized). See also:
368
- <https://github.com/rust-lang/cargo/issues/10882>
369
- - A `rust-version` field that could indicate e.g. `rust-version = "nightly"`
370
- or `rust-version = "1.65"` to specify a MSRV for that feature. See:
371
- <https://github.com/rust-lang/rfcs/pull/3416#discussion_r1174478461>
372
- - At some point, the decision to not include `doc` in the index could be
373
- reevaluated. Including only the first (summary) line of `doc` could be a
374
- possibility.
375
- - The `public` option could be used to allow optional dev dependencies. See:
376
- <https://github.com/rust-lang/cargo/issues/1596>
377
- - `cargo add` can show the `doc` and `deprecated` summary with the listed
378
- features.
379
- - [`cargo-info`] can use this information to provide feature descriptions.
380
- - `deprecated` could take a `suggestion` key that indicates features have
381
- moved to a different name (as with the [`deprecated-suggestions`] feature)
382
- - Feature documentation could be allowed in a separate markdown file. For
383
- convenience, markdown anchors could be used to specify a section, so
384
- multiple features can share the same file. This could be a good option for
385
- features requiring long descriptions.
386
-
387
- ```toml
388
- foo = { enables = [], doc-file = " features.md#foo" }
389
- bar = { enables = [], doc-file = " features.md#bar" }
390
- ```
143
+ - A ` rust-version ` field that could indicate e.g. ` rust-version = "nightly" ` or
144
+ ` rust-version = "1.65" ` to specify a MSRV for that feature. See:
145
+ < https://github.com/rust-lang/rfcs/pull/3416#discussion_r1174478461 >
146
+ - ` cargo add ` can show the ` doc ` and ` deprecated ` summary with the listed
147
+ features.
148
+ - [ ` cargo-info ` ] can use this information to provide feature descriptions.
391
149
392
150
[ cargo #12335 ] : https://github.com/rust-lang/cargo/issues/12235
393
151
[ cargo #10882 ] : https://github.com/rust-lang/cargo/issues/10882
0 commit comments