Skip to content
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

Add new channels for long term support (LTS) releases #2483

Closed
wants to merge 1 commit into from

Conversation

withoutboats
Copy link
Contributor

@withoutboats withoutboats commented Jun 21, 2018

This RFC proposes a system for providing long term support (LTS) releases in line with our existing "release channels" mechanism. Essentially, every four releases, we upgrade the previous release to an LTS release. LTS releases "ride the trains" just like stable, beta, and nightly, and receive the same level of support as stable does.

Assuming this RFC is accepted in time for 1.28 to become an LTS release (which it might not be), the schedule would look like this:

beta stable lts lts-prior
2018-08-02 1.29 1.28
2018-09-13 1.30 1.29 1.28
2018-10-25 1.31 1.30 1.28
2018-12-06 1.32 1.31 1.28
2019-01-17 1.33 1.32 1.28
2019-02-28 1.34 1.33 1.32 1.28
2019-04-11 1.35 1.34 1.32 1.28
2019-05-23 1.36 1.35 1.32 1.28
2019-07-04 1.37 1.36 1.32 1.28
2019-08-15 1.38 1.37 1.36 1.32
etc..

Rendered

@withoutboats withoutboats added the T-core Relevant to the core team, which will review and decide on the RFC. label Jun 21, 2018
@withoutboats
Copy link
Contributor Author

cc @rust-lang/release

@withoutboats
Copy link
Contributor Author

Also, a noteworthy implication of this is that based on our planned release date for Rust 2018, all channels, including lts-prior, would support the 2018 edition on August 15, 2019 (though of course all channels would still support 2015 edition at that time, and no one would be forced to change).

@Lokathor
Copy link
Contributor

Is there any way to add a system so that a crate will be able to determine, through macro in core or something, what channel it's being compiled in? Then it can potentially adapt what it does to offer new functionality asap and also keep working with lts and lts-prior.

@withoutboats
Copy link
Contributor Author

@Lokathor that is fraught I think because the compiler that each channel refers to changes every 6 weeks. It seems like what you actually want is which rustc version, rather than which channel. Also seems orthogonal to adding new release channels.

@sgrif
Copy link
Contributor

sgrif commented Jun 21, 2018

I'm not immediately clear what the difference between lts and lts-prior is in this RFC. If they have the same level of support. It seems like it'd be much clearer to say "every fourth release is an LTS release, it will receive support for 32 weeks".

That said, 32 weeks definitely does not feel like "LTS" to me. For languages without a 6 week release model, that's just the difference between releases, much shorter than how long they are supported for. As a point of contrast, Ubuntu releases an LTS version every 2 years, and supports them for 3 years after release.

Is there a specific group that this short support cycle is meant to target specifically?

@SimonSapin
Copy link
Contributor

For anyone else wondering, four 6 week cycles is just under half a year.

@Lokathor Today you can use https://crates.io/crates/rustc-version in a build script and conditionally run println!("cargo:rustc-cfg=foo");, which affects #[cfg(foo)] in the crate. But as boats said that seems unrelated.

2. Their library compiles on the stable channel.
3. Their library compiles on any release more recent than an arbitrary old
release, which is different for each library (for example, `failure` compiles
on 1.18.0, whereas `serde` compiles on 1.13.0).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly unrelated, but worth mentioning -- Serde only supports 1.13 with default features turned off. With them enabled, it only supports 1.24 and later -- Diesel supports specifically that version since one of our dependencies requires serde and didn't set default-features = false. While not specifically related to this RFC, it's a larger problem that is tangentially related to the one this seems to be trying to solve.

@algesten
Copy link

Isn't this RFC missing to mention the relationship between this and "editions"? I mean a library could theoretically target an edition and guarantee it compiles with the syntax at the beginning of that edition?

@Ixrec
Copy link
Contributor

Ixrec commented Jun 21, 2018

I'm under the impression that "LTS" implies multiple years, and some quick googling seemed to confirm that 3-5 years is typical. Are we sure that an "LTS" which we support for less than a year is acceptable? I didn't see any discussion of that in the RFC.

Otherwise I like the idea of using the existing release channel system for this, and I like the idea of making it our official recommendation on what Rust libraries should support.

@Manishearth
Copy link
Member

There was some discussion on this topic previously at https://internals.rust-lang.org/t/possible-lts-releases-tied-to-editions/7380/12

The main difference is that that proposed making them happen around every edition, not every four releases. However, that thread has a bunch of discussion on use cases which may prove relevant here.

@Lokathor
Copy link
Contributor

Well, it's just that the suggestion is right there in the RFC that we stop targeting rustc versions and start target channels. Yes, I know about the rust version crate. If we're serious about crates "targeting a channel" we need to promote something like the rust version crate into a core ability of the rust build process.

