Idea: Semi-stabilization

I seem to be relatively alone with this view, but from a user perspective, I’m really against any kind of semi-stabilization.

The nightly system has it’s issues, but I like the way it works because:

  • it draws a very clear line between ‘this is stable and definitely won’t change’ and ‘this is experimental and under development’
  • it is comparatively easy to evaluate and understand code (snippets) and a crate: if it uses any features, I know it can only be used with the nightly compiler and includes experimental features. Otherwise I know it’s stable and can be relied upon long term.

Even with this distinction, the feature system is already quite opaque/confusing for users less familiar with the language and implementation process. It’s also quite hard to get an overview of existing features and what they are used for. (There is the unstable book, but I don’t think many know about it, there is no distinction between minor changes and major RFCs and many features lack a decent description).

Introducing another layer of stabilization (with new attributes) risks making this quite a bit more confusing . The “so this is pretty stable and probably won’t change much but there is no guarantee” seems like a suboptimal system to me.

It also risks features being stuck in a “semi-stable” status for extended amounts of time and and things becoming de-facto stable due to the amount of code written, and reduce the pressure to get things finished because they already work on stable anyway.

A cautious tale here could be Haskell where the numerous (sometimes incompatible) language extensions make checking the enabled ones a prerequisite for understanding a lot of code and are one of the worst aspects of an otherwise great language for me.

It’s already quite trivial to use the nightly compiler in Rust compared to other languages (if you pin the compiler to a known good version) and many have used it for extended amounts of time.

Specifically WRT to async/await, I’m quoting my Reddit post on the topic below:


I think a “early adopter stabilization” would be the worst path to take right now.

It would seem to me like punting on the (major) question of syntax which will be final, at least for years, and also like rushing out the door just to have something stable.

Stabilizing early with a stop-gap syntax and usability issues won’t help anyone, and will only create problems:

  • documentation issues with posts/docs/SO answers describing the initial syntax
  • frustration due to usability gaps
  • a “let’s hold off until things are actually stable stable” attitude from the ecosystem (specifically tokio for example)

I understand the urge to get things stabilized. But this is a hard engineering and language problem. In other ecosystems it has taken years and years of discussing, implementation and tuning to reach a solution (eg the recently accepted C++ coroutines).

I always thought that the rush to stabilization was a bit ill-advised. Let the feature bake in nightly as long as it needs to. Iron out usability issues, get practical experience to uncover API/design issues. Try to get error messages as helpful as they can be without additional aides like existential types.

I also understand that this is technically challenging thing to work on, hence the lack of contributors. The back and forth with the Pin + Future APIs, syntax discussions, etc are probably also probably very exhausting/demotivating for contributors.

But early adopters lived with nightly usage for years and can stick to nightly for now. After all, that’s exactly what nightly features are for. It’s already really easy to use experimental features in Rust compared to most other language ecosystems.

Slow and steady wins the race for me on this one.

  • let things bake on nightly until involved parties (lang team, compiler devs, major ecosystem stakeholders) are sufficiently happy with it, at least for the medium term
  • ensure good documentation in the book, in std, prepare blog posts etc

Then stabilize.

If this only happens in 2020, so be it.

18 Likes

This is why this proposal also suggests to automatically stabilize semi-stable feature in ~3 releases if no major flaws detected. The problem which you miss is that using feature can be a huge investment for projects, and with binary "stable" vs. "unstable, can break every nightly" status quo I believe Rust repels a sizable chunk of potential early adopters, meanwhile users are desperately needed for feature testing.

If we don’t have enough testers to really hammer out the bugs, then we don’t have enough testers to be assured of a good result after an auto-stabilize in 3 releases. So, that part seems deeply suspicious to me.

2 Likes

Rather than call them “semi-stable” and attempt to invent new definitions around that, we could have “beta” features. Then the semantic is clear. “Unstable” features require using nigltly. “Beta” features require using either beta or nightly. Beta features can change in a way that breaks code, but will only do so upon a new beta release, so this cannot occur more frequently than once every 6 weeks as opposed to every single night with nightly. This at least gives users the ability to keep up and gain some experience with the feature before it goes to stable.

