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