@withoutboats
Copy link
Contributor Author

withoutboats commented Jun 21, 2018

Its stated in the RFC, but as it rides the trains, every "LTS release" (e.g. 1.28) will be supported for 54 weeks, or just over a year. This is because it is the head of the stable train for 6 weeks, then the head of the lts train for 24 weeks, and then the head of the lts-prior train for another 24 weeks.

If a library supports only the lts train, it is compatible with roughly 6 months of previous Rust releases (30 weeks), and if it supports the lts-prior train, it is compatible with roughly a year of previous Rust releases (24 weeks).

Different projects have different definitions of LTS, the lengths of support in this RFC is based on the ember project's LTS policy (as the RFC mentions in the prior art section). Other projects have very different stability guarantees from us, in addition to having different LTS guarantees. With our policy that any stable-to-stable regression is a bug, I think supporting users who only upgrade their compiler once annually is sufficient.

Isn't this RFC missing to mention the relationship between this and "editions"? I mean a library could theoretically target an edition and guarantee it compiles with the syntax at the beginning of that edition?

An edition is not really any different from any other compiler feature relating to this proposal; the only way its relevant is to ask if a given compiler version supports the edition or doesn't. A core point of editions is that they are not tightly coupled to compiler versions.

@withoutboats
Copy link
Contributor Author

One thing that could be worked on corollary to this RFC is how rustup surfaces the user experience. Users who want to update once annually want to follow version 1.28 (or w/e) until it becomes unsupported, then upgrade to version 1.36. This isn't the same as choosing a train and sticking to it, and the UX should probably surface that option instead of strictly surfacing the release channels.

@algesten
Copy link

An edition is not really any different from any other compiler feature relating to this proposal; the only way its relevant is to ask if a given compiler version supports the edition or doesn't. A core point of editions is that they are not tightly coupled to compiler versions.

Ok. So I guess we have compiler features and stability/security patches as two strands of motivation. Edition is about guarantees around compiler features, whilst this RFC is more about the support in terms of patches/stability?

@BurntSushi
Copy link
Member

We recommend that libraries consider dropping support for a release channel to be a breaking change

To be super clear on this, that means that moving a library from one lts-prior release to the next (as in, failing to compile on the prior lts-prior release) is not considered a breaking change according to this recommendation?

(I am super excited to have a policy on this point, and it seems very reasonable!)

@Mark-Simulacrum
Copy link
Member

I believe that something that's missing from the current RFC is discussion about how compatibility lints fit into the LTS model: I think it would be reasonable to suggest that these warnings would be backported onto LTS and LTS-prior channels so as to mitigate the amount of breakage encountered when migrating from LTS to LTS.

@withoutboats
Copy link
Contributor Author

@BurntSushi Yea, that's correct.

A sufficient way to implement this as a library would be to just run CI on all of the release channels, instead of running it on any particular version. Then when the LTS rotates every fourth release, your minimum version would automatically be bumped to the version of lts-prior.

@withoutboats
Copy link
Contributor Author

withoutboats commented Jun 22, 2018

Something that i think isn't super clear in the RFC is that this amounts to having 2 concurrently supported LTS releases, each supported for roughly 1 year. What this means is you can update once per year and keep current, but if a feature comes out that you really want, you could upgrade once more after 6 months and "switch tracks" to the other LTS, then continue updating once a year after that.

An equivalent system would be to have just lts-1 and lts-2 releases, released in alternating 24 week intervals, each supported for 48 weeks, rather than having the shift from lts to lts-prior. It'd result in the same versions being supported, and I can't tell if it is more or less clear than what the RFC proposes.

Here's the table with that designation:

beta stable lts-1 lts-2
2018-08-02 1.29 1.28
2018-09-13 1.30 1.29 1.28
2018-10-25 1.31 1.30 1.28
2018-12-06 1.32 1.31 1.28
2019-01-17 1.33 1.32 1.28
2019-02-28 1.34 1.33 1.28 1.32
2019-04-11 1.35 1.34 1.28 1.32
2019-05-23 1.36 1.35 1.28 1.32
2019-07-04 1.37 1.36 1.28 1.32
2019-08-15 1.38 1.37 1.36 1.32
etc..

@XAMPPRocky
Copy link
Member

I feel generally sceptic towards adding two additional stable release channels. Firstly I think this complicates how we talk about the release model of Rust, currently we have a very straight forward linear stream of releases. Now with the addition of lts and lts-prior when we explain the model we have to discuss how the stable version is not actually the most “stable” channel you can be on. I think the addition of these channels would probably warrant changing the name of stable to something like current.

