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

MSRV policy for libc crate #72

Open
joshtriplett opened this issue Jul 17, 2022 · 215 comments
Open

MSRV policy for libc crate #72

joshtriplett opened this issue Jul 17, 2022 · 215 comments
Labels
T-libs Relevant to the libraries subteam, which will review and decide on the PR/issue.

Comments

@joshtriplett
Copy link
Member

joshtriplett commented Jul 17, 2022

In a previous libs team meeting, we discussed MSRV policy for the libc crate, and we debated between an N-1 policy and a slightly more conservative policy such as N-3 or N-4. We ended the meeting without having settled on a specific consensus, though it seemed like we were roughly on the same page.

Rather than make ad-hoc changes based on a non-specific MSRV policy, I think we should go ahead and nail down an MSRV policy for present and future changes.

I'd like to propose the following concrete policy:

  • Support the last three stable versions of rustc (stable and the prior two versions).
  • Only bump MSRV when we use a feature requiring newer Rust. (We do not systematically bump MSRV each time a stable release occurs.)
  • Treat MSRV increases as an ordinary change, not a breaking change.

Note that this is a policy proposal for libc, not for other crates maintained by the libs team. After we get consensus on an MSRV policy for libc, we can consider what policy we want for other crates. Nonetheless, libc MSRV policy seems likely to serve as a defacto lower-bound for supported Rust versions among other libs team crates, and among many crates in the ecosystem.

For further information on the benefits of this: the PR dropping support and version detection for older versions of rustc was able to remove ~1600 lines of code, and that's not counting subsequent work that may be able to drop some of the wrapper macros. This represents a substantial improvement to maintainability, and may make it easier in the future to move to more automation to keep libc updated with the latest platform APIs.

@joshtriplett
Copy link
Member Author

@rfcbot merge

@rfcbot
Copy link

rfcbot commented Jul 17, 2022

Team member @joshtriplett has proposed to merge this. The next step is review by the rest of the tagged team members:

Concerns:

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@petrochenkov
Copy link

This is such an unreasonably short support window for a foundational crate like libc.
I would expect at least couple of years of supported versions instead of N-3,4

@thomcc
Copy link
Member

thomcc commented Jul 17, 2022

Yeah it's a bit tough, since this impacts a lot of crates that have libc in their dep tree. I think being conservative here is worthwhile, unfortunately.

