Attributes and Conditional Compilation
#[deprecated]
#[deprecated] marks a public or internal item (function, method, struct, enum, variant, field, trait, constant, type alias, or module) as superseded, causing the compiler to emit a deprecated warning diagnostic whenever caller code references the item and adding a prominent deprecation banner in generated rustdoc HTML documentation.
Syntactic Forms of #[deprecated]
// 1. Bare attribute:
#[deprecated]
// 2. Shorthand message string:
#[deprecated = "use `connect_with_timeout` instead"]
// 3. Structured `since` version + `note` migration guide (Recommended):
#[deprecated(since = "1.4.0", note = "use `Client::builder()` instead")]
| Field | Purpose | Best Practice |
|---|---|---|
since = "X.Y.Z" |
Records the exact crate version in which the item was deprecated (or "TBD" if slated for next release) |
Allows callers to plan upgrades across semver versions |
note = "..." |
Explains why the item was deprecated and names the exact replacement function or type | Include backticks around the replacement path (use \new_fn` instead`) |
Deprecating Legacy APIs While Calling Them Internally Without Warnings
Inside the implementation of a deprecated function (or inside backwards-compatibility unit tests that verify the deprecated function still works), place #[allow(deprecated)] on the test or forwarding block so your own crate compiles with zero warnings while external callers still see the deprecation warning:
pub struct Connection {
pub endpoint: String,
}
impl Connection {
#[deprecated(
since = "0.2.0",
note = "use `Connection::connect(url)` instead; `open` will be removed in 1.0"
)]
pub fn open(url: &str) -> Self {
Self::connect(url)
}
pub fn connect(url: &str) -> Self {
Self {
endpoint: url.to_string(),
}
}
}
#[allow(deprecated, reason = "Testing backwards-compatible deprecated wrapper")]
fn verify_legacy_open() -> Connection {
Connection::open("https://api.example.com")
}
fn main() {
let modern = Connection::connect("https://modern.example.com");
let legacy = verify_legacy_open();
println!("modern: {}, legacy: {}", modern.endpoint, legacy.endpoint);
}
modern: https://modern.example.com, legacy: https://api.example.com
When a caller without #[allow(deprecated)] calls Connection::open(...), the compiler prints:
warning: use of deprecated associated function `Connection::open`: use `Connection::connect(url)` instead; `open` will be removed in 1.0
--> src/main.rs:28:18
|
28 | let legacy = Connection::open("https://api.example.com");
| ^^^^^^^^^^^^^^^^
|
= note: `#[warn(deprecated)]` on by default