Summary
Add a scheduled_removal
paramter to the deprecated
attribute, to allow library authors to specify when a deprecated item is scheduled to be removed.
Motivation
Currently, library authors can specify when an item is deprecated via the since
parameter. However, when these deprecated items are removed, it is often confusing to some library users as to why a portion of the public API is removed, without noticing that it has been already deprecated. Users may not be aware that certain items have become deprecated, but even if they notice, they may not migrate to something else immediately. When the deprecated items do get removed, it is then difficult for users to migrate to another API. Removal of APIs can be sudden, and users are usually not prepared for sudden removal of deprecated items.
Having a scheduled_removal
attribute, that specifies the version of which a deprecated item is removed would mean users obtain the information of when the deprecated item will be removed from the public API and hence can prepare or complete for the migration beforehand.
Guilde-level Explanation
This Pre-RFC proposes the addition of the scheduled_removal
parameter to the deprecated
attribute, as with the following example, when a version is specified:
#[deprecated(since = "0.2.1", scheduled_removal = "0.3.0")]
struct ThisItemIsDeprecated;
Usages of this struct would result in the following warning:
warning: use of deprecated unit struct `ThisItemIsDeprecated`
--> src/main.rs:5:17
|
5 | let _ = ThisItemIsDeprecated;
| ^^^^^^^^^^^^^^^^^^^^
|
= note: this deprecated unit struct will be removed in version 0.3.0
= note: `#[warn(deprecated)]` on by default
The added line note: this deprecated item will be removed in version 0.3.0
tells the user this deprecated item will be removed in version 0.3.0
and would make it clear that the user needs to migrate to another API before 0.3.0
lands, otherwise their code would break and fail to compile due to the removal of the API.
If no value is provided for the scheduled_removal
parameter, like so:
#[deprecated(since = "0.2.1", scheduled_removal)]
struct ThisItemIsDeprecated;
Then theu sages of this struct would result in the following warning:
warning: use of deprecated unit struct `ThisItemIsDeprecated`
--> src/main.rs:5:17
|
5 | let _ = ThisItemIsDeprecated;
| ^^^^^^^^^^^^^^^^^^^^
|
= note: this deprecated unit struct will be removed in a future version
= note: `#[warn(deprecated)]` on by default
The second case is particularly useful - while knowing the version in which the item will be removed is a good thing for the library users, always requiring to put a version is troublesome, as putting a specific version then forces the maintainer to remove those items in that specific version.
Reference-level Explanation
The scheduled_removal
parameter optionally takes in a &str
value, signifying the version for which the deprecated item is scheduled to be removed.
The compiler takes this parameter into account when generating diagnostics for usages of an item marked as #[deprecated]
using this parameter.
If a version is provided, the compiler will append a note
line that reads: this deprecated {item_type} will be removed in version {version}
, where {item type}
is the type of item
used, like a unit struct
in this example, and the {version}
being the version specified as the value to the scheduled_removal
parameter. Otherwise, the appended note line would read like this deprecated {item_type} will be removed in a future version
,
Drawbacks
None.
Rationale and alternatives
A separate scheduled_for_removal
attribute
A separate attribute named scheduled_for_removal
will be introduced. Usage of this attribute looks like, when a version is provided:
#[deprecated(since = "0.2.1")]
#[scheduled_for_removal(at = "0.3.0")]
struct ThisItemIsDeprecated;
Which would result in the following warning:
warning: use of unit struct `ThisItemIsDeprecated` that is scheduled for removal
--> src/main.rs:5:17
|
5 | let _ = ThisItemIsDeprecated;
| ^^^^^^^^^^^^^^^^^^^^
|
= note: this unit struct will be removed in version 0.3.0
= note: `#[warn(scheduled_for_removal)]` on by default
When a version is not specified:
#[deprecated(since = "0.2.1")]
#[scheduled_for_removal]
struct ThisItemIsDeprecated;
Which would result in the following warning:
warning: use of unit struct `ThisItemIsDeprecated` that is scheduled for removal
--> src/main.rs:5:17
|
5 | let _ = ThisItemIsDeprecated;
| ^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(scheduled_for_removal)]` on by default
The scheduled_for_removal
lint would be introduced alongside with this attribute.
This was briefly considered but ultimately personally vetoed because another attribute is quite some work, and it is like an extension to the deprecated
attribute - describing when will this item will be removed. Hence, adding the scheduled_removal
parameter is preferred hence this proposal is based
on a new parameter rather than a new attribute.
Prior art
- The JetBrains Annotations Java package has a similar annotation:
@ApiStatus.ScheduledForRemoval
, which allows the library author to specify when an API will be removed from the public API entirely, and is mostly the inspiration for this Pre-RFC. - The
@Deprecated
attribute from the Java standard library, which has the boolean parameterforRemoval
, it is used to specify whether the deprecated item will be removed in a future version - albeit a bit vague (as it does not allow you to specify which version would the item be removed).
Unresolved questions
- How should this new attribute be named? (Albeit
scheduled_removal
sounds kind of weird to me, it is the currently the best name after discussion on Rust Internals). - How should the diagnostics be updated to accommodate for this? Currently, simply a
note
line is added. Is that good enough?
Future possibilities
Other API status attributes can be exposed to library authors, for example experimental
to mark experimental APIs and emit corresponding warnings to the
user about the usage of an unstable and experimental API of the library, that the code may break at any time without prior notice.