However, for various institutional reasons, many users do not find it convenient and desirable to upgrade with the frequency that Rust releases. So far, they have been left on their own to figure out when to actually upgrade, creating a situation of uncertainty and disparity.

This sounds more like users don’t have confidence in our current stable releases, because the answer should be “when they can”. Whenever they are allowed to upgrade they should be able to, and feel confident in upgrading to whatever rust version is out at that time to use until they are allowed once again to upgrade.

When we talk about releases we’re really talking about patches and whether or not they need to be backported. A non-backported patch that lands today will be present in the next nightly build, the beta build after the upcoming release, and the stable build in the release of the previous beta. The addition of two stable release channels doesn’t really change this model. I think were it becomes complicated is when a patch needs to be backported. The longer the timeframe between releases is the longer the code rots and the harder it becomes to patch. This will put a lot more pressure on stable releases that are going to become lts releases to try and minimise the need for lts(-prior) patches. lts, lts-prior and stable might receive the same level of support after their release, but up to their release the nature of this system will place more importance on stable -> lts releases than releases only appearing in stable.

Also what the same level of support with the stable channel is unclear in relation to non-technical aspects of releases. For example will there now occasionally be two simultaneous rust release blog posts? Each showcasing the features added to each release. Because the people who are upgrading between ltss might not want to read through 4/8 separate blog posts to read what is the new, to get the same level of support there would now need be a separate LTS blog post explaining to those users the changes between versions.

While the intention may be that a lts user would only update once a year, there is no current workflow to have this behaviour. Assuming that someone was handling their rust upgrades with rustup and set rustup default lts this toolchain would update every six months or so and not every year as rustup currently would never switch you to lts-prior automatically based on rustc version.

I do think that the disparity between libraries on what rustc versions they support is a problem. I think however that the solution for that is already underway with editions. Editions will already require a major version bump if they are incompatible. An edition is also a lot longer than the currently proposed LTS which is a greater degree of stability for library authors and their users.

@est31
Copy link
Member

est31 commented Jun 22, 2018

Its a great idea to offer LTS releases. They give the crate ecosystem a "pulse" after which it can update compiler version requirements.

Given how quickly the ecosystem is jumping onto requiring new releases, as an application author you basically have to use rustup and while its awesome for trying out nightly stuff, and I certainly prefer enjoying the fastest compiler there is and this is usually the latest nightly compiler, should every user of my application be required to use it as well? Installation of rustup itself is non-trivial, certainly less trivial than a simple apt install rustc and it's another tool to learn. Also, I'd prefer to not download any binaries except through the means my distribution provides for me. I think that LTS releases will help with this use case, and I greatly appreciate that!

I've got one open question: Should rustc bootstrap from the last LTS now instead of the last stable release? This would ease the life of distributors of Rust as they don't have to follow every release of Rust but it could be harmful for work on rustc, slowing some changes down, etc.

@pietroalbini
Copy link
Member

Just a note, backporting even simple patches to lts-prior will surely be hard. There are already cases when backports from nightly to beta requires rewriting parts or even the whole patch.

I also prefer lts-1 and lts-2 instead of lts and lts-prior, maybe with a different name. What about lts-even for 1.x0 and lts-odd for 1.x5?

@XAMPPRocky
Copy link
Member

On backporting changes using git diff 1.19.0..1.27.0 --stat -- src/ ':!src/test' ':!src/doc' ':!src/ci' there was roughly 7x as many changes as those in a normal release. That is a pretty dramatic increase in code rot and potential amount of work required to backport a patch. The question then also becomes who is going to write the lts-prior & lts patch. Once a bug has been found to be required to be backported there is a lot of time pressure to get it out as soon as possible.

With a mounting time pressure and the potential scale of the patch dramatically increasing I would say that this actually increases Rust's surface to bugs as the code-bases between releases drift apart.

upgrade between Rust stable releases.

However, for various institutional reasons, many users do not find it
convenient and desirable to upgrade with the frequency that Rust releases. So
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, this should be substantiated by at least some examples of the institutional reasons and the users, and that are specific to Rust.

The Rust project recommends that library authors interested in providing
support for users on versions older than the latest stable, instead of focusing
on supporting particular *versions*, focus on supporting particular *release
channels*. That is, a library may guarantee that it will compile on any of the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that doesn't work well and will lead to surprises for users.

