1# Stability attributes 2 3<!-- toc --> 4 5This section is about the stability attributes and schemes that allow stable 6APIs to use unstable APIs internally in the rustc standard library. 7 8For instructions on stabilizing a language feature see [Stabilizing 9Features](./stabilization_guide.md). 10 11## unstable 12 13The `#[unstable(feature = "foo", issue = "1234", reason = "lorem ipsum")]` 14attribute explicitly marks an item as unstable. Items that are marked as 15"unstable" cannot be used without a corresponding `#![feature]` attribute on 16the crate, even on a nightly compiler. This restriction only applies across 17crate boundaries, unstable items may be used within the crate that defines 18them. 19 20The `issue` field specifies the associated GitHub [issue number]. This field is 21required and all unstable features should have an associated tracking issue. In 22rare cases where there is no sensible value `issue = "none"` is used. 23 24The `unstable` attribute infects all sub-items, where the attribute doesn't 25have to be reapplied. So if you apply this to a module, all items in the module 26will be unstable. 27 28You can make specific sub-items stable by using the `#[stable]` attribute on 29them. The stability scheme works similarly to how `pub` works. You can have 30public functions of nonpublic modules and you can have stable functions in 31unstable modules or vice versa. 32 33Note, however, that due to a [rustc bug], stable items inside unstable modules 34*are* available to stable code in that location! So, for example, stable code 35can import `core::intrinsics::transmute` even though `intrinsics` is an 36unstable module. Thus, this kind of nesting should be avoided when possible. 37 38The `unstable` attribute may also have the `soft` value, which makes it a 39future-incompatible deny-by-default lint instead of a hard error. This is used 40by the `bench` attribute which was accidentally accepted in the past. This 41prevents breaking dependencies by leveraging Cargo's lint capping. 42 43[issue number]: https://github.com/rust-lang/rust/issues 44[rustc bug]: https://github.com/rust-lang/rust/issues/15702 45 46## stable 47The `#[stable(feature = "foo", since = "1.420.69")]` attribute explicitly 48marks an item as stabilized. Note that stable functions may use unstable things in their body. 49 50## rustc_const_unstable 51 52The `#[rustc_const_unstable(feature = "foo", issue = "1234", reason = "lorem ipsum")]` 53has the same interface as the `unstable` attribute. It is used to mark 54`const fn` as having their constness be unstable. This allows you to make a 55function stable without stabilizing its constness or even just marking an existing 56stable function as `const fn` without instantly stabilizing the `const fn`ness. 57 58Furthermore this attribute is needed to mark an intrinsic as `const fn`, because 59there's no way to add `const` to functions in `extern` blocks for now. 60 61## rustc_const_stable 62 63The `#[rustc_const_stable(feature = "foo", since = "1.420.69")]` attribute explicitly marks 64a `const fn` as having its constness be `stable`. This attribute can make sense 65even on an `unstable` function, if that function is called from another 66`rustc_const_stable` function. 67 68Furthermore this attribute is needed to mark an intrinsic as callable from 69`rustc_const_stable` functions. 70 71## Stabilizing a library feature 72 73To stabilize a feature, follow these steps: 74 750. Ask a **@T-libs-api** member to start an FCP on the tracking issue and wait for 76 the FCP to complete (with `disposition-merge`). 771. Change `#[unstable(...)]` to `#[stable(since = "version")]`. 78 `version` should be the *current nightly*, i.e. stable+2. You can see which version is 79 the current nightly [on Forge](https://forge.rust-lang.org/#current-release-versions). 802. Remove `#![feature(...)]` from any test or doc-test for this API. If the feature is used in the 81 compiler or tools, remove it from there as well. 823. If applicable, change `#[rustc_const_unstable(...)]` to 83 `#[rustc_const_stable(since = "version")]`. 844. Open a PR against `rust-lang/rust`. 85 - Add the appropriate labels: `@rustbot modify labels: +T-libs-api`. 86 - Link to the tracking issue and say "Closes #XXXXX". 87 88You can see an example of stabilizing a feature with 89[tracking issue #81656 with FCP](https://github.com/rust-lang/rust/issues/81656) 90and the associated 91[implementation PR #84642](https://github.com/rust-lang/rust/pull/84642). 92 93## allow_internal_unstable 94 95Macros and compiler desugarings expose their bodies to the call 96site. To work around not being able to use unstable things in the standard 97library's macros, there's the `#[allow_internal_unstable(feature1, feature2)]` 98attribute that allows the given features to be used in stable macros. 99 100## rustc_allow_const_fn_unstable 101 102`const fn`, while not directly exposing their body to the world, are going to get 103evaluated at compile time in stable crates. If their body does something const-unstable, 104that could lock us into certain features indefinitely by accident. Thus no unstable const 105features are allowed inside stable `const fn`. 106 107However, sometimes we do know that a feature will get 108stabilized, just not when, or there is a stable (but e.g. runtime-slow) workaround, so we 109could always fall back to some stable version if we scrapped the unstable feature. 110In those cases, the rustc_allow_const_fn_unstable attribute can be used to allow some 111unstable features in the body of a stable `const fn`. 112 113You also need to take care to uphold the `const fn` invariant that calling it at runtime and 114compile-time needs to behave the same (see also [this blog post][blog]). This means that you 115may not create a `const fn` that e.g. transmutes a memory address to an integer, 116because the addresses of things are nondeterministic and often unknown at 117compile-time. 118 119Always ping @rust-lang/wg-const-eval if you are adding more 120`rustc_allow_const_fn_unstable` attributes to any `const fn`. 121 122## staged_api 123 124Any crate that uses the `stable`, `unstable`, or `rustc_deprecated` attributes 125must include the `#![feature(staged_api)]` attribute on the crate. 126 127## rustc_deprecated 128 129The deprecation system shares the same infrastructure as the stable/unstable 130attributes. The `rustc_deprecated` attribute is similar to the [`deprecated` 131attribute]. It was previously called `deprecated`, but was split off when 132`deprecated` was stabilized. The `deprecated` attribute cannot be used in a 133`staged_api` crate, `rustc_deprecated` must be used instead. The deprecated 134item must also have a `stable` or `unstable` attribute. 135 136`rustc_deprecated` has the following form: 137 138```rust,ignore 139#[rustc_deprecated( 140 since = "1.38.0", 141 reason = "explanation for deprecation", 142 suggestion = "other_function" 143)] 144``` 145 146The `suggestion` field is optional. If given, it should be a string that can be 147used as a machine-applicable suggestion to correct the warning. This is 148typically used when the identifier is renamed, but no other significant changes 149are necessary. 150 151Another difference from the `deprecated` attribute is that the `since` field is 152actually checked against the current version of `rustc`. If `since` is in a 153future version, then the `deprecated_in_future` lint is triggered which is 154default `allow`, but most of the standard library raises it to a warning with 155`#![warn(deprecated_in_future)]`. 156 157[`deprecated` attribute]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated-attribute 158[blog]: https://www.ralfj.de/blog/2018/07/19/const.html 159