Idea: Bring `unstable` or similar attribute to the masses

Currently we have the attribute deprecated meant for items that are being sunsetted, or are only retained for compatibility. But there's no equivalent attribute for the other end of the life cycle. Many of us are probably painfully aware of the chicken-and-egg problem of trying to get feedback on new features before they're ready, as many users don't want to fully switch to an unstable version just to test something.

The ability to opt in to preview features in otherwise stable releases could lower that threshold. The attribute #[preview] (:bike::house:) could be attached to any item with public visibility and would have the following effects:

  • Signal that the item and any contained items are exempted from semantic versioning while in preview
  • Cause rustdoc add a warning/de-emphasize/etc the item in docs.
  • Trigger a warn-by-default lint (or even deny-by-default?) on any use in a dependent crate.
  • Trigger a deny-by-default lint within the crate if a preview item is exposed by non-preview API. Use as an implementation detail is fine.

Like deprecated, this attribute could admit additional metadata such as reason for unstability and planned stable release version.

Disadvantages

  • Another thing to implement and maintain and learn. For full effect requires compiler and rustdoc support. However, the footprint is tiny and the deprecated machinery is already there.
  • This would be fairly useless for APIs that are being changed, not just amended with new items, although sometimes it's possible to publish a parallel preview version of an existing API.

Alternatives

  • Continue the status quo; strict semantic versioning only allows incompatible changes between major versions. Crate users have to use dev releases if they want to test new APIs.

  • Let crate authors rely on documentation, perhaps utilizing warning blocks. Downsides include lack of standard vocabulary and not being (easily) machine-readable or lintable. It's also fairly easy to forget to update documentation.

  • Have users put unstable things behind crate features.

    Upside is it's easy to have as fine-grained features as one wants. Downsides include lack of standard vocabulary, inability to use an inactive item even within the crate itself, lack of a "warn" level between disabled and enabled, and inability to include metadata (though features might permit this in the future).

  • Add a more general facility for creating and triggering custom lints that could be used for this purpose as well. A downside, again, is the lack of standard vocabulary as well as asymmetry with deprecated. This would also be a much larger change and would undoubtedly linger longer in development.

Unresolved questions

  • Exhaustiveness: what to do with enum variants and struct fields? Could just disallow the use of the attribute with those, or only allow if the containing type is non_exhaustive.
5 Likes

We have an item on the 2024 lang roadmap specifically about stabilizing the "stability marker" attributes, so that libraries other than std could have "unstable APIs". If we did that, I don't think we would tie that to a nightly compiler. We'd have a way for the top-level crate to opt into the use of nightly APIs within a given dependency.

3 Likes

For clarity, that's "stuff we want in 2024", not "stuff we want in the next edition", correct?

1 Like

Insofar as we could provide it in all editions, yes.

1 Like

Regarding exhaustiveness, we already have to deal with that since std uses the unstable attribute. Current behavior is that if you don't use the unstable feature then the struct/enum is essentially non_exhaustive, and if do use the feature then you have to mention all fields/variants. In other words: it works as you'd expect, this shouldn't need extra #[non_exhaustive] annotations.