Say that you start with adding lts to your Travis CI matrix... After half a year, lts will suddenly become a different version, and so you are testing a different version, instead of the one you were testing when you added lts into your matrix. Therefore, instead should become in addition to. Otherwise, a crate like serde will actually support fewer versions (provided --no-default-features per @sgrif's note).

Another way to solve this is to always increment the X in lts-X such that you can pin to a particular lts version. lts and lts-prior itself will refer to the highest X and X - 1. Backports will still only be provided for lts and lts-prior.


We recommend that libraries consider dropping support for a release channel to
be a breaking change, but that dropping support for any particular version of
Rust to be a non-breaking change.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, libraries have until now considered bumping the minimum stable release requirement to be a breaking change. This seems to weaken that guarantee considerably?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Centril the question is contentious. This suggestion is somewhat of a middle ground.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@est31 Thanks for the link -- I haven't read the thread in depth, but think I agree with @KodrAus.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Centril To summarize, I don't think there is actually any strong consensus on this point. Some libraries do as you say. Others adopt a different policy as a compromise where they are allowed to bump the minimum Rust version in minor version releases. Some libraries even bump the minimum Rust version in patch releases, although it is sometimes for good reason. This happened, in recent memory, with the log and rand crates, where they used the semver trick to make a patch release depend on a new minor release, which in turn required a newer rustc.

In my view, we're kind of all over the place right now. The best I've come to hope for is that library authors pin a Rust release in their CI so that it's at least easy to observe a possibly non-minimal lower bound.

I welcome a recommendation (such as the one in this RFC) that we can all unite around.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BurntSushi Alright; Thank you for the summary. The policy mess sounds like a bad place to be in, I agree. I agree that there should be a recommendation to unite around, but I don't think it should be the one in this RFC.


For libraries that do not believe they are "core libraries," we make no
particular recommendation about which channels to support. There is always a
trade off between providing the best API for users on stable as soon as
Copy link
Contributor

@Centril Centril Jun 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In principle, I have no objection to providing LTS release channels if the bandwidth exists..

However, I believe the timing is not right and that this should be done in 2021. Why? Because the existence of LTS and the marketing thereof incentivizes supporting LTS releases and users will request that of libraries. I think that for the time being, there are important language features, such as:

  • Generic Associated Types (GATs),
  • const generics,
  • support for impl Trait in traits,
  • specialization

that would improve many APIs considerably, but which will not make it into Rust 2018.

I also think that the mechanisms to detect if a library path exists, or similar methods for ergonomic conditional compilation does not exist yet.

Therefore, I think we should wait until some important language features are in place.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Centril But LTS releases, as proposed, are to supported only for about a year, so should not intefer with marketing of these language features. That is, the conservative people would have needed to upgrade 2-3 times anyways to get to 2021.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not the marketing of the features I'm concerned about, but how LTS releases and marketing thereof incentivizes libraries, to become, in my view, prematurely more conservative, and thus miss out on these specific features that are important for the public API of libraries. 2021 was just an example; it doesn't have to be that long. But I still think the time is not right, yet.

Copy link
Member

@tshepang tshepang Jun 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Centril I think the important libraries are already conservative anyways, meaning they don't bump minimum versions unless they "have to". What you are also asking is for someone to decide what future feature is worth waiting for, meanwhile we were able to get by without such features.

Copy link
Contributor

@Centril Centril Jun 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tshepang I don't think that is true. Some important libraries are conservative (serde). Others don't compile on stable yet (rocket). Other important libraries have breaking changes more frequently (syn). A library like diesel supports 1.24.1, which was released 2018-03-01, in its .travis.yml. Some libraries will/should be important but can't be made 1.0 yet due to lack of the specific features I've cited, in particular GATs.

What you are also asking is for someone to decide what future feature is worth waiting for, meanwhile we were able to get by without such features.

I think those features in particular, and especially GATs affect very much the fundamental nature of some library APIs (see StreamingIterator vs. Iterator). One can always "get by" with a very minimal mostly featureless language without parametric polymorphism and such things. But if you want more than "getting by", then good APIs depend on the abstractive power of the language.

I am not asking that everyone should wait for these features. They can always pin to some version of Rust like 1.13 as they've done so far. But if we're going to provide LTS releases, then our story around conditional compilation should first be improved, and these features, in particular GATs, important for the APIs of libraries, should be there first, in my opinion.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rocket and syn are special cases, the former explicitly target nightly, and the latter depends on recent compiler changes (I think), and I besides didn't consider it important, not in a sense that serde is important. The diesel one falls under "have to", as explained here #2483 (review).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rocket targets nightly because it has no choice but to (until proc macros land), which is precisely my point. There are fundamental language features which have not landed yet that important crates need. diesel, a central crate in the ecosystem, having to support 1.24.1 means that it wouldn't otherwise. This means that it would be even less conservative.

[drawbacks]: #drawbacks

This increases the maintenance burden on the release and infrastructure teams
by adding two additional release channels.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm currently skeptical that the bandwidth to do this release work and that the funding to support those doing the work exists. But I would be happy to be proven wrong.

[prior-art]: #prior-art

Many different projects offer an LTS release. Our most direct inspiration was
the ember project. The ember project's LTS support is described well by both
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does surprise me. I would think that some of the users most interested in LTS releases are more industrial applications including embedded devices. I concur with others that something called "LTS" is surprising to only provide support for 6 months / 1 years.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Centril Would you prefer it be longer than 1 year, or would you prefer it being called something else?

Copy link
Contributor

@Centril Centril Jun 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no preference. But if we are going to call it "LTS", then I think it should be longer than 1 year. On the other hand, if it is longer than 1 year, then even more bandwidth will be required of the people doing the back-porting of bugfixes.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Time to invent "MTS" (Medium Term Support) releases.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"long" is a relative term, and in this case, 1 year vs 6 weeks

@steveklabnik
Copy link
Member

steveklabnik commented Jun 22, 2018

@sgrif @Ixrec @Centril

I have always envisoned our LTS schedule to start small, and then expand over time. Right now, we offer no real support beyond the current stable release. Moving from six weeks to nearly a full year is a big jump. I imagine in five years, stretching it out two two years will make sense. But you gotta start somewhere.

receive the same level of support. We will host documentation for all three
channels and provide equivalent levels of patch release support - that is, if a
bug justifying a patch exists in any of these channels, we will release a patch
for that channel, just as we do today for stable. However, lts releases are
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a good formulation of our current support, but I might like to see it laid out a bit better for LTSes, that is, can we refine this policy too? It's basically 100% subjective at the moment.

@Centril
Copy link
Contributor

Centril commented Jun 22, 2018

@steveklabnik Granted; it is reasonable to extend the LTS period over time, but then that should be stated explicitly :) But I think we should not start yet but later (~1.5 years from now or the next edition preferably). As such, I think this RFC should be postponed due to lack of important features (for API surfaces) such as GATs, and more ergonomic conditional compilation around existence of paths (e.g. in the standard library), as well as the increased workload as described by @Aaronepower.

