| # Stability attributes |
| |
| <!-- toc --> |
| |
| This section is about the stability attributes and schemes that allow stable |
| APIs to use unstable APIs internally in the rustc standard library. |
| |
| For instructions on stabilizing a language feature see [Stabilizing |
| Features](./stabilization_guide.md). |
| |
| ## unstable |
| |
| The `#[unstable(feature = "foo", issue = "1234", reason = "lorem ipsum")]` |
| attribute explicitly marks an item as unstable. Items that are marked as |
| "unstable" cannot be used without a corresponding `#![feature]` attribute on |
| the crate, even on a nightly compiler. This restriction only applies across |
| crate boundaries, unstable items may be used within the crate that defines |
| them. |
| |
| The `issue` field specifies the associated GitHub [issue number]. This field is |
| required and all unstable features should have an associated tracking issue. In |
| rare cases where there is no sensible value `issue = "none"` is used. |
| |
| The `unstable` attribute infects all sub-items, where the attribute doesn't |
| have to be reapplied. So if you apply this to a module, all items in the module |
| will be unstable. |
| |
| You can make specific sub-items stable by using the `#[stable]` attribute on |
| them. The stability scheme works similarly to how `pub` works. You can have |
| public functions of nonpublic modules and you can have stable functions in |
| unstable modules or vice versa. |
| |
| Note, however, that due to a [rustc bug], stable items inside unstable modules |
| *are* available to stable code in that location! So, for example, stable code |
| can import `core::intrinsics::transmute` even though `intrinsics` is an |
| unstable module. Thus, this kind of nesting should be avoided when possible. |
| |
| The `unstable` attribute may also have the `soft` value, which makes it a |
| future-incompatible deny-by-default lint instead of a hard error. This is used |
| by the `bench` attribute which was accidentally accepted in the past. This |
| prevents breaking dependencies by leveraging Cargo's lint capping. |
| |
| [issue number]: https://github.com/rust-lang/rust/issues |
| [rustc bug]: https://github.com/rust-lang/rust/issues/15702 |
| |
| ## stable |
| The `#[stable(feature = "foo", "since = "1.420.69")]` attribute explicitly |
| marks an item as stabilized. Note that stable functions may use unstable things in their body. |
| |
| ## rustc_const_unstable |
| |
| The `#[rustc_const_unstable(feature = "foo", issue = "1234", reason = "lorem ipsum")]` |
| has the same interface as the `unstable` attribute. It is used to mark |
| `const fn` as having their constness be unstable. This allows you to make a |
| function stable without stabilizing its constness or even just marking an existing |
| stable function as `const fn` without instantly stabilizing the `const fn`ness. |
| |
| Furthermore this attribute is needed to mark an intrinsic as `const fn`, because |
| there's no way to add `const` to functions in `extern` blocks for now. |
| |
| ## rustc_const_stable |
| |
| The `#[rustc_const_stable(feature = "foo", "since = "1.420.69")]` attribute explicitly marks |
| a `const fn` as having its constness be `stable`. This attribute can make sense |
| even on an `unstable` function, if that function is called from another |
| `rustc_const_stable` function. |
| |
| Furthermore this attribute is needed to mark an intrinsic as callable from |
| `rustc_const_stable` functions. |
| |
| ## Stabilizing a library feature |
| |
| To stabilize a feature, follow these steps: |
| |
| 0. Ask a **@T-libs** member to start an FCP on the tracking issue and wait for |
| the FCP to complete (with `disposition-merge`). |
| 1. Change `#[unstable(...)]` to `#[stable(since = "version")]`. |
| `version` should be the *current nightly*, i.e. stable+2. You can see which version is |
| the current nightly [on Forge](https://forge.rust-lang.org/#current-release-versions). |
| 2. Remove `#![feature(...)]` from any test or doc-test for this API. If the feature is used in the |
| compiler or tools, remove it from there as well. |
| 3. If applicable, change `#[rustc_const_unstable(...)]` to |
| `#[rustc_const_stable(since = "version")]`. |
| 4. Open a PR against `rust-lang/rust`. |
| - Add the appropriate labels: `@rustbot modify labels: +T-libs`. |
| - Link to the tracking issue and say "Closes #XXXXX". |
| |
| You can see an example of stabilizing a feature at [#75132](https://github.com/rust-lang/rust/pull/75132). |
| |
| ## allow_internal_unstable |
| |
| Macros and compiler desugarings expose their bodies to the call |
| site. To work around not being able to use unstable things in the standard |
| library's macros, there's the `#[allow_internal_unstable(feature1, feature2)]` |
| attribute that allows the given features to be used in stable macros. |
| |
| ## rustc_allow_const_fn_unstable |
| |
| `const fn`, while not directly exposing their body to the world, are going to get |
| evaluated at compile time in stable crates. If their body does something const-unstable, |
| that could lock us into certain features indefinitely by accident. Thus no unstable const |
| features are allowed inside stable `const fn`. |
| |
| However, sometimes we do know that a feature will get |
| stabilized, just not when, or there is a stable (but e.g. runtime-slow) workaround, so we |
| could always fall back to some stable version if we scrapped the unstable feature. |
| In those cases, the rustc_allow_const_fn_unstable attribute can be used to allow some |
| unstable features in the body of a stable `const fn`. |
| |
| You also need to take care to uphold the `const fn` invariant that calling it at runtime and |
| compile-time needs to behave the same (see also [this blog post][blog]). This means that you |
| may not create a `const fn` that e.g. transmutes a memory address to an integer, |
| because the addresses of things are nondeterministic and often unknown at |
| compile-time. |
| |
| Always ping @rust-lang/wg-const-eval if you are adding more |
| `rustc_allow_const_fn_unstable` attributes to any `const fn`. |
| |
| ## staged_api |
| |
| Any crate that uses the `stable`, `unstable`, or `rustc_deprecated` attributes |
| must include the `#![feature(staged_api)]` attribute on the crate. |
| |
| ## rustc_deprecated |
| |
| The deprecation system shares the same infrastructure as the stable/unstable |
| attributes. The `rustc_deprecated` attribute is similar to the [`deprecated` |
| attribute]. It was previously called `deprecated`, but was split off when |
| `deprecated` was stabilized. The `deprecated` attribute cannot be used in a |
| `staged_api` crate, `rustc_deprecated` must be used instead. The deprecated |
| item must also have a `stable` or `unstable` attribute. |
| |
| `rustc_deprecated` has the following form: |
| |
| ```rust,ignore |
| #[rustc_deprecated( |
| since = "1.38.0", |
| reason = "explanation for deprecation", |
| suggestion = "other_function" |
| )] |
| ``` |
| |
| The `suggestion` field is optional. If given, it should be a string that can be |
| used as a machine-applicable suggestion to correct the warning. This is |
| typically used when the identifier is renamed, but no other significant changes |
| are necessary. |
| |
| Another difference from the `deprecated` attribute is that the `since` field is |
| actually checked against the current version of `rustc`. If `since` is in a |
| future version, then the `deprecated_in_future` lint is triggered which is |
| default `allow`, but most of the standard library raises it to a warning with |
| `#![warn(deprecated_in_future)]`. |
| |
| [`deprecated` attribute]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated-attribute |
| [blog]: https://www.ralfj.de/blog/2018/07/19/const.html |