One danger here is if a lot of crates end up pinning libc versions (which they shouldn't1, but in practice is the tool many people reach for), those crates become incompatible to use with eachother.

Footnotes

  1. Allowing users with a lockfile to deal with it via cargo update --precise is better.

@joshtriplett
Copy link
Member Author

@petrochenkov Assume, for the moment, that we aren't looking to support the use case of "run brand new crates from crates.io on a multi-year-old snapshot of rustc/cargo in an enterprise distribution". Are there any other use cases for which "couple of years" is actually a specific end-user need? Not something where crate-author asks crate-author asks crate-author based on hypotheticals, but actual end users who have an old rustc, and a need for new crates, and no better options?

@joshtriplett joshtriplett added the I-libs-api-nominated Indicates that an issue has been nominated for discussion during a team meeting. label Jul 17, 2022
@BurntSushi
Copy link
Member

BurntSushi commented Jul 18, 2022

My instinctual response to this is also, frankly, that N-4 is too aggressive. But:

Are there any other use cases for which "couple of years" is actually a specific end-user need? Not something where crate-author asks crate-author asks crate-author based on hypotheticals, but actual end users who have an old rustc, and a need for new crates, and no better options?

I basically don't have a great concrete answer to this. And I will say, I've personally been looking for one for a while. Any time someone tells me about wanting crates to compile with older versions of Rust, I always try to ask: why? From memory, I've basically gotten these answers:

  1. "I did sudo apt-get install rustc cargo, cloned your repository and then tried to run cargo build." In effect, they are trying to port workflows that they expect to work (probably from other language ecosystems) to Rust, and then get miffed that compilation breaks. Sometimes this even translates into errant bug reports. (Although, I think that's largely solved by Cargo's rust-version feature, once I get around to using it.) I also think people interpret this as a signal that Rust is "too unstable," in the sense that too many people are using language features that require a very new compiler. My experience is that most C or C++ libraries don't do this, and tend to update their language version (e.g., C++11 to C++14) pretty conservatively. So even folks using a conservative Linux distro will be able to do the apt-get install foo and then build random projects using foo. But for Rust, that doesn't really work. Instead, they really have to go use rustup, which is just going to be foreign to lots of folks not familiar with the Rust ecosystem.
  2. "My company pins its Rust version in CI and it takes a lot of resources to upgrade." I've only heard this one once or twice, and I didn't really get a ton of details out of it. The obvious question to ask here, then, is whether they in turn need to use crates that require a new Rust. My recollection (I couldn't find a record of the discussion) is that the Rust ecosystem moved so fast relative to how often they upgraded their Rust compiler that it was not uncommon for them to try to bring in a crate and then have it fail to compile on their version of Rust. I don't recall drilling into this any more, e.g., why they couldn't "just" use old versions of crates. (Which does seem pretty annoying to me.) I think the overall impression I got was that this just wasn't typically a problem for them when using C or C++.

I think (1) is basically some combination of an awareness/workflow/perception problem. I think there's probably something to (2), but I just don't know enough concrete details about any specific use case to really know for sure. And in particular, I suspect (2) is kind of also a perception problem. Both (1) and (2) seem somewhat rooted in the idea that Rust and its ecosystem move so much faster than the things it tends to supplant that it tends to be really noticeable.

Now I do think perception problems are real problems, but I'm not convinced they reflect concrete use cases that argue strongly for a conservative MSRV policy. (By "conservative," I'm thinking that there is roughly support for N-9 releases, i.e., one year.)

Note that this is a policy proposal for libc, not for other crates maintained by the libs team. After we get consensus on an MSRV policy for libc, we can consider what policy we want for other crates.

OK, so I think this is really where my real concern with this change is. libc is basically as foundational as you can get as a library. Deciding an MSRV policy for it comes very close to effectively deciding an MSRV for the broader ecosystem. IMO, even if the MSRV is really just a perception problem, that's a pretty big deal. (I say "very close," because as @thomcc mentioned, if people hate this enough, they'll starting pinning libc and then that's going to be a cure that is worse than the disease. So technically, users of libc can still enforce their MSRV by either pinning libc in libraries (very bad) or pinning libc in their Cargo.lock (which is totally fine). But other than that, libc will end up deciding the MSRV for a lot of folks I think.)

Since libc is foundational and because I suspect this policy is probably more aggressive than extant MSRV policies in the ecosystem (being a little hand wavy there), I do think that we should try to broadcast this policy question before making a final decision on it. That is, I would like to make a good faith effort to give folks an opportunity to provide their opinion on this because of the impact this will have on the broader ecosystem. Basically, I want to avoid a scenario where this happens:

  • We do an FCP here and because relatively few people watch this repo, it passes silently.
  • The libc MSRV policy is put into place.
  • Six months from now, we finally have a need to "test" the policy because there's this new Rust feature or API that was introduced in Rust N-4. So that gets merged and shipped out.
  • A bunch of people who care about MSRV realize that the new release of libc has almost nearly forced them to make their policy more aggressive than what they had end up asking what's going on in the libc tracker.
  • They get pointed to this issue and wonder why such a change wasn't broadcasted more widely so that they could have the opportunity to have their voice heard.

Maybe I'm overplaying it, but that's my sense. So I'll register a concern for that:

@rfcbot concern opportunity for ecosystem to give feedback

Otherwise, for me personally, I don't think I feel strongly for or against this change. I've long wanted good reasons for a conservative MSRV policy, and I've had a hard time finding them. Maybe this issue will force out some good ones that I've not heard of before. But I can definitely empathize with the annoyance of having to wait so long to use new Rust stuff, so I get where this is coming from.

@joshtriplett
Copy link
Member Author

Note that this is a policy proposal for libc, not for other crates maintained by the libs team. After we get consensus on an MSRV policy for libc, we can consider what policy we want for other crates.

OK, so I think this is really where my real concern with this change is. libc is basically as foundational as you can get as a library. Deciding an MSRV policy for it comes very close to effectively deciding an MSRV for the broader ecosystem.

I was attempting to narrow the question to libc, not because I think it likely that other official crates can or should realistically be more conservative than libc, but rather, I wanted to separate the questions so that if someone wanted to argue "we should support X" they didn't have to simultaneously argue whether that meant X for libc or for everything.

If we do agree on N-2 for libc, then our realistic choices of policies for other official crates are N-2, N-1, or N. I'd tend to suggest N-2 for "foundational" crates like libc or libz-sys.

@petrochenkov
Copy link

petrochenkov commented Jul 18, 2022

  1. "My company pins its Rust version in CI and it takes a lot of resources to upgrade."

I more or less meant this scenario.
In my case it was more like "several teams need to build the code in several infras, and asking others to update their infra too often is a nuisance because they have other more important things to do, so in practice the required Rust toolchain gets updated once in 0.5-1.5 years".

Crate versions still can be updated more often because it doesn't require similar coordination.
Also few crates change MSRV that often in practice so most of the dependencies still build in a year and don't need to be pinned to prevent updates. So the N-3,4 policy actually makes libc move much faster than majority of other less fundamental crates.

@shepmaster
Copy link
Member

So the N-3,4 policy actually makes libc move much faster than majority of other less fundamental crates.

Not necessarily, but only possibly:

Only upgrade if there's a feature we actually need.

It just means that libc could bump the MSRV if needed. As you said...

few crates change MSRV that often in practice

@BurntSushi
Copy link
Member

@petrochenkov Can you say more please? Here are the things I'm personally interested in:

  • Why do you think it's justified for the (probably the entire) Rust project to spend effort maintaining a conservative MSRV because it is costly for y'all to upgrade? To me, it feels like this hinges a lot on just how common your scenario is. Like, what scale of problem is this? Is this a "I'm a little annoyed" flavor of problem, or is this a "we'll probably have to stop using Rust" showstopping problem?
  • If upgrading Rust is really that costly, can you say more about why using older versions of crates isn't an acceptable alternative path for you?

@shepmaster

So the N-3,4 policy actually makes libc move much faster than majority of other less fundamental crates.

Not necessarily, but only possibly:

Only upgrade if there's a feature we actually need.

It just means that libc could bump the MSRV if needed. As you said...

few crates change MSRV that often in practice

I think you're technically correct, but I think the color you're adding here might give the wrong impression. There's a burden to supporting older MSRVs, and while @joshtriplett's post does include the language "Only upgrade if there's a feature we actually need," I think the word "need" there is doing a lot of work. For example, "need" might mean, "we want to use a new std API and don't feel like writing version sniffing code in build.rs to do conditional compilation" or it might mean "we have so much version sniffing already that adding more is just not worth the burden" or it might mean "we want to use a new Cargo.toml feature and there's no easy way of introducing such things conditionally." Frankly, all three are somewhat reasonable interpretations, but it's not totally clear which one will be followed in practice to me. So it might worth clarifying what exactly is meant by "need" here.

For example, if "need" is interpreted broadly, then I think it's very likely that libc will end up bumping MSRV more rapidly than existing "core" crates. But if "need" is interpreted narrowly, then it might actually be pretty rare for libc to bump MSRV.

@BurntSushi
Copy link
Member

Someone else I'd like to hear from is @dtolnay. As I understand it, you maintain a Rust 1.13 MSRV for serde. This is despite requiring at least some non-trivial effort to do so. I don't think I've seen you opine on why exactly you do this. Could you share your perspective here?

@BurntSushi
Copy link
Member

(Also, I have not actually broadcast this issue to a wider audience yet. Are people okay if I do that? Or do folks think we should wait on that for a bit or go about it a different way? As a former mod, I always feel a little weird shining spotlights on GitHub issue threads, since it can go sideways pretty easily.)

@petrochenkov
Copy link

@BurntSushi

Why do you think it's justified for the (probably the entire) Rust project to spend effort maintaining a conservative MSRV because it is costly for y'all to upgrade?

Because it's not that much effort in practice.
It's "some extra maintenance in libc alone" vs "some extra maintenance for all the people with slower Rust toolchain update schedules", the choice seems pretty clear to me.

If upgrading Rust is really that costly, can you say more about why using older versions of crates isn't an acceptable alternative path for you?

It's acceptable, and the issue is not a showstopper, but newer crate versions are not purely cosmetic and do fix relevant bugs sometimes (or add relevant Linux constants or whatever, in case of libc).

@BurntSushi
Copy link
Member

Because it's not that much effort in practice.

Eh. The libc build.rs is pretty gnarly, and all of those cases get turned into conditional compilation knobs that get sprinkled throughout the code. I know I'm pretty averse to doing that (I've done it before on several occasions), so I end up just usually waiting to use a new feature in cases where I've tried to maintain a "conservative" MSRV.

