-
Notifications
You must be signed in to change notification settings - Fork 1.6k
RFC for #[stable(since)]
#3854
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
RFC for #[stable(since)]
#3854
Conversation
text/0000-stable_since.md
Outdated
- The entire `#[stable(feature)]`/`#[unstable(feature)]` functionality could be stabilized for 3rd party crates | ||
- API stability could be stored outside of the source code, e.g. in a file similar to `rustdoc`'s JSON | ||
- It could be shortened to `#[since("version")]` | ||
- It could be expanded to `#[stable(added = "version", changed = "version", rust_version = "msrv")]` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 Does "msrv" really belong here? If the rustc
version is too old the crate would simply refuse to be compiled, regardless if the you the tagged API or not. Besides you can't bump the MSRV without publishing the package, so it can be inferred from the changed
crate version already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could see the argument that a person would maybe want to know "if I use this then I can't go back in rust version farther then X", but that's extremely rare. Usually people seem to have a particular (possibly locked) version of rust available, and then want to know what they can do while on that same version of rust.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the
rustc
version is too old the crate would simply refuse to be compiled
This is not true if the package detects the rustc
version in use, which is already sometimes done through build scripts, and which #3857 proposes to make possible with a simple cfg
.
text/0000-stable_since.md
Outdated
|
||
Should the `version` allow a placeholder value like `UNRELEASED`? | ||
|
||
Is it clear enough that the version is the crate's own version and not the minimum requierd Rust version? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you thinking that a person would see a 1.0-series crate with "stable since 1.34" or something, and then think that it means that the crate provides an item as long as the rust version is 1.34? Because that's... Not How It Works for anything else in rust crates. A particular user could think that, but as soon as they ask almost anyone else I'm sure they'd be corrected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note, however, that there are real world examples of crates providing their own APIs based on the Rust version (e.g., camino
and fs-err
wrap std APIs and use Rust version detection to support new additions without constantly bumping MSRV).
text/0000-stable_since.md
Outdated
|
||
Should crates reset the `version` when making semver-breaking changes to the item? | ||
|
||
Should the `version` allow a placeholder value like `UNRELEASED`? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a rule like "you must put a string that can be a cargo crate version" is a simple enough rule, and however people want to get fancy with it is up to the ecosystem. For example, people could put the next minor version to be released, or put 0.0.0 as a placeholder, or whatever fits the project's tools and workflow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is indeed, but if people are going to use 999.999.999
or 0.0.0-unreleased
etc. as placeholders, we could as well provide some placeholder out of the box.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would love placeholder support as well as a teaching aid to use it (e.g. a clippy lint saying that the since
is too new)
How does #[deprecated(since)]
deal with any of this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"rustc
does not currently interpret the string, but external tools like Clippy may check the validity of the value."
#[deprecated(since = "abcdef")]
currently does not produce any lints or errors, but clippy denies with clippy::deprecated_semver
. It does recognize the special string "TBD"
though (rust-lang/rust-clippy#11850).
|
||
Versions on re-exported items are not relevant for the crate re-exporting them, because it matters when the re-export has been added. | ||
|
||
# Rationale and alternatives |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There can be multiple ways something can be stable. Today, std
also uses const_stable
. I assume this should at least be acknowledged in case it can affect the design. Today they are separate attributes. Should we instead generalize stable
to make it work for both? What impact may that have on this attribute?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's best to start with the simplest possible case and worry about the full situation later. I have some notes and design sketches for my thoughts if you'd like to discuss it on Zulip.
|
||
How to support items re-exported from other crates? Could `use` support overriding `#[stable(since)]`? | ||
|
||
# Future possibilities |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cargo update
could tell people to run some new command, like cargo report news clap@before clap@after
and see what is newly available.
Even better if we can get some form of "behavior change" and "remove attributes" (along with the stable deprecated
) along with build-flow analysis and tailor those parts of the report specifically to your use of the library (plus the new stuff)
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. |
text/0000-stable_since.md
Outdated
- The entire `#[stable(feature)]`/`#[unstable(feature)]` functionality could be stabilized for 3rd party crates | ||
- API stability could be stored outside of the source code, e.g. in a file similar to `rustdoc`'s JSON | ||
- It could be shortened to `#[since("version")]` | ||
- It could be expanded to `#[stable(added = "version", changed = "version", rust_version = "msrv")]` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like changed
will need its own attribute, stacked on top of each other.
Should this be in future possibilities? How I've been visualizing all of this in my head, changed
is another important element I would like us to have a serious discussion about at some point.
Huh, I guess changed
could be added as an unstable attribute and applied to home
as a way to start playing with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed can't really be a future possibility, because at the rate these sorts of language things happen, people will have stable(since)
for X many months already, and already think of the attribute as meaning one thing, and then eventually another attribute comes in and it changes how people should think about that.
So either it's in the initial design and all stabilized at once, or it can't really happen at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think changed
must be stabilized together. It should be sufficient to have some plan for future extensions. The stable
attribute can define how it's supposed to be used with APIs that changed, and attributes for providing extra information can be added later.
I would prefer "first add" and we provide something else to track changes, like a |
Personally, with the way I usually think about this, I'd like |
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 👍 from me. My primary suggestion is to include a recommendation (but not a hard requirement) for a lint for future versions. Having |
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(since = "2.25.0")]
pub fn add_trombone_emoji() {} |
|
||
Should it be allowed on private items? (there's `--document-private-items`, but those items won't be accessible from outside of the crate). | ||
|
||
Should it support specifying different kinds of stability, like `const_stable`? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would be useful, because marking a function as const
is forward-compatible.
If the #[doc(...)]
syntax is used then an item might be annotated #[doc(since="1.1", const_since="1.23")]
.
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).
There may be multiple kinds of features/behaviors stabilized separately. libstd has So I'm wondering whether some changelog-like attribute would be better. If multiple |
RFC for the issue rust-lang/rust#74182
Rendered