Support multiple stability attributes on items by dianne · Pull Request #131824 · rust-lang/rust (original) (raw)
Motivation
Many unstable library items require the stabilization of multiple features before they can be stabilized. By allowing them to be annotated with multiple #[unstable]
attributes, this prevents their accidental stabilization when some of those features are stabilized, and helps mitigate upgrade pains for unstable toolchain users.
New stability attribute semantics
- If any
#[unstable]
attribute is present on an item, it is unstable. Likewise, any#[rustc_const_unstable]
marks an item as const-unstable, and any#[rustc_default_body_unstable]
marks it as default body-unstable. - In order to use an unstable item, all feature gates specified by its
#[unstable]
attributes must be enabled. Conceptually, this is because it depends on multiple unstable features. Practically, this also means nightly toolchain users are less likely to need to replace one unstable feature gate with another in their crate-level attributes. - Multiple
#[stable]
attributes may be present. The stabilization version of an item is the most recent stabilization version in present#[stable]
attributes. Likewise,#[stable]
attributes may be present on an unstable item. This simplifies macros that can apply stability attributes to items.
This is documented in rust-lang/rustc-dev-guide#2128.
New syntactic constraints
- As a sanity check, an item is not allowed to have multiple stability attributes for the same feature.
- At most one
#[unstable]
attribute on an item may have areason
provided (and likewise for#[rustc_const_unstable]
and#[rustc_default_body_unstable]
). At a glance, thereason
meta-item was used to describe the reason for an item being unstable, rather than an individual feature it depends on. Enforcing this makes the diagnostic formatting much cleaner. - If any
#[unstable]
attribute on an item has asoft
marker, it must be present on all#[unstable]
attributes on that item. Items can't be partially soft-unstable, and this helps prevent accidentally making a soft-unstable item unusable on stable when stabilizing one of the features it requires.
Fixes #94770
Based on #94988
PR for a diagnostic formatting change this uses: #132544
Some notes on assumptions I've made and how I've handled them:
- Stability structs are specialized to how they're used for stability checking and rustdoc.
rustc_passes::lib_features
also reads stability attributes, but it parses them itself. I considered it out of the scope of this PR refactor that too, but once attribute handling is reworked to be more unified in the future, this may need further adjustment (but hopefully not too much). - Under the assumption that most library items will still have at most one
#[unstable]
attribute, this usesSmallVec<[_; 1]>
for storage. Is this assumption reasonable? I haven't done any performance testing. - Since
StabilityLevel
no longer hasCopy
, stability structs are now arena-allocated; that was the simplest fix. I'm not sure what the performance implications are. If it's an issue, I can try try making it only allocate for multiple unstable features (which would also letStabilityLevel
regainCopy
). As a stopgap until Proper support for cross-crate recursive const stability checks #132541 lands, this is using aConstStabilityLevel
enum for const-stability levels. Once that's merged, I should be able to move const-stability levels back to usingStabilityLevel
.
This doesn't update any libraries to add additional unstable attributes to items that should have them.