- Feature Name: Public Stability
- Start Date: 2015-09-03
- RFC PR: rust-lang/rfcs#1270
- Rust Issue: rust-lang/rust#29935
Summary
This RFC proposes to allow library authors to use a #[deprecated]
attribute,
with optional since = "
version"
and note = "
free text"
fields. The
compiler can then warn on deprecated items, while rustdoc
can document their
deprecation accordingly.
Motivation
Library authors want a way to evolve their APIs; which also involves deprecating items. To do this cleanly, they need to document their intentions and give their users enough time to react.
Currently there is no support from the language for this oft-wanted feature (despite a similar feature existing for the sole purpose of evolving the Rust standard library). This RFC aims to rectify that, while giving a pleasant interface to use while maximizing usefulness of the metadata introduced.
Detailed design
Public API items (both plain fn
s, methods, trait- and inherent
impl
ementations as well as const
definitions, type definitions, struct
fields and enum variants) can be given a #[deprecated]
attribute. All
possible fields are optional:
since
is defined to contain the version of the crate at the time of deprecating the item, following the semver scheme. Rustc does not know about versions, thus the content of this field is not checked (but will be by external lints, e.g. rust-clippy.note
should contain a human-readable string outlining the reason for deprecating the item and/or what to use instead. While this field is not required, library authors are strongly advised to make use of it. The string is interpreted as plain unformatted text (for now) so that rustdoc can include it in the item’s documentation without messing up the formatting.
On use of a deprecated item, rustc
will warn
of the deprecation. Note
that during Cargo builds, warnings on dependencies get silenced. While this has
the upside of keeping things tidy, it has a downside when it comes to
deprecation:
Let’s say I have my llogiq
crate that depends on foobar
which uses a
deprecated item of serde
. I will never get the warning about this unless I
try to build foobar
directly. We may want to create a service like crater
to warn on use of deprecated items in library crates, however this is outside
the scope of this RFC.
rustdoc
will show deprecation on items, with a [deprecated]
box that may
optionally show the version and note where available.
The language reference will be extended to describe this feature as outlined in this RFC. Authors shall be advised to leave their users enough time to react before removing a deprecated item.
The internally used feature can either be subsumed by this or possibly renamed to avoid a name clash.
Intended Use
Crate author Anna wants to evolve her crate’s API. She has found that one
type, Foo
, has a better implementation in the rust-foo
crate. Also she has
written a frob(Foo)
function to replace the earlier Foo::frobnicate(self)
method.
So Anna first bumps the version of her crate (because deprecation is always
done on a version change) from 0.1.1
to 0.2.1
. She also adds the following
prefix to the Foo
type:
extern crate rust_foo;
#[deprecated(since = "0.2.1",
note="The rust_foo version is more advanced, and this crate's will likely be discontinued")]
struct Foo { .. }
Users of her crate will see the following once they cargo update
and build
:
src/foo_use.rs:27:5: 27:8 warning: Foo is marked deprecated as of version 0.2.1
src/foo_use.rs:27:5: 27:8 note: The rust_foo version is more advanced, and this crate's will likely be discontinued
Rust-clippy will likely gain more sophisticated checks for deprecation:
future_deprecation
will warn on items marked as deprecated, but with a version lower than their crates’, whilecurrent_deprecation
will warn only on those items marked as deprecated where the version is equal or lower to the crates’ one.deprecation_syntax
will check that thesince
field really contains a semver number and not some random string.
Clippy users can then activate the clippy checks and deactivate the standard deprecation checks.
Drawbacks
- Once the feature is public, we can no longer change its design
Alternatives
- Do nothing
- make the
since
field required and check that it’s a single version - require either
reason
oruse
be present reason
could include markdown formatting- rename the
reason
field tonote
to clarify its broader usage. (done!) - add a
note
field and makereason
a field with specific meaning, perhaps even predefine a number of valid reason strings, as JEP277 currently does - Add a
use
field containing a plain text of what to use instead - Add a
use
field containing a path to some function, type, etc. to replace the current feature. Currently with the rustc-private feature, people are describing a replacement in thereason
field, which is clearly not the original intention of the field - Optionally,
cargo
could offer a new dependency category: “doc-dependencies” which are used to pull in other crates’ documentations to link them (this is obviously not only relevant to deprecation)
Unresolved questions
- What other restrictions should we introduce now to avoid being bound to a possibly flawed design?
- Can / Should the
std
library make use of the#[deprecated]
extensions? - Bikeshedding: Are the names good enough?