-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Release channels take 2 #507
Conversation
cc @wycats, this is a culmination in what feature-related work we were discussing at the work week. |
Some additional restrictions are enforced by the compiler as a sanity | ||
check that they are being used correctly. | ||
|
||
* The `deprecated` attribute *must*` be paired with a `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.
extra grave after the must
Just thinking out loud: it would be interesting if we could use a Cargo feature to enable some potentially-unstable APIs in a crate. For example, a Cargo feature "use_experimental" to conditionally-compile in use of some unstable |
which version each feature of the language and each feature of the | ||
library was stabilized, and by detecting every feature used by a | ||
crate, rustc can determine the minimum version required; and rustc may | ||
assume that the crate will be compatible with future 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.
This whole "rustc automatically determines the compatible version" idea is wishful thinking. There will be tons of subtle (and often unexpected) language/compiler/library changes that affect backwards compatibility across versions. This happens with every compiler/language/framework and while unfortunate, any expectations to the contrary are unrealistic.
Assuming that rustc can then automatically determine that any non-trivial library built and tested with rustc 1.5 will work just fine with rustc 1.3 because it only declares it's using features available from 1.3 onwards is again, wishful thinking. Such a library would have to be tested by the authors before one could confidently say it works with 1.3.
Any attempts at heuristically figuring out library & compiler/language compatibility will produce more harm than good. Someone will end up using a library that hasn't been tested with an older compiler/language/std version and if they're extremely lucky, the library will fail in obvious ways. If they're unlucky, it will behave only slightly differently than the author of the library intended.
A much better, simpler and more robust approach is to just enforce that a minimum language version is specified for a library. The KISS rule is a good idea here. Any attempts by a software system at "lets figure out what he user actually meant" almost always end in tears. Examples:
- The JavaScript equality table.
- "Error-correcting" parsers for HTML4.
- Perl.
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.
This all sounded good when we were discussing it in person, but now I see it written down, it does look rather complex.
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.
We do understand that this is not a rock-solid guarantee (what the minimum version of a crate is), but we also see the benefits of this detection to far outweigh the alternatives. One alternative (which it sounds like @Valloric is arguing for) is to simply do nothing, but this is strictly less useful than the system proposed here. If the compiler detects that 1.3 is required, then it must have at least 1.3, the failure mode is if a newer compiler is actually required. This is why a manual specification via Cargo.toml
is allowed if necessary. We do not expect the majority of code to require a custom annotation in their Cargo.toml
to request a particular nightly version.
Put another way, I personally doubt that adding this infrastructure will do more harm than good, and I also personally expect it to be quite a useful tool in upgrading rustc over time.
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'm not suggesting to do nothing, I'm suggesting the simplest and sanest approach of just demanding that every library state what is the minimum version of rust it requires (I mentioned this in my previous post). Libraries already have to specify the version of a library dependency (AFAIK you can't say "I depend on libfoo" without specifying the version of libfoo) and for the same reasons they should also specify the version of the language they require.
Extend this idea of heuristics to library dependencies to see how absurd it is: libraries say they require libfoo and cargo waves a magic wand, applies some heuristics and pulls out a "compatible" version. It's obvious this won't work, and yet we want to do this for the language.
The language itself is a versioned dependency much like any other library. Why is it being treated differently?
Stable builds are versioned and named the same as today's releases, | ||
both with just a bare version number, e.g. '1.0.0'. They are | ||
published at the beginning of each development cycle and once | ||
published are never refreshed or overwritten. Provisions for 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.
"never" seems very strong here - we should be able to patch if there is a critical security issue, for example
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.
@nick29581 Rather the version be removed from crates.io than a different version be made to take the same name. In this case, the version with a critical security issue would be 1.0.1, and 1.0.0 would be unavailable so people don't use 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.
Yes this means that 1.0.0 will never change, not that we'll never release 1.0.1
Thank you for looking into this! As a library author, I'm going to miss In fact, |
SemVer for Rust and As the maintainer of
I would love to be able apply SemVer rules to the "Rust platform" the same way I apply them to any other crate that I manage with Cargo. As for the idea of automatically detecting the appropriate compiler version to use with a given source tree, my reactions are:
To be fair, I can just modify |
merged, and like the 'nightly' channel each published build during a | ||
single development cycle retains the same version number, but can be | ||
uniquely identified by the commit number. Beta artifacts are likewise | ||
simply named 'rust-beta'. |
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.
Is this meant to be 1.0.0-beta
?
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.
No. I intend beta and nightly artifacts to not include version numbers. It's mostly just so that old beta artifacts don't stick around forever - the beta artifacts are intended to be transient, unlike betas from a typical (non-channel-based) release process.
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.
Oh, I see. ("1.0.0-nightly
" is mentioned in the previous paragraph.)
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.
@huon I think maybe it will be better to have the version number in the beta artifacts. Makes it clearer what you are getting, but it does mean that 1.0.0-beta-*.tar.gz will get overwritten with updates during the release cycle. What do you prefer?
Which "channel" will you recommend to a newcomer? |
@nodakai stable |
1. The compiler will discover all `#![feature]` directives | ||
enabled for the crate and calculate a list of all enabled features. | ||
2. While compiling, all unstable language features used will be | ||
removed from this list. If a used feature is note enabled, then an |
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.
s/note/not/
@alexcrichton Thank you for your response! My apologies for being so stubborn about this issue, too.
I agree that a hard error My proposal is to have two versions of
Here's a use-case for for something like #[deriving(Show, Default)]
pub struct Hints<'a> {
/// A value from an HTTP Content-Language header. The value "fr,en"
/// will bias the decoder towards French and English.
pub content_language: Option<&'a str>,
/// The top-level domain associated with this text. The value "fr"
/// will bias the decoder towards French.
pub tld: Option<&'a str>,
/// The original encoding of the text, before it was converted to
/// UTF-8. See `Encoding` for legal values.
#[experimental]
pub encoding: Option<Encoding>,
/// An extra language hint.
pub language: Option<Lang>
} Here, I've finalized 3 out of 4 fields in a struct, but the Basically, I feel that Needless to say, everything I argue here goes equally for Anyway, thank you for patiently listening to this long argument in favor of library-level |
Thanks for your clear articulation of what you'd like to see as a library author. I definitely see where you're coming from -- I am very sympathetic to wanting stability attributes in the Cargo ecosystem. It's a feature we definitely want to provide at some point. But we don't necessarily want to just keep the old stability system alongside the release channel system for Rust -- that would give two very different meanings to stability attributes. We also want to gain some experience using release channels for Rust itself before moving forward with something for the libraries. In short, I think we're likely to provide these facilities for external libraries in some form in the future, but we want to take our time to get the design right. In the interim, once plugins are stabilized it should be possible to build something like our existing stability system externally. I hope you can understand where we're coming from here -- as with so many feature requests, we'd really like to offer it, but we need time before we can commit to a design, and there is a lot of other stuff in flight right now. |
Thank you for your kind response, @aturon! I'll try to figure out the design disconnect one last time, offer to prepare a PR, and then drop this issue. :-)
I think this is where the disconnect is happening. The
As a library author, I need:
I don't need fine-grained control over multiple unstable features, or release channels, or anything else like that. A really simple system with nothing but Now, given the realities of getting 1.0 out the door, I understand that it might be necessary to remove the simple versions of Anyway, I'd be happy to contribute code, if that's the primary thing needed. But if there's no consensus in favor of an ultra-simple Anyway, thank you to everybody for listening to this plea. And I'll leave this alone from here on, unless somebody asks for a PR or something. :-) |
I've pushed a new revision that does a few minor things:
|
I appreciate the recent changes made here, but the proposed system still seems like lots of unnecessary complexity that will end up shooting users in the foot. I've asked this before without receiving an answer, so I must ask again: the language itself is a versioned dependency much like any other library, so why is it being treated differently? Why aren't we asking the user to always explicitly state which version of the language their library requires? There should be no "shoot yourself in the foot" option where cargo guesses for you. I'm fine with cargo verifying that the version you stated as a minimum actually works (if you say stable but are using feature directives, cargo should complain) and even cargo recommending a version based on its analysis (while stating that the recommendation is a best-effort guess and shouldn't be taken as gospel), but it really should always be leaving the final decision to you. This is the simplest approach and the one that's least likely to lead to nasty surprises. |
The approach I had in mind wasn't that Cargo says "this will definitely work on Rust 1.3", but rather "this will definitely not work before Rust 1.3". The idea is that if people leave out the version number, at least we can give a useful error message to people using the library on versions of Rust we know for sure won't work. |
@wycats Thank you for the explanation. That's a lot more reasonable.
What I'm saying is don't make that an option. You must state the language version number when you upload a library to crates.io. No confusion possible. If you leave out the version number, cargo complains saying you must, and tells you it has detected a certain minimum version based on what you used in the code. Say, it detects 1.2.1 as a min version. You on the other hand know that that version has a bug in a std library that affects your code, and you pick 1.2.2 as the min language version. If you pick 1.2.0, cargo complains that the version you picked can't compile your code (based on its analysis; it should even tell you why). |
We could do this, but I'm not sure how this would be an improvement. Most of the time, people would just blindly copy in what Cargo tells you to use, so why not just have us insert it automatically? |
Because it forces you to think about it. By doing it automatically, you're teaching people to blindly trust the version cargo spits out. By not doing it automatically, you make it explicit that cargo is making an (educated) guess. If you're aiming for your library to be compatible with 1.1, but cargo tells you it detects 1.2 as a minimum, you know you messed something up and you know it before publishing the library. |
I agree completely with @emk and would be very sad if the complicated and very niche needs of the standard library for versioning ruined the system for the rest of us. The std library should just use another set of attributes which could optionally be exposed to library authors and there should remain a simple set of attributes for setting stability of library APIs. |
@reem To be clear, everybody wants the stability attribute system to be useable in the crates.io ecosystem. The problem is that the current system has an extremely coarse-grained "opt in" where you have to accept unstable APIs from any sources, rather than saying only that certain unstable APIs are OK with you. We'd like to change this before committing to the design. I'm curious whether you agree that this is a problem with the design. It may be that using a feature naming system in crates.io is the right way to go; or maybe an item-based opt-in. It's not clear yet. But we plan to look into this ASAP. Also, we discussed the possibility of letting the attributes be used but not yet linting against them, which would at least retain a way to signal stability without committing to the blanket opt-in. |
This RFC has had some pushback against removing the stability attributes for this RFC, but I believe that @brson has addressed many of these concerns by renaming the attributes to their less appealing counterparts (prefixed with Additionally, @Valloric has pointed out that the "Cargo version detection" mechanisms may be too ambitious, but with @wycats's clarification and @brson's update the wording around this has been toned down significantly. As @wycats points out, the precise implementation in Cargo can develop over time. As a result, we've decided to merge this RFC as-is. Thanks again for the discussion everyone! |
Tracking issue: rust-lang/rust#20445 |
Maybe out of scope but rust-lang/rust#18815 should be considered too. |
Though this was merged while I was on vacation, I spilled a lot of words before that and want to point out a couple of final things:
|
of `#[staged_unstable(feature = "foo")]` APIs unless the current crate | ||
declares `#![feature(foo)]`. This enables crates to declare what API | ||
features of the standard library they rely on without opting in to all | ||
unstable API features. |
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 like this a lot, I think I'll use it in my own language, Noether (not necessarily tied to the "train" release model).
This RFC describes changes to the Rust release process, primarily the division of Rust's time-based releases into 'release channels', following the 'release train' model used by e.g. Firefox and Chrome; as well as 'feature staging', which enables the continued development of experimental language features and libraries APIs while providing strong stability guarantees in stable releases.
This revision includes a significant simplification by merging stability attributes with feature gates, which further enables some additional useful features within Cargo related to version detection. One big implication of this change is that stability attributes are no longer suitable for use outside of std (if such a feature is desirable it is intended to be solved by Cargo).