I think it would be a major benefit if projects like Rocket could move to beta from nightly, as this would allow a lot less code attempting to rely on the stability of nightly.

20 Likes

When patches are backported to beta, does that change the current beta? I actually don't know, but it could mean that beta changes more than once every 6 weeks, but to your point those are rare and probably very small changes.

It doesn't automatically change the current beta, but then we put out a new release of beta with the changes, so it would change then, yes.

1 Like

So it looks like the beta suggestion of people here is good enough to solve this problem? No need for semi stabilization, removes the need to potentially change code every day to every 6 weeks. the only modification to this I could see is a longer form of the beta (changes every 2+ months) but that just feeds directly from beta somehow.

Well, if I understand correctly, a feature that moves to beta it doesn’t automatically also end up in stable as soon as that beta becomes stable. It stays beta-only for as long as we need to keep it in beta, correct?

1 Like

Here’s my interpretation and description of the proposal.

Beta features

Summary

Add a new tier for features that are available on beta but not on the corresponding stable, for testing important features that are believed to be ready for wide testing but may rarely still require breaking changes not compatible with stable.

Guide-Level Explanation

By opting into the beta toolchain, you get access to the “Rust of Tomorrow”. Barring unforeseen circumstances, the current beta toolchain (plus or minus a small number of backported patches) will become the next stable. If you write code on beta, you can be reasonably sure that it will work on stable in 6 weeks, though this isn’t guaranteed.

Beta also gives access to features that are a little further out. By using a #![feature(..)], you can opt into any of a small number of “beta” features. These are features that the Rust team believes are likely to stabilize in the form that they are currently, but need more widespread testing before being stabilized.

If you want to help with the development of Rust, using beta is a great way to do it! Use tomorrow’s features today and participate in the discussion to smooth out the remaining rough edges that keep it from being stabilized.

Implementation-Level Explanation

We use a similar mechanism as was used for the 2018 edition “extended beta” to allow the use of a small number of “beta” features on the beta toolchain.

What features should go beta?

This is left up to the discretion of the team in charge of stabilization of the feature. Not every feature needs to go through an extended beta, and not every feature is ready for an extended beta.

The RFC author suggests that very “public” RFC changes such as async/await and const generics may benefit from the extended testing that an extended beta can bring. These are features with a large impact that need to be used to be fully understood, and are likely to be stabilized with a compatible API to what would be offered in the extended beta period.

When should features go beta?

This decision is also left up to the team in charge of stabilization. A beta features should be “relatively likely” to stabilize in a semver-compatible version to its current state.

This is obviously a vague heuristic. It is the RFC author’s hope that a informal contract will emerge for how “ready” beta features are expected to be, while still allowing for breaking changes when needed to reach the best possible version of the feature.

Open Questions

  • Should beta feature markers look different from nightly ones?
  • Should be feature markers include a “revision number” so that any change to the feature can notify testers of the feature?
  • Will this lead to real users pinning a beta (that wouldn’t already pin a stable)?
  • How do we encourage real testing of beta features without accidentally “de facto” stabilizing them? Is the informal social contract enough?

If someone wants to polish that further and post a real (pre) RFC, feel free to take it.

4 Likes

I don't think we should make them different. This way if there is some crate A which used a nightly feature F. That crate won't have to change if feature F moves into beta, crate A will seamlessly compile on beta (given that there are no other nightly features). This way unmaintained crates will still benefit from beta features by allowing more people to reasonably use them.

2 Likes

While I like focus on beta and your general explanation of the proposal, I think that reusing #![feature(..)] will prevent crates which work on beta today to work on future stable (assuming that feature is unchanged), which I believe an important incentive for users to test beta features. This is why I think that enabling beta (and unstable) features in Cargo.toml as was proposed a bit earlier will fit perfectly.