It's doubly annoying because finding real tangible use cases for conservative MSRV has proven difficult. So it just feels like a lot of hand wringing for... not much in exchange.

It's "some extra maintenance in libc alone"

Certainly not! It's extra maintenance for everyone who tries to maintain a conservative MSRV. If libc got more aggressive about it, it might spur everyone else to get more aggressive too, thus reducing maintenance burden for a whole bunch of folks. Whether that's bigger or smaller than the "people with slower Rust toolchain update schedules" is actually totally unclear to me. I have no idea how widespread "slow toolchain update schedules" is in practice. I'm sure it's not just you (I've heard of others complaining about it), but I truly do not know the scale of it.

@shepmaster
Copy link
Member

I think you're technically correct, but I think the color you're adding here might give the wrong impression.

I was not attempting to add color, or even opinions, just surface the wording concerns which you have now expanded upon.


For SNAFU, I maintain a Rust 1.34 MSRV, although I don't use a build.rs for newer versions. Instead, I use feature flags for each version that I need and use default features to enable a "new enough" version of Rust. This places the burden on people who want to use SNAFU with an "old enough" version of Rust, while still allowing a wide range of Rust versions to use SNAFU.

This works for me because I can write the majority of my code targeting old Rust versions. This does mean I'm locked to edition 2018, among other things, but that isn't amazingly painful for me in practice.

I have received feedback from Linux distro users that are using old versions of Rust so I know that there are real people out there affected by this.


Is there a list of what "new Rust" features the libc crate would like to make use of?

@cuviper
Copy link
Member

cuviper commented Jul 18, 2022

  1. "I did sudo apt-get install rustc cargo, cloned your repository and then tried to run cargo build." In effect, they are trying to port workflows that they expect to work (probably from other language ecosystems) to Rust, and then get miffed that compilation breaks. Sometimes this even translates into errant bug reports. (Although, I think that's largely solved by Cargo's rust-version feature, once I get around to using it.) I also think people interpret this as a signal that Rust is "too unstable," in the sense that too many people are using language features that require a very new compiler. My experience is that most C or C++ libraries don't do this, and tend to update their language version (e.g., C++11 to C++14) pretty conservatively. So even folks using a conservative Linux distro will be able to do the apt-get install foo and then build random projects using foo. But for Rust, that doesn't really work. Instead, they really have to go use rustup, which is just going to be foreign to lots of folks not familiar with the Rust ecosystem.

I totally understand that folks in the Rust ecosystem generally don't want to support traditional distro toolchain timelines, especially in enterprise where that can stretch 10 years or more. However, I do want distro Rust toolchains to be a viable option, and for RHEL we've tried to make that happen by keeping a more aggressive "rolling stream". That doesn't mean we ship every 6-week Rust release, but we do update the Rust toolchain in each RHEL minor release, every 6 months. (I also maintain Fedora's Rust, and we do ship every update there on all active releases.)