@Ixrec
Copy link
Contributor

Ixrec commented Jun 22, 2018

I have always envisoned our LTS schedule to start small, and then expand over time. ... I imagine in five years, stretching it out two two years will make sense.

This makes perfect sense to me, though it never occurred to me until your comment. We should mention this possibility somewhere in the actual RFC.

@steveklabnik
Copy link
Member

@Centril there will always be new, important stuff around the corner. Many people write a lot of Rust code, today, without those features. Yes, they will add cool new things. But, if we wait for the cool new things, we'll be waiting forever.

If we start ~1.5 years from now, well, there will also be LTSes kicking off in that time frame as well.

@aturon
Copy link
Member

aturon commented Jul 12, 2018

@rfcbot concern edition

One of the major motivations for this RFC is establishing a clear "baseline" for libraries that aim for maximum compatibility; right now, most fundamental libraries shoot for "as old a version as possible", which prevents adoption of new features and idioms.

I worry that delaying setting up the release channels described here will also substantially delay the point at which fundamental libraries can/will transition their code to the new edition. While they will of course be compatible with all editions, it seems highly desireable for our most visible libraries to adopt new idioms relatively quickly.

@rfcbot rfcbot added proposed-final-comment-period Currently awaiting signoff of all team members in order to enter the final comment period. disposition-postpone This RFC is in PFCP or FCP with a disposition to postpone it. labels Jul 12, 2018
@aturon
Copy link
Member

aturon commented Jul 12, 2018

I should say: it's possible that we can set a "baseline" policy independently of working out the full LTS story. But before we postpone this RFC, I'd like to get some clarity on this point.

@withoutboats
Copy link
Contributor Author

I see this as very important to shipping the edition. Essentially what @aturon said: without this, we need an alternative that enables libraries to confidently upgrade their minimum Rust version so that they can move to 2018.

@nagisa
Copy link
Member

nagisa commented Jul 12, 2018 via email

@sdht0
Copy link

sdht0 commented Jul 12, 2018