Though I would remove the part about "you can be reasonably sure that it will work on stable in 6 weeks". Also maybe we should propose that all unstable features should undergo beta stage before stabilization.

We could re-use markers and just add an additional "version" field. Adding a separate marker is a viable solutions as well. I don't have strong opinions here.

Well, assuming beta feature is unchanged and we have beta features versioning, there is no reason to pin beta. But if there is a breaking change, then yes, crate users will have to use the beta which implements the old version. Hopefully such situations will be extremely rare.

I think "de-facto" stabilization syndrome is unlikely because features should have beta status relatively short time. In several releases they must be either fully stabilized, or moved back to unstable.

There probably should be an upper limit, e.g. in 3-4 releases feature should lose beta status in one of the two ways.

I honestly don’t think there should be any upper limit to beta time. There are some things which have reached some form, and which are unlikely to progress all the way to stable or change suddenly, and those should probably float into beta.

Here, I’m thinking specifically of the asm! macro, which is probably not likely to be stabilized exactly as it is now (because it’s heavily designed around LLVM), but also probably isn’t going to change suddenly from how it’s currently set up. We could probably have other examples as well.

We should, if we can, try to get people off of the lava lamp of crazy that is Nightly (where RLS and Clippy might be missing for weeks at a time), obviously without polluting Stable itself.

3 Likes

The guide level explanation also includes stable features on beta. The ones I refer to as "stable in 6 weeks" are those that are beta stable today.

I also think that making code using unstable beta features future-stable source compatible is too aggressive personally. They should still be opt-in. (This could be in cargo, I suppose, but shouldn't be "just work" without a higher level of confidence as was present for the e2018 extended beta.)

I also feel that the current beta train (6 weeks "beta stable") is enough for most small features and they don't need to do an extended beta. Many stdlib additions are small, obvious helpers that just ride the trains normally and are better off for it.

I could see a "extended beta" term limit, though. The idea as I see it is these features are those that could be stabilized "as-is" but need further testing and/or discussion. If asm! could never be source compatible with it's eventual stable version in its current format, it wouldn't get my vote for an extended beta. Removing a feature from extended beta in order to change it would also automatically inform any users (assuming they stay up to date).

It's a hard question and several players want different things out of this middle ground. In C-land, maybe this is the land of "vendor extensions" rather than standard features. Or maybe it's stricter than that; ESnext-approved-but-not-formally-published. In my draft, that's left to FCP & stabilizing teams to decide. But I'd err on the side of caution and opt-in, and not being future-stable-compatible (without deleting the opt-in).

Beta can leak some "vendor specific" beta features. Stable should stay purely (eventual) standard compliant and no more.

Could you please elaborate on that do you mean by "a higher level of confidence"?

As I picture it beta-features always will be opt-in, stable compiler will simply check if enabled beta-feature was indeed stabilized with the given version number. If it was, then it will emit a warning (something like "beta-feature flags can be removed") and will continue compilation as usual. Otherwise it will issue a compilation error stating that beta-feature(s) used by the crate have changed or haven't yet stabilized, thus user will be informed that the given crate can not be compiled by current stable compiler. Of course this approach requires strict versioning of beta-features, but I think it should be done either way.

agreed. if a beta feature hits stable with no changes, and older code expecting that feature is compiled on a recent stable version that stabilized that feature as is, just accept the code and move on with life. it’s the same as if you use a nightly feature after it goes stable, you get a warning but the code compiles.

things that let old code break with future compilers are bad.

That’s not correct. !#[feature] is always an error on stable.

Where it continues working is on nightly. (Or in terms of beta features, beta). I have no issue with that. But the “vendor extension” of experimental features shouldn’t be able to leak to stable.

1 Like

right, I meant nightly. sorry for any confusion.

hmm, and now that i slow down a moment to think twice about it, i agree. code should be able to forever live on the same channel. needing some intervention to go “down” a channel is fine.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.