Now, with our own internal development pipeline, the version we put out in a RHEL minor release will already be 3-4 months old when it comes out. That's our latest version for the next 6 months, so it will be 9-10 months old by the time the next one comes around. For example, in May 2022, RHEL 8.6 and 9.0 shipped Rust 1.58, and those will be in use until 8.7 and 9.1 around November.

People also don't upgrade RHEL releases right away. Conservatively, padding that out to a year for an MSRV update policy is probably good enough, and if they still haven't updated they'll have some impetus. And FWIW, we did choose a one-year MSRV policy for rayon (although it's currently sitting quite a bit older).

I know many people won't care about RHEL, but we're trying to find a good compromise there.

2. "My company pins its Rust version in CI and it takes a lot of resources to upgrade."

I more or less meant this scenario. In my case it was more like "several teams need to build the code in several infras, and asking others to update their infra too often is a nuisance because they have other more important things to do, so in practice the required Rust toolchain gets updated once in 0.5-1.5 years".

And in some cases, this sort of case is also "outsourced" to the distro update process.

@saethlin
Copy link
Member

As someone who delivers software written in Rust to RHEL environments, I would really like to hear from users who are developing on RHEL using the distro rustc/cargo instead of rustup. We jump through hoops to deliberately avoid using distro packages when possible, on account of their age.

@cuviper
Copy link
Member

cuviper commented Jul 18, 2022

I don't have hard customer data to offer here, but I think there's also a chicken-and-egg problem, that Rust won't even be a viable option for those customers at all if the ecosystem won't support this kind of use.

@saethlin
Copy link
Member

saethlin commented Jul 18, 2022

I mean for our usage, the rest of RHEL packages are an obstacle, so we never even considered using a Rust toolchain from the distro. So I wonder if this is a more severe chicken-egg scenario.

@cuviper
Copy link
Member

cuviper commented Jul 18, 2022

Fair enough. :)

@alex
Copy link
Member

alex commented Jul 20, 2022

I'm one of the maintainers of pyca/cryptography, a popular Python package (top 20 downloads from PyPI most days) with a risk component. I can provide some limited stats on versions of Rust we see.

Our current MSRV is 1.41, and our next release intends to increase our MSRV to 1.48.

Looking at downloads of our source artifacts (i.e., users who need to compile themselves, excluding pre-compiled artifacts) we have rustc version data for about 1.6% of those downloads (because tracking this information requires a relatively recent pip).

Here is the % of such downloads where the rustc version is >= to each target, from the past 30 days:

1.41.0: 99.6%
1.42.0: 97.2%
1.43.0: 97.2%
1.44.0: 97.2%
1.45.0: 95.9%
1.46.0: 95.9%
1.47.0: 95.9%
1.48.0: 95.7%
1.49.0: 91.3%
1.50.0: 90.3%
1.51.0: 90.3%
1.52.0: 90.2%
1.53.0: 89.7%
1.54.0: 89.4%
1.55.0: 89.2%
1.56.0: 89.2%
1.57.0: 87.4%
1.58.0: 86.6%
1.59.0: 75.7%
1.60.0: 48.9%
1.61.0: 40.3%
1.62.0: 20.5%

Hopefully this presentation of the data makes sense.

@m-ou-se
Copy link
Member

m-ou-se commented Jul 20, 2022

If/once cargo can use the rust-version from Cargo.toml to automatically pick the latest version that works on the compiler that's used, this could go a lot smoother. Then if libc 0.2.135 requires Rust 1.70, cargo will just pick libc 0.2.134 for users on Rust 1.69, such that nothing breaks that didn't need the latest libc.

@matklad
Copy link
Member

matklad commented Jul 20, 2022

Two scenarios for "My company pins its Rust version in CI and it takes a lot of resources to upgrade." I've seen personally:

  • slipped upgrades: Rust version is pinned in rust-toolchain.toml for reproducibility and general sanity reasons. There's a process in place to upgrade that version to the stable rust, but, as everything is broken, sometimes the things slip and no one gets to actually upgrading the toolchain in a couple of months.
  • pinned nightly: some part depends on nightly b/c something is not stabilized. As this is nightly, upgrades are actually non-trivial (code changes required), and get somewhat postponed.

The problem with "just using older versions of crates" is that sometimes you want to upgrade something for unrelated reason. Like, you use "latest-async-framework-my-company-fork-5.0.0.beta.8", and you want to switch to "latest-async-framework-5.0.0" b/c that has much fewer bugs, and, while doing that work, you discover you need to upgrade rustc as well.