Here are some of my thoughts. I have to warn you that I am very new to the Rust ecosystem and might be missing completely obvious things. Please do point them out if any :)

  • As @teiesti mentioned, RFC: Minimum Supported Rust Version #2495 (MRV) provides a technical solution that alleviates part of the issues that motivate this RFC. Specifically, libraries can individually decide what minimum rust version they want to target (depending on the features they are using), and cargo can automatically determine for users if their rust version is sufficient to use a particular library version.
  • Another question that I think would benefit from some more discussion is why a library (in contrast to a user) would want to upgrade the MRV they support. Given Rust's strong backward compatibility guarantees, shouldn't a library be simply able to target rustc 1.0.0 as their MRV and stick to that? Of course, this changes when the library wants to use new features (e.g., impl Trait). Then they would have to update their MRV to the first rustc version that implements that feature (e.g., 1.26.0), and then stick to this version until the next such change.
  • This RFC does bring up an important point that libraries experience uncertainty around when to start using a new feature (e.g., impl Trait). I think that it is this point that a LTS rustc version helps address the most, because a LTS version would become a natural MRV that the community can coalesce to. However, it might happen naturally as well (speculating), such as the first version of rustc supporting 2018 edition might become the defacto MRV for the next major version of all libraries.
  • On the other hand, I am still unclear how lts channels will be effective, as per my comment Add new channels for long term support (LTS) releases #2483 (comment). Say a lts channel currently supports 1.28 and 1.32, as soon as a library starts using new features introduced in 1.31, users won't be able to compile the library using 1.28, so this will be a breaking change for the library.

In summary, I think one approach could be to, stepwise:
i) implement the MRV rfc and leave it to the community to decide which versions they want to support. Updating MRV should probably always be considered a breaking change.
ii) Introduce rustc LTS versions, which would become natural MRVs that libraries can choose with much more certainty, without the additional concept of lts channels.

@newpavlov
Copy link
Contributor

newpavlov commented Jul 12, 2018

Updating MRV should probably always be considered a breaking change.

Can you elaborate why do you think so? As i see it after initial migration (which will be equivalent to requiring at least Rust 1.27), specifying MSRV will allow us to bump it in a backwards compatible way. crago simply will not use newer dependency versions, thus builds will not be broken.

Though it will make sense for post-1.0 crates to bump minor version on MSRV bump to allow easy publishing of important backports (e.g. security or soundness fixes) with patch versions.

@sdht0
Copy link

sdht0 commented Jul 12, 2018

You're right. I meant libraries should not change the MRV in patch releases, for the reasons you mentioned.

Whether they can change the MRV in minor versions or only in major version is a policy decision we can make.

@ashleygwilliams
Copy link
Member

ashleygwilliams commented Jul 12, 2018

Hey! So I'd like to provide some context for the call to postpone.

In the core team meeting, we discussed several aspects of both this RFC and the general process of stabilization. Here were our primary thoughts:

  1. We are probably not getting as many eyes on nightly as we want to. As a result, we have seen an uptick in point releases. Our convo originally started as a convo about backporting and we realized that the first thing we'd like to try to do is establish a better stabilization process with concerted efforts to help folks help us QA nightly so that we can feel more confident about what we stabilize. This is not necessarily directly related to an LTS policy, but is a stepping stone towards building a system where an LTS policy can happen.

  2. We don't entirely know what LTS means. It was clear from our convo that many of us have different ideas of what an LTS could mean, and that other ecosystems also have definitions. We think it would be super useful to talk to stakeholders (library authors and production users) to get a clearer sense of what community expectations of an LTS would be.

  3. Communicating an LTS strategy is hard work! We spoke a lot about how other ecosystems implemented LTS and the struggles they had with properly communicating it with the community. Even despite best efforts, a lot of ecosystems had a lot of trouble with this, especially because of the things mentioned in 2- everyone comes with their own understanding. As a result, the communication burden of a new LTS strategy is pretty high- and it's not something that many of us thought the team had bandwidth for.

  4. Community can only understand so much at one time. Even if we did have bandwidth for a fantastic marketing and communication plan around an LTS, its worth noting that a community can only understand so much at a time. With the edition coming soon, we felt that it would be easy to confuse LTS and the edition concerns. We are already tarrying with misunderstandings around what the edition is, and adding another idea on top of that could have, at best, middling results. We think LTS is important, and we want to get it right, and so giving it its own moment seems like a good idea.

  5. Having an LTS can lead to less folks experimenting on nightly. This relates back to 1. While this is not a hard and fast rule, we've observed ecosystems that have introduced an LTS and have seen a dramatic reduction in folks using an "Edge" or "experimental" release. Since the meeting started with acknowledging that we might be lacking in this area, we want to be sure to have programs/process in place for maintaining community help and support on triaging and QAing nightly before we introduce an LTS.

In general, I really love the idea of an LTS. As a library author I definitely share the concern about knowing what to support. I don't necessarily believe that the things I have listed here are pure blockers, but I do think it is incredibly important that we keep an eye on how saturated with new things our community is and our bandwidth for communicating critical changes to Rust.

@alexcrichton
Copy link
Member

