163 lines
7.3 KiB
Markdown
163 lines
7.3 KiB
Markdown
# Stability attributes
|
|
|
|
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. To do this, follow the instructions in
|
|
[Stabilizing Features](./stabilization_guide.md).
|
|
|
|
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 `#[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.
|
|
|
|
|
|
## allow_internal_unstable
|
|
|
|
Macros, compiler desugarings and `const fn`s 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 whitelists the given features for usage in stable macros or
|
|
`const fn`s.
|
|
|
|
Note that `const fn`s are even more special in this regard. You can't just
|
|
whitelist any feature, the features need an implementation in
|
|
`qualify_min_const_fn.rs`. For example the `const_fn_union` feature gate allows
|
|
accessing fields of unions inside stable `const fn`s. The rules for when it's
|
|
ok to use such a feature gate are that behavior matches the runtime behavior of
|
|
the same code (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 @oli-obk, @RalfJung, and @Centril if you are adding more
|
|
`allow_internal_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
|
|
|
|
## -Zforce-unstable-if-unmarked
|
|
|
|
The `-Zforce-unstable-if-unmarked` flag has a variety of purposes to help
|
|
enforce that the correct crates are marked as unstable. It was introduced
|
|
primarily to allow rustc and the standard library to link to arbitrary crates
|
|
on crates.io which do not themselves use `staged_api`. `rustc` also relies on
|
|
this flag to mark all of its crates as unstable with the `rustc_private`
|
|
feature so that each crate does not need to be carefully marked with
|
|
`unstable`.
|
|
|
|
This flag is automatically applied to all of `rustc` and the standard library
|
|
by the bootstrap scripts. This is needed because the compiler and all of its
|
|
dependencies are shipped in the sysroot to all users.
|
|
|
|
This flag has the following effects:
|
|
|
|
- Marks the crate as "unstable" with the `rustc_private` feature if it is not
|
|
itself marked as stable or unstable.
|
|
- Allows these crates to access other forced-unstable crates without any need
|
|
for attributes. Normally a crate would need a `#![feature(rustc_private)]`
|
|
attribute to use other unstable crates. However, that would make it
|
|
impossible for a crate from crates.io to access its own dependencies since
|
|
that crate won't have a `feature(rustc_private)` attribute, but *everything*
|
|
is compiled with `-Zforce-unstable-if-unmarked`.
|
|
|
|
Code which does not use `-Zforce-unstable-if-unmarked` should include the
|
|
`#![feature(rustc_private)]` crate attribute to access these force-unstable
|
|
crates. This is needed for things that link `rustc`, such as `miri`, `rls`, or
|
|
`clippy`.
|
|
|
|
[blog]: https://www.ralfj.de/blog/2018/07/19/const.html
|