For both of these scenarios as I've encountered them, N-1 would create measurable pain, N-4 would be OK, and N-8 would be very comfortably OK.

@CAD97
Copy link

CAD97 commented Jul 20, 2022

A minor thing is build caching. When using a shared Rust compilation cache, it's nice to be able to stay on a specific toolchain for longer, because then you get fewer rebuilds. This is maybe a less important reason for libc, though, as upgrading libc means recompiling much of the world anyway.

(And as a sidenote: it's naive to say that this policy is just for libc. libc's msrv policy basically is the baseline msrv policy for the entire ecosystem... at least for msrv at maximal dependency versions.)

It's definitely worth polling major ecosystem crates for what their msrv policy is and for what users they hold that policy. E.g. tokio has committed to a 6 month msrv through 2024 at a minimum.

Plus it's worth restating: a rust-version aware version resolution will make msrv bumping much smoother.

msrv musings

At least from my viewpoint, the realistic msrvs are

timeline usecase
forever for managing msrv
distro to support source installs on distro
3 year glacier pace / previous edition
1 year foundational crate with low need for new language features
6 month reasonable LTS compromise for core libraries
3 month reasonable lead time for most libraries

But also, it's imho silly to try to enforce msrv without an msrv supporting dependency resolution. Right now, the best we have is -Zminimal-versions, and libraries ideally should be testing with that anyway to ensure their manifests are accurate. For consumers, the default maximal versions avoiding too-new rust-version basically unlocks msrv from essentially being ecosystem-wide to being a localizable concern.

@BurntSushi
Copy link
Member

(And as a sidenote: it's naive to say that this policy is just for libc. libc's msrv policy basically is the baseline msrv policy for the entire ecosystem... at least for msrv at maximal dependency versions.)

Yeah I think @joshtriplett and I discussed this briefly above. I think that's the idea behind considering the MSRV policy for libc first. It starts with the most expansive question.

@joshtriplett
Copy link
Member Author

joshtriplett commented Jul 20, 2022

@alex Thank you, that's useful information. Would it be possible to get, rather than the last 30 days, three chunks of this information? Specifically: 2022-04-07 to 2022-05-19 (while 1.60 was newest), 2022-05-20 to 2022-06-30 (while 1.61 was newest), and 2022-07-01 to today (while 1.62 was newest)?

It would help to see how much correlation that has. (Which in turn will depend on how many of your users get rust from rustup vs a distribution package; I would guess many do, but this will at least give us a conservative bound to consider.)

Also, what does

relatively recent pip

mean here? How old is that version of pip? (We'd like to take into account the possible bias towards recent versions there.)

@epage
Copy link

epage commented Jul 20, 2022

Only upgrade if there's a feature we actually need.

One downside to an as-need basis is if you upgrade too infrequently, your users might build up an expectation that diverges from what is documented. clap has always had an N-2 policy but went so long without updating the MSRV that we got backlash when updating our MSRV to something less than a year old.

@matklad
Copy link
Member

matklad commented Jul 20, 2022

If/once cargo can use the rust-version from Cargo.toml to automatically pick the latest version that works on the compiler that's used, this could go a lot smoother.

One effect here is that we might weaken ecosystem-wide "live at HEAD" property. Today, the world mostly looks like this:

  • libraries support at least some old versions, and, regardless of specific "slightly outdated rustc", any application can be upgraded to the latest version of all libraries, and, in general, most folks try to stick with latest version. So, "latest version of everything" is a mostly well-tested integration scenario.
  • in the world where Cargo just transparently picks old versions of libraries, and libraries default to latest stable, there will be more heterogenity to what ends up in Cargo.lock after cargo upgrade

No idea what's the size of the effect here.

@faho
Copy link

faho commented May 10, 2024

Since the last comment the libc crate has increased MSRV to 1.71 in rust-lang/libc#3525.

This is a bit awkard for us on the https://github.com/fish-shell/fish-shell side because we just decided on 1.70 to facilitate the next Debian Stable building fish with their package, which appears to be 1.70 (in fact we increased MSRV from 1.67). There are a bunch of distributions with 1.70, see repology for details.

I'm not sure if I should file an issue on libc to ask them to reduce MSRV to 1.70 - I can't find any discussion on the change, so I don't know what led to 1.71 specifically (the PR also doesn't show any specifics for 1.70 vs 1.71, I think?), but I'm also not very "plugged in" to the rust ecosystem or the libc crate.

@djc
Copy link

djc commented May 10, 2024

As I just commented in that PR, it's surprising to me that the MSRV for such a foundational crate is bumped in a PR that doesn't reference any discussion on what the new MSRV should be. (Personally I also think this issue should have had a pointer to such a discussion prior to the PR being merged.)

@Thomasdezeeuw
Copy link

So basically this RFC went through (effectively), even though according to #72 (comment) there is no consensus on it?

I completely understand the want to bump the MSRV, as a maintainer myself I've the MSRV issue a couple of times and it's a pain in the behind. But I don't think this is the way to do it to be honest. We have entire discussion only to go around it do it any way...

Not going to lie, it a little disappointing to see. Especially for a crate that is so fundamental.

@Amanieu
Copy link
Member