@aturon and @withoutboats the point about the library ecosystem and rustc compatibility I've often felt is too often conflated with LTS releases as well, and is one point of why I'm in favor of postponing this RFC. I would, for example, not consider it a great situation if our most idiomatic libraries (aka serde) can't use new features for nearly a year after they're released!

I think that instead this problem is best tackled from a different direction. I've often heard that if Cargo on rustc 1.24 (for example) would simply not select versions of Serde (for example) that doesn't build on 1.24 then this would largely be a solved problem. In this sort of world Serde would be able to use any language feature it wanted, and older Cargos would only ever use a version of Serde that their coupled version of rustc understands. This sort of strategy, to me at least, also seems much more achievable before the edition than figuring out LTS releases.

@oli-obk
Copy link
Contributor

oli-obk commented Jul 12, 2018

Serde is already using cfgs set by a build.rs file to automatically enable features depending on the rustc version. While direct cargo support for that seems neat, the way you described it seems to me like old rustc versions could not update their serde dependency anymore. Currently serde keeps adding features that are enabled by default and work on old rustc versions. The features requiring newer rustc versions are independent from the serde version.

Cc @dtolnay

@cuviper
Copy link
Member

cuviper commented Jul 12, 2018

You'd have to start that baseline from a Cargo that understands compiler dependencies, and from there on your "old" minimum toolchain will know to avoid newer versions of the dependency.

@alexcrichton
Copy link
Member

Er sorry, I don't mean to detract too much from this RFC about LTS releases! I mostly wanted to point out that I personally believe there's different (and what I see as better) solutions for rustc version compatibility in the ecosystem not attached to LTS releases at all, hopefully addressing @aturon's blocking concern for postponing this RFC right now

@aturon
Copy link
Member

aturon commented Jul 12, 2018

@ashleygwilliams Thanks so much for the elaboration! I definitely agree with the rationale as a whole -- my sole concern is making sure we have an adequate story for advancing core libraries with the Edition.

