RFC for `#[stable(since)]`
Unsure what has been holding this up but would really love to have this!
One thing worth considering here that distinguishes crate APIs from the standard library is that so far, the standard library has not introduced any truly breaking changes to things, but crates do all the time. It might be worth investigating how to properly distinguish that the stability attributes specifically indicate the stability of the current version of an API, and not just when the API was introduced.
@clarfonthey
One thing worth considering here that distinguishes crate APIs from the standard library is that so far, the standard library has not introduced any truly breaking changes to things, but crates do all the time. It might be worth investigating how to properly distinguish that the stability attributes specifically indicate the stability of the current version of an API, and not just when the API was introduced.
I would prefer "first add" and we provide something else to track changes, like a #[changed] attribute, see also https://github.com/rust-lang/rfcs/pull/3854#discussion_r2349997019
Personally, with the way I usually think about this, I'd like stable(since) to mean "stable in this form since", and the fact that something might have existed in some other way before the current iteration is just not as important. I don't need to read about something being stable since 1.6 and changed in 2.0 and then changed in 3.0, the 1.6 and 2.0 version info doesn't really help.
While I have a vision for reforming stability attributes in general and exposing them to all crates, I don't see any scenario where this is not a subset of what is ultimately decided.
Huge :+1: from me. My primary suggestion is to include a recommendation (but not a hard requirement) for a lint for future versions. Having since = "NEXT" or similar (as mentioned) would also be very useful for scenarios where you don't know if it's a patch, minor, or major version that'll be released next.
If this attribute is intended for documentation and won't be enforced by the compiler, would it make sense to put it in the #[doc(...)] attribute?
#[doc(since = "2.25.0")]
pub fn add_trombone_emoji() {}
When considering why anyone needs this information, the primary use-case seems to be choosing the minimum required version of a crate (especially if the latest version of the crate requires a very new MSRV).
#[stable(since = "added")] with the first version in which an item has appeared seems more natural given the "stable since" terminology. However, it may be unsuitable for choosing the correct minimum required version if the oldest implementation isn't a compatible substitute for the latest one. What exactly is breaking for downgrades is hard to define, even harder than semver for upgrades.
There may be multiple kinds of features/behaviors stabilized separately. libstd has const_stable, but there may be library-specific functionality added. For example, wgpu features may be added to Vulcan backend much earlier than to WebGPU backend, and this distinction matters a lot to users who build for browsers.
So I'm wondering whether some changelog-like attribute would be better. If multiple #[changelog(version, note)] attributes were allowed, it would be easy to log multiple kinds of changes over time. min(version) would be "stable since", and max(version) would be a conservative minimum required crate version.
There's going to be a cfg() for Rust version: https://github.com/rust-lang/rust/issues/64796 which together with doc(cfg) could be a way to display MSRV for each item in the documentation.
The since version in libstd is effectively both MSRV and the minimum libstd crate version, but in 3rd party crates these two could diverge, and theoretically both could be available at the same time.
#[stable(since = "added")]with the first version in which an item has appeared seems more natural given the "stable since" terminology. However, it may be unsuitable for choosing the correct minimum required version if the oldest implementation isn't a compatible substitute for the latest one. What exactly is breaking for downgrades is hard to define, even harder than semver for upgrades.
Let's say foolib-v1.1 adds a new function fn decode_u64(buf: &[u8]) -> u64. That symbol could be annotated with #[doc(since = "1.1")] to aid the reader in knowing which minimum version of foolib they need to depend on.
If foolib-v1.2 changes the behavior of decode_u64 to support a new encoded format then it doesn't make sense to change its availability annotation. Similarly if there was a bug that returned the wrong value for some inputs and v1.1.1 fixed that bug then it wouldn't make sense to bump the "available since" annotation.
There could be an annotation to mark the most recent version that modified a given function's observable behavior, but that seems like it would be difficult to keep in sync with the actual code -- imagining a deep call graph, does a fix in some inner core logic cause the entire API surface to get its "API mtime" bumped...?
So I'm wondering whether some changelog-like attribute would be better. If multiple
#[changelog(version, note)]attributes were allowed, it would be easy to log multiple kinds of changes over time.min(version)would be "stable since", andmax(version)would be a conservative minimum required crate version.
This seems like it would be a better fit for prose, such as a summary of changes in the API comment or a traditional CHANGELOG.txt. The rustdoc extended Markdown syntax for tables can be used to good effect for inline changelogs, because it's more flexible than a strict (version, note) tuple.
@jmillikin you say it doesn't make sense to change the availability annotation, but don't justify why. If decode_u64 started supporting a new format in v1.1, then for users needing the new format it would be important to know they can only use decode_u64 since v1.1, and earlier versions won't work. I'm trying to address that problem by suggesting to bump the since version, so that users get a version that will be compatible with the behavior specified in the documentation they're reading.
An attribute only specifying when an item has become available for the first time is simpler to define, but what would you use this information for? I'm trying to look at it from a perspective of use-cases to avoid merely adding facts because it's possible. This version needs to be useful for something.
Maybe the issue could be redefined in a documentation-centric way (justifying doc(since) attr): saying that this documentation as written applies to the item since the given version. So if the docs say "the decode function supports the new format", it needs to refer to some later library version that added the new format support, not the oldest version that added the function without new format support.