Amanieu commented May 10, 2024

rust-lang/libc#3525 only applies to the v1.0 branch (main) which is not released yet. The v0.2 branch still has the old MSRV.

@BurntSushi

This comment was marked as duplicate.

@faho
Copy link

faho commented May 10, 2024

Ah, cool, I must have misinterpreted what branch I was on (we don't really do long-lived branches so I sometimes forget to check). That also explains why the version in Cargo.toml threw me off.

Anyway, consider me someone who'd like to see a pretty conservative MSRV policy (but then there's a massive culture shock in that I'm used to using C++11 in 2020 because asking users to upgrade compilers is too much)

tgross35 added a commit to tgross35/rust-libc that referenced this issue Nov 15, 2024
Currently this crate maintains the `main` branch (future 1.0) alongside
`libc-0.2` (current stable release). PRs are made against `main` then
cherry picked as applicable to `libc-0.2`.

Usually this flow works okay, but there is a substantial difference in
minimum supported versions: libc-0.2 is tested down to 1.19 and main is
tested with 1.63. This means that supported features differ quite a bit
and as a result, cherry picks get conflict-heavy (e.g. `repr(align)`,
`union`, and `const fn` cannot be used on `libc-0.2`).

In order to make it easier to keep these branches in sync and get us
close to a 1.0 release, raise the MSRV on `libc-0.2` to 1.63. This means
both branches can run the exact same tests.

This still does not establish a MSRV policy, which has been discussed at
great length in [1]. For the purpose of unsticking us this selects 1.63
as the MSRV, which is the version currently available on Debian stable
(a commonly requested reference point in [1], and about the oldest
specific version mentioned).

This is a documentation-only change to keep things simple, cleanup can
follow. Further increases and official policy are not precluded.

An attempt to raise the MSRV to 1.57 in 2022 was approved at one point
[2], but never merged due to various failures. Making this a
documentation-only change hopes to avoid this problem.

I brought up a 0.3 release to increase versions in [3], but consensus
there was that we should be able to increase the MSRV in the existing
0.2 release without a semver-breaking change.

Link: rust-lang/libs-team#72 [1]
Link: rust-lang#2845 [2]
Link: rust-lang/libs-team#463 [3]
tgross35 added a commit to tgross35/rust-libc that referenced this issue Nov 15, 2024
Currently this crate maintains the `main` branch (future 1.0) alongside
`libc-0.2` (current stable release). PRs are made against `main` then
cherry picked as applicable to `libc-0.2`.

Usually this flow works okay, but there is a substantial difference in
minimum supported versions: libc-0.2 is tested down to 1.19 and main is
tested with 1.63. This means that supported features differ quite a bit
and as a result, cherry picks get conflict-heavy (e.g. `repr(align)`,
`union`, and `const fn` cannot be used on `libc-0.2`).

In order to make it easier to keep these branches in sync and get us
close to a 1.0 release, raise the MSRV on `libc-0.2` to 1.63. This means
both branches can run the exact same tests.

Context
=======

This still does not establish a MSRV policy, which has been discussed at
great length in [1]. For the purpose of unsticking us this selects 1.63
as the MSRV, which is the version currently available on Debian stable
(a commonly requested reference point in [1], and about the oldest
specific version mentioned).

This is a documentation-only change to keep things simple, cleanup can
follow. Further increases and official policy are not precluded.

History
=======

An attempt to raise the MSRV to 1.57 in 2022 was approved at one point
[2], but never merged due to various failures. Making this a
documentation-only change hopes to avoid this problem.

I brought up a 0.3 release to increase versions in [3], but consensus
there was that we should be able to increase the MSRV in the existing
0.2 release without a semver-breaking change.

Link: rust-lang/libs-team#72 [1]
Link: rust-lang#2845 [2]
Link: rust-lang/libs-team#463 [3]
tgross35 added a commit to tgross35/rust-libc that referenced this issue Nov 15, 2024
Currently this crate maintains the `main` branch (future 1.0) alongside
`libc-0.2` (current stable release). PRs are made against `main` then
cherry picked as applicable to `libc-0.2`.

Usually this flow works okay, but there is a substantial difference in
minimum supported versions: libc-0.2 is tested down to 1.19 and main is
tested with 1.63. This means that supported features differ quite a bit
and as a result, cherry picks get conflict-heavy (e.g. `repr(align)`,
`union`, and `const fn` cannot be used on `libc-0.2`).

In order to make it easier to keep these branches in sync and get us
close to a 1.0 release, raise the MSRV on `libc-0.2` to 1.63. This means
both branches can run the exact same tests.

Future Changes
==============

This still does not establish a MSRV policy, which has been discussed at
great length in [1]. For the purpose of unsticking us this selects 1.63
as the MSRV, which is the version currently available on Debian stable
(a commonly requested reference point in [1], and about the oldest
specific version mentioned).

This is a documentation-only change to keep things simple, cleanup can
follow. Further increases and official policy are not precluded.

History
=======

An attempt to raise the MSRV to 1.57 in 2022 was approved at one point
[2], but never merged due to various failures. Making this a
documentation-only change hopes to avoid this problem.

I brought up a 0.3 release to increase versions in [3], but consensus
there was that we should be able to increase the MSRV in the existing
0.2 release without a semver-breaking change.

Link: rust-lang/libs-team#72 [1]
Link: rust-lang#2845 [2]
Link: rust-lang/libs-team#463 [3]
tgross35 added a commit to tgross35/rust-libc that referenced this issue Nov 15, 2024
Currently this crate maintains the `main` branch (future 1.0) alongside
`libc-0.2` (current stable release). PRs are made against `main` then
cherry picked as applicable to `libc-0.2`.

Usually this flow works okay, but there is a substantial difference in
minimum supported versions: libc-0.2 is tested down to 1.19 and main is
tested with 1.63. This means that supported features differ quite a bit
and as a result, cherry picks get conflict-heavy (e.g. `repr(align)`,
`union`, and `const fn` cannot be used on `libc-0.2`).

In order to make it easier to keep these branches in sync and get us
close to a 1.0 release, raise the MSRV on `libc-0.2` to 1.63. This means
both branches can run the exact same tests.

Future Changes
==============

This still does not establish a MSRV policy, which has been discussed at
great length in [1]. For the purpose of unsticking us this selects 1.63
as the MSRV, which is the version currently available on Debian stable
(a commonly requested reference point in [1], and about the oldest
specific version mentioned).

This is a documentation-only change to keep things simple, cleanup can
follow. Further increases and official policy are not precluded.

History
=======

An attempt to raise the MSRV to 1.57 in 2022 was approved at one point
[2], but never merged due to various failures. Making this a
documentation-only change hopes to avoid this problem.

I brought up a 0.3 release to increase versions in [3], but consensus
there was that we should be able to increase the MSRV in the existing
0.2 release without a semver-breaking change.

Link: rust-lang/libs-team#72 [1]
Link: rust-lang#2845 [2]
Link: rust-lang/libs-team#463 [3]
tgross35 added a commit to tgross35/rust-libc that referenced this issue Nov 15, 2024
Currently this crate maintains the `main` branch (future 1.0) alongside
`libc-0.2` (current stable release). PRs are made against `main` then
cherry picked as applicable to `libc-0.2`.

Usually this flow works okay, but there is a substantial difference in
minimum supported versions: libc-0.2 is tested down to 1.19 and main is
tested with 1.63. This means that supported features differ quite a bit
and as a result, cherry picks get conflict-heavy (e.g. `repr(align)`,
`union`, and `const fn` cannot be used on `libc-0.2`).

In order to make it easier to keep these branches in sync and get us
close to a 1.0 release, raise the MSRV on `libc-0.2` to 1.63. This means
both branches can run the exact same tests.

Future Changes
==============

This still does not establish a MSRV policy, which has been discussed at
great length in [1]. For the purpose of unsticking us this selects 1.63
as the MSRV, which is the version currently available on Debian stable
(a commonly requested reference point in [1], and about the oldest
specific version mentioned).

This is a documentation-only change to keep things simple, cleanup can
follow. Further increases and official policy are not precluded.

History
=======

An attempt to raise the MSRV to 1.57 in 2022 was approved at one point
[2], but never merged due to various failures. Making this a
documentation-only change hopes to avoid this problem.

I brought up a 0.3 release to increase versions in [3], but consensus
there was that we should be able to increase the MSRV in the existing
0.2 release without a semver-breaking change.

Link: rust-lang/libs-team#72 [1]
Link: rust-lang#2845 [2]
Link: rust-lang/libs-team#463 [3]
@ctz
Copy link

ctz commented Nov 27, 2024

I think it's a bit of a shame that after this gajillion pages of discussion, there's not a clear consensus or outcome.

I think it would be really great if there was some sort of collective, common MSRV policy that crate authors could adopt, and strikes a reasonable balance between the contending desires of crate authors and users. Most importantly, that would mean users can understand what they can expect from a crate's MSRV changes, and within what parameters they need to update their compiler version. At the moment, that is not feasible because they must understand the policy of each of their dependencies, severally and transitively.

(I'm aware of failed attempts to do this previously in rust-lang/api-guidelines, but that was more like "crates should have an MSRV policy" than "crates may adopt the standard N-minus-X MSRV policy as published by rust-lang/libs-team".)

(FWIW this comes out of rustls defining an MSRV policy for the first time, but I would have much preferred to pick one "off the shelf" and availed ourselves of some sweet, sweet economies of scale.)

@ChrisDenton
Copy link
Member

For libc, and some other foundational crates, the de facto policy currently appears to be "whatever Rust version ships with Debian stable". So up to three or so years old depending on where we are on Debian's release cycle.

For everyone else, I suspect we'll have to wait for a consensus to emerge amongst popular crates. I doubt the libs-api team will be able to lead in this (libc can force the issue but that's a sledgehammer). Maybe they can encourage crates to have an MSRV policy and push for a consensus that way.

@epage
Copy link

epage commented Nov 27, 2024

1.84 is also about to change the landscape with the MSRV-aware resolver. For example, I'm tempted to define an MSRV policy that is maintained by allowing bug fixes into old major or minor versions while the latest can be more flexible.

@jhpratt
Copy link
Member

jhpratt commented Dec 1, 2024

Definitely. Personally I'm really tempted to have a stable-only policy for my crates, assuming that if you're willing to use an older compiler that you're willing to use old versions of crates as well. Realistically I probably won't go that far, but it's best to let things settle out before trying to establish a more far-reaching recommended policy.

@algesten
Copy link

algesten commented Dec 1, 2024

Personally I'm really tempted to have a stable-only policy for my crates

I don't understand that position. Why would that be so appealing?

Rightly or wrongly there are people out there who can't use the standard tools like rustup.

With a central crate like time, you wield a lot of power in dictating how we all must relate to MSRV. Not only for end users, but also other library maintainers like myself. When you change MSRV, I must scramble to find workarounds for my crates to uphold my promises.

Of course this is unpaid works and no one is forced to use your code, but de-facto I am. Even if you don't agree with other people's way of handling Rust updates, or my MSRV policy, you could make a lot of peoples' lives easier by wielding that power less aggressively.

@jhpratt
Copy link
Member

jhpratt commented Dec 1, 2024

@algesten My comment was largely in response to the immediately preceding remark regarding the MSRV-aware resolver. Once that is widely used (i.e. once most people are on 1.84 or higher), it would be possible to provide all the benefit of newer language and stdlib features with minimal drawback. I'm well aware of the effective power I hold by maintaining a central crate in the ecosystem, which is why I am reluctant to bump it for small things.

When you change MSRV, I must scramble to find workarounds for my crates to uphold my promises.

That's not the case once the MSRV aware resolver is widely used 😄

@adamreichold
Copy link

adamreichold commented Dec 1, 2024

That's not the case once the MSRV aware resolver is widely used

Note that the MSRV-aware resolver does open another can of worms though: What if people on these old compilers need a bugfix that is only available in an MSRV-incompatible version? In other language ecosystems, I think this usually handled via maintenance branches/series which receive only bugfixes. So using the MSRV-aware resolver to increase the "MSRV velocity" of your trunk/head/tip might actually imply more maintenance work.

@jhpratt
Copy link
Member

jhpratt commented Dec 1, 2024

If someone is willing to forego bugfixes in the compiler and standard libray, they should be willing to do the same for crates imo. However this is getting a bit off-topic; I merely wanted to state that the MSRV-aware resolver hitting stable soon will very much influence MSRV policy.

@TheBlueMatt
Copy link

Given the standard library and compiler's sizes and broad use, bugs in them tend to impact relatively fewer users and only for very specific cases, in comparison to many crates which have comparatively fewer users leaving bugs unfound. Saying "well, you're willing to tolerate bugs in one place, so you should be willing to tolerate bugs in all the places" doesn't pass muster.

@epage
Copy link

epage commented Dec 2, 2024

@TheBlueMatt Yes, the standard library is more mature and is less likely to have bug fixes that people need. There is also the compounding factor as you multiply error rates across all of your dependencies. Some users may also be using a version of Rust supplied by a vendor with a wider support policy.

However, MSRV policies put a burden on maintainers which are the linchpin of the ecosystem. People are expecting free labor from maintainers to support unsupported software. I also tend to see this conversation focus more on security vulnerabilities than bug fixes. That can shift the calculus because the impact can be much higher even if the probability is still low.

This is covered more in the Cargo book: https://doc.rust-lang.org/nightly/cargo/reference/rust-version.html#support-expectations

This is all a balancing act and I can understand why people land in different spots.

For myself, this is why I'm considering the approach of allowing backports of bug fixes to old major or minor versions that support older rust versions. I've already been allowing backports in clap for major versions and the impact is minimal while allowing giving users confidence that they won't be blocked too badly. Granted, time is 0-ver and there is no distinguishment made between minor and patch versions to give room for this.

@TheBlueMatt
Copy link

However, MSRV policies put a burden on maintainers which are the linchpin of the ecosystem. People are expecting free labor from maintainers to support unsupported software. I also tend to see this conversation focus more on security vulnerabilities than bug fixes. That can shift the calculus because the impact can be much higher even if the probability is still low.

Yea, I didn't mean to suggest otherwise :). Obviously every maintainer is free to pick any policy they want, doubly so if they feel like doing otherwise would require some effort on their part that they simply don't want to do. My point here was only that suggesting that "users are using old rustc so they must be fine with bugs" is obviously a bogus stance. If a maintainer doesn't want to do the extra work, just say so :).

For myself, this is why I'm considering the approach of allowing backports of bug fixes to old major or minor versions that support older rust versions. I've already been allowing backports in clap for major versions and the impact is minimal while allowing giving users confidence that they won't be blocked too badly. Granted, time is 0-ver and there is no distinguishment made between minor and patch versions to give room for this.

Yea, projects that do that seem to be happy with it (eg tokio) - its mostly relatively little effort to do backports of bugfixes, and it allows downstream projects to pick their own MSRV while freeing maintainers to pick a more aggressive MSRV if they have some features in newer rustc they want to use. Of course its not zero effort, and maintainers may decide to do otherwise, but its definitely nice when packages do this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-libs Relevant to the libraries subteam, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests