Summary
This RFC describes a new key under features in Cargo.toml to indicate that a
feature is deprecated.
Please see the parent meta RFC for background information: feature-metadata.
Motivation
Cargo features are widely used and typically have lifecycles the same as other
API components. There is not currently a way to indicate that a feature is
intended for removal and warn about it: This RFC proposes a deprecated key
that shows this information.
Guide-level explanation
A new deprecated key will be allowed for features, defaulting to false if
not specified. If specified, the value can be either a boolean, a string, or an
object with since and/or note keys. Cargo will warn downstream crates using
this feature.
[features]
foo = { enables = [], deprecated = true }
foo = { enables = [], deprecated = "this works as a note" }
bar = { enables = [], deprecated = { since = "1.2.3", note = "don't use this!" } }
See feature-metadata for information about enables.
Reference-level explanation
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,
falseindicates not deprecated andtrueindicates deprecated - If an object, the keys
sinceand/ornotecan be specified- An empty object is not allowed to avoid ambiguity
foo = { deprecated = {} }
- An empty object is not allowed to avoid ambiguity
- If a string (e.g.
foo = { deprecated = "my msg" }), it will be equivalent to if that string was specified in thenotefield (e.g.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 phooey 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.
Index changes
The infromation provided by deprecated needs to be stored in the index, and
will be stored 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, i.e.:
"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.
Drawbacks
- Added complexity to Cargo. Parsing is trivial, but exact implementation details do add test surface area
Rationale and alternatives
WIP
Prior art
WIP
Unresolved questions
- How should
sincework with thedeprecatedkey? See a note onsincefor further information.
Future possibilities
- Somehow inform users if they are using to-be-deprecated features, i.e.,
deprecated
sinceis set but is later than the current dependancy version. - Via the
manifest-lintRFC, a user could specify that deprecated crates should be denied. This would, however, be blocked by cargo #12335. - A
stablefield can be set false to indicate API-unstable or nightly-only features (something such asstable = 3.2could be used to indicate when a feature was stabilized). See also: https://github.com/rust-lang/cargo/issues/10882 - A
rust-versionfield that could indicate e.g.rust-version = "nightly"orrust-version = "1.65"to specify a MSRV for that feature. See: https://github.com/rust-lang/rfcs/pull/3416#discussion_r1174478461 cargo addcan show thedeprecatedsummary with the listed features.deprecatedcould take asuggestionkey that indicates features have moved to a different name (as with thedeprecated-suggestionsfeature)