Several folks are raising the "MRV" approach (where Cargo's resolver is sensitive to the Rust version). Before @withoutboats wrote this RFC, the two of us sat down with @wycats and talked through that approach. We concluded that it had some major pitfalls, but I don't recall the details offhand -- but I'm hoping @withoutboats can fill them in.

So, to be clear: I'm 100% fine postponing on the basis you described, as long as the core team otherwise has a reasonable plan for libraries moving their version requirement forward around the Edition.

@newpavlov
Copy link
Contributor

@aturon
Can you or @wycats (or @withoutboats?) please comment in #2495 on those "major pitfalls" you've mentioned?

@aturon
Copy link
Member

aturon commented Jul 26, 2018

@newpavlov Sorry it took so long, but instead of a comment, I've written a blog post :-)

@kbknapp
Copy link

kbknapp commented Jul 26, 2018

Here's some relevant comments from a reply I made on reddit to @aturon's excellent blog:

Here's my experience, as Minimum Supported rustc Version (MSRV) has been a major concern for me, and at times a major headache.
I feel conflicted between two camps. On the one hand I want to use the newest and shiniest features, some of which have direct impacts on the ergonomics or performance of my crates. However, my crates are nothing without their users. And many users simply cannot update their rustc at will to the latest and greatest stable version.
I personally work in an environment with incredibly lethargic update processes due to having to use "certified" (via internal audit) versions of software and libraries. Once something has been certified for use, you have to have a very good reason to increase that version to something new (which spawns a whole new audit phase). So I very much get the pain of not being able to update your rustc like you'd want. I also understand the core team's desire to have everyone on coherent Rust story. This is why I'd like it acknowledged that there are places where updating stable every 6 weeks simply can't happen (Government, public service, high security, etc, etc.) and there should be some tooling or guidelines to deal with these areas that aren't going away.
[...]
[...] So why not just let [...] any other system which requires older rustc versions package an older version of the application (which in turn requires an older clap) and always use the latest stable for the latest clap? [...] what this leads to is users on old rustc versions requesting bug fixes which are already fixed in newer versions of clap.
I'm a single person, working on these projects in my spare time. As much as I'd love to, I can't maintain bug-fixes on multiple branches back-ported to old versions which support older rustcs. It's just not feasible for me. I'd try to make exceptions for security related bugs, but beyond that I just don't have the bandwidth.
So I'm left with the choice of sticking with an old rustc which is hopefully a common denominator between as many clap users as possible at the expense of some ergonomics (typically just internal ergonomics though), or sticking with a newer stable rustc and potentially isolating or losing users who can't update. I pick the former without hesitation.
[...]
Having a single concrete version to target would be a dramatic improvement (even for my auditing reviewers at work, having a single version to look at every 6-12 months).

To me, LTS could even simply mean a single concrete version marketed as, "if you're going to stick to old versions use this one." And receives security/soundness updates only (as point releases).

@kbknapp
Copy link

kbknapp commented Jul 26, 2018

@alexcrichton : think that instead this problem is best tackled from a different direction. I've often heard that if Cargo on rustc 1.24 (for example) would simply not select versions of Serde (for example) that doesn't build on 1.24 then this would largely be a solved problem. In this sort of world Serde would be able to use any language feature it wanted, and older Cargos would only ever use a version of Serde that their coupled version of rustc understands.

This still leads to the problem above where users on old rustc versions want things (features/bug fixes) back-ported to their version of serde. Serde's only answer can be, "Well if want said fixes/features use a newer rustc." Which I don't think is a good answer, or even always possible. Also without a single mass marketed "LTS" rustc it's an arbitrary guess as to which one most of your users need/use.

There's also all the cfg and build.rs hacks we can use to back port things and "magically" make everything work...but it's super hacky IMO and I'd prefer to put that energy into the lib itself instead of working around language version issues 😜

@Ixrec
Copy link
Contributor

Ixrec commented Jul 27, 2018

To me, LTS could even simply mean a single concrete version marketed as, "if you're going to stick to old versions use this one."

Agreed. In fact, I think this is the only clear and useful meaning of "LTS" (it's certainly the only one I've heard expressed so far).

I also agree with @aturon's post's argument that even if we introduce some MSRV mechanism, we're still going to need an "LTS" in that sense, if only because of users that simply aren't allowed to upgrade whenever they want.


I think the key question for this RFC now is: for those of you in industries with audits or whatever that effectively forbid you from updating your toolchains every six weeks, how often can/do you update? I have a vague impression that "annually" is probably the slowest update frequency we really need to support, but we clearly need more confidence than that.

@Ixrec
Copy link
Contributor

Ixrec commented Jul 27, 2018

I guess we could also bikeshed possible terminology alternatives to "LTS".

With most software, I tend to assume there's a "stable" and a "not-so-stable" and that I always want the "stable" unless I'm the kind of hardcore power user that would actually read the release notes and educate myself on the new features and so on every time that specific program had an update. So "LTS" tends to sound like "the stable one" to me, even if there's some other version officially referred to as "stable".

Obviously, we don't want most users of Rust sticking to an LTS release when stable is fine for them. Moreover, hardcore power user-ness has nothing to do with whether you should be on LTS vs stable (maybe stable vs nightly, but not LTS), so maybe we want to think about terms that might avoid giving off the "use this if you just want stuff to work" impression that "LTS" gives me personally (or is that just me?). Unfortunately I have no ideas yet.

@johnthagen
Copy link

I recently read in the clap documentation:

clap will officially support current stable Rust, minus two releases, but may work with prior releases as well.

As a stepping point to LTS releases in the short term, maybe the Rust community could come to some consensus on a guideline for what version of stable Rust is a good target for library compatibility. Basically a guidelines for N in stable - N.


An example (where the actual N numbers could vary):

While library authors are free to support whichever versions of Rust they choose, the community has reached general consensus about the following guidelines for the minimum supported Rust to be a good balance between backwards compatibility and keeping crates up-to-date with the latest Rust idioms.

The suggested compatibility in ascending levels, where each is more conservative:

  • Level 1: stable - 4
  • Level 2: stable - 8
  • Level 3: stable - 16

@Centril
Copy link
Contributor

Centril commented Sep 20, 2018

I still think it would be beneficial to improve the story around conditional compilation in light of LTS versions. However, that is mostly orthogonal and can be solved separately. And to be more constructive, I will consider some solutions to that problem and possibly propose one.

I have now proposed this in #2523. :)

@withoutboats
Copy link
Contributor Author

So I proposed this specifically in connection to edition 2018. Since its clearly not going to be part of our story about how we get libraries to upgrade to the new edition, it no longer has that urgency. I'm closing this RFC now and we can revisit LTS support some time in the future.

@rfcbot rfcbot removed proposed-final-comment-period Currently awaiting signoff of all team members in order to enter the final comment period. disposition-postpone This RFC is in PFCP or FCP with a disposition to postpone it. labels Oct 11, 2018
@Centril
Copy link
Contributor

Centril commented Nov 20, 2018

Relevant: https://www.reddit.com/r/rust/comments/9yub0a/red_hat_support_lifecycle_for_clangllvm_go_and/

While we don't have time to do this for the edition release, I think it would be nice to consider this for 4 (so that it coincides...) versions or so after the edition release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-core Relevant to the core team, which will review and decide on the RFC.
Projects
None yet
Development

Successfully merging this pull request may close these issues.