# MSRV-Specific Code

**URL:** <https://internals.rust-lang.org/t/msrv-specific-code/17045>\
**Category:** language design\
**Created:** [July 20, 2022, 9:14am UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045 "2022-07-20T09:14:03Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![stackinspector](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/stackinspector/32/9487_2.png) [@stackinspector](https://internals.rust-lang.org/u/stackinspector)\
**Post date:** [July 20, 2022, 9:14am UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/1 "2022-07-20T09:14:03Z")

</div>

The Rust language itself already supports const generics, and thus supports implementing traits for arbitrary length arrays without macro expansion and redundance in compilation products. But the serde community seems to have been lacking widely support for arbitrary length arrays for a long time because of the MSRV strategy. For example, the crate `serde_bytes` does not support [u8, N] so far, and a [PR](https://github.com/serde-rs/bytes/pull/28) that added that support was not merged for 4 months, seemingly because it directly raised the MSRV to 1.53, which is unacceptable for crate's MSRV strategy. (I have not actually seen the MSRV strategy of this crate, and the crate maintainer has not replied to the PR, so the above words are just my guess.) By searching I found a [RFC](https://github.com/rust-lang/rfcs/pull/2523) ([tracking issue](https://github.com/rust-lang/rust/issues/64796)) that might be able to solve this problem. However, the tracking issue was opened almost 3 years ago and has not been completed yet. I would like to know the progress.

---

<div class="post-metadata">

**Author:** ![burntsushi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/burntsushi/32/279_2.png) [@burntsushi](https://internals.rust-lang.org/u/burntsushi)\
**Post date:** [July 20, 2022, 11:20am UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/2 "2022-07-20T11:20:00Z")

</div>

This issue seems pretty relevant: [MSRV policy for libc crate · Issue #72 · rust-lang/libs-team · GitHub](https://github.com/rust-lang/libs-team/issues/72)

---

<div class="post-metadata">

**Author:** ![stackinspector](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/stackinspector/32/9487_2.png) [@stackinspector](https://internals.rust-lang.org/u/stackinspector)\
**Post date:** [July 20, 2022, 12:01pm UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/3 "2022-07-20T12:01:49Z")

</div>

I've mostly cited arguments, but perhaps not very clearly expressed what I would like to see: by making crate selectable for features and code based on the user's chosen language version in a similar way to `cfg`, just as it does for different platforms. For the mentioned above `serde_bytes` example, would theoretically make it perfectly possible to make `[u8; N]` support available to users using language version above 1.51, while maintaining compatibility for users using language versions below that.

---

<div class="post-metadata">

**Author:** ![jonasbb](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jonasbb/32/2084_2.png) [@jonasbb](https://internals.rust-lang.org/u/jonasbb)\
**Post date:** [July 20, 2022, 12:33pm UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/4 "2022-07-20T12:33:14Z")

</div>

Conditional compilation based on rustc version is already possible and somewhat spread in the ecosystem. While direct support would be nice, [build scripts](https://github.com/serde-rs/serde/blob/master/serde/build.rs) can be used right now. serde uses this already to keep the MSRV at 1.13+. Requiring a new feature would not help keeping the MSRV low.

serde and other crates by the same author are all pretty much stalled concerning development, and many PRs are entirely ignored. For the specific case of `serde_bytes` there are [alternatives available](https://docs.rs/serde_with/latest/serde_with/struct.Bytes.html).

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [July 20, 2022, 12:57pm UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/5 "2022-07-20T12:57:55Z")

</div>

With the newly added `rust-version` field in `Cargo.toml`, it would be possible for Cargo to support an MSRV-dependent resolution which takes that field into account and selects the newest version with a compatible MSRV, even if it were gated behind a flag like `-Z msrv-compatible-versions`

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [July 20, 2022, 1:35pm UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/6 "2022-07-20T13:35:56Z")

</div>

> [@bascule](#):
>
> even if it were gated behind a flag like `-Z msrv-compatible-versions`

A nightly-only flag requires using the nightly toolchain to generate your `Cargo.lock`. This is the case today with `-Z minimal-versions` as well (which I think is the better solution long-term, but I digress).

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [July 20, 2022, 4:36pm UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/7 "2022-07-20T16:36:04Z")

</div>

> [@mathstuf](#):
>
> `-Z minimal-versions` as well (which I think is the better solution long-term, but I digress).

Using `-Z minimal-versions` locks you out of bugfixes which are MSRV compatible, forcing you to specify them explicitly in `Cargo.toml` instead of being able to pick them up automatically.

IMO the main use case for `-Z minimal-versions` is checking that your dependencies have their required versions properly declared and that your crate will still compile when the minimum versions are selected.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [July 20, 2022, 4:48pm UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/8 "2022-07-20T16:48:16Z")

</div>

If a bugfix in your dependency represents a bugfix in you, it's absolutely reasonable for that to mean a patch release for you to bump the dependency edge to guarantee that patch. `-Zminimal-versions` isn't the only way you could be using the older dependency; normal lockfile usage and time could also result in you using the buggy version as well.

This of course doesn't mean that providing rust-version-aware dependency resolution by default isn't still both useful and desirable. But it does hint at that metadata/manifest-only package updates are _also_ a useful thing to have access to (where the old compilation cache can potentially be reused).

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [July 20, 2022, 5:20pm UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/9 "2022-07-20T17:20:17Z")

</div>

> [@bascule](#):
>
> Using `-Z minimal-versions` locks you out of bugfixes which are MSRV compatible

That's why running `cargo-audit` on a `-Z minimal-versions` lock file is still important. Of course, bugfixes being present means that you may need to evaluate the minimum versions again.

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [July 20, 2022, 5:36pm UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/10 "2022-07-20T17:36:20Z")

</div>

> [@mathstuf](#):
>
> That's why running `cargo-audit` on a `-Z minimal-versions` lock file is still important.

Speaking as the author of `cargo audit`, it won't help you with bugfixes, only security issues.

> [@](#):
>
> Of course, bugfixes being present means that you may need to evaluate the minimum versions again.

This is the sort of manual maintenance work picking the latest compatible version automatically avoids which I was alluding to earlier.

It also means for transitive dependencies, you won't receive bugfixes until the downstream authors of your immediate dependencies bump versions in the lockfile.

This greatly increases the amount of friction involved in ensuring your code is up-to-date.

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [July 20, 2022, 5:52pm UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/11 "2022-07-20T17:52:01Z")

</div>

> [@bascule](#):
>
> Speaking as the author of `cargo audit`, it won't help you with bugfixes, only security issues.

True. These are those that are "surprising" and not usually tracked. If I get an issue that some dependency releases a fix that I care about, then I bump the minimum.

> [@bascule](#):
>
> This is the sort of manual maintenance work picking the latest compatible version automatically avoids which I was alluding to earlier.

Yes. Unfortunately, this means that the MSRV creeps up as crates have varying views of what it means for stability. `-Z minimal-versions` keeps that stable at least.

> [@bascule](#):
>
> It also means for transitive dependencies, you won't receive bugfixes until the downstream authors of your immediate dependencies bump versions in the lockfile.

It's easy enough to force a bump by adding a direct dependency to the crate to your own `Cargo.toml` file. I typically comment it with a link to the issue(s) related to getting a dependency bumped.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [July 20, 2022, 6:05pm UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/12 "2022-07-20T18:05:03Z")

</div>

With my Cargo team hat on: I'd _love_ to see version resolution take `rust-version` into account (and emit an informational message saying it's doing so and thus not choosing a newer version), but that's quite non-trivial, as it will require resolver changes.

(Also, it's not clear if we want to do that _by default_, or if we want that to be an opt-in for use by people who want to keep running older versions.)

---

<div class="post-metadata">

**Author:** ![stackinspector](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/stackinspector/32/9487_2.png) [@stackinspector](https://internals.rust-lang.org/u/stackinspector)\
**Post date:** [July 20, 2022, 7:30pm UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/13 "2022-07-20T19:30:46Z")

</div>

Learned about the `serde_with` crate because of some demands, although it didn't solve my demands in the end (most likely because I didn't understand how to use it). I hadn't noticed before that there was an alternative to serializing bytes in it. But it seems that introducing this whole crate for this one feature is a bit redundant.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [July 21, 2022, 12:47am UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/14 "2022-07-21T00:47:43Z")

</div>

> [@mathstuf](#):
>
> It's easy enough to force a bump by adding a direct dependency to the crate to your own `Cargo.toml` file.

A better option could be [a theoretical `[phantom-dependencies]`](https://internals.rust-lang.org/t/phantom-dependencies/17048) table.

I stand behind what I said earlier that if your library's correctness relies on a bug fix in your dependency, you should upgrade your dependency requirement. Being "minimal-versions correct" isn't just about working under `-Zminimal-versions`, it's also about getting the appropriate versions to people who `cargo add` your library but already have older versions of your dependencies in their lockfile.

_Especially_ if you're a "maximal-versions maximalist," you should be upgrading your dependency requirements for each release to be the most recent at the time of release. Or at the very least, to whatever the versions are in your lockfile. Those are the versions you tested against, so don't lie and say you work with earlier versions.

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [July 21, 2022, 12:19pm UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/15 "2022-07-21T12:19:32Z")

</div>

> [@CAD97](#):
>
> Or at the very least, to whatever the versions are in your lockfile. Those are the versions you tested against, so don't lie and say you work with earlier versions.

The projects I regularly work on have `minimal-versions` CI setup, so at least _I_ know they work.

---

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [July 22, 2022, 2:25pm UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/16 "2022-07-22T14:25:40Z")

</div>

imo specifying `rust-version` would be opting in.

One way of informing users that we are holding back dependencies is my idea to [add a `cargo outdated`-like table to `cargo update` and `cargo upgrade`](https://github.com/rust-lang/cargo/issues/4309#issuecomment-1112326678).

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [July 22, 2022, 4:04pm UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/17 "2022-07-22T16:04:20Z")

</div>

> [@epage](#):
>
> One way of informing users that we are holding back dependencies is my idea to [add a `cargo outdated`-like table to `cargo update` and `cargo upgrade`](https://github.com/rust-lang/cargo/issues/4309#issuecomment-1112326678).

+1. If an MSRV-aware resolver were added, it would definitely be good to somehow warn users that an outdated version is being selected due to MSRV restrictions

---

<div class="post-metadata">

**Author:** ![ekuber](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ekuber/32/1646_2.png) [@ekuber](https://internals.rust-lang.org/u/ekuber)\
**Post date:** [September 15, 2022, 9:49am UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/18 "2022-09-15T09:49:20Z")

</div>

I'd go as far as saying: it'd be neat to proactively patch specific old versions that are distributed by distros to provide custom errors in the face of an attempt to use new features. I don't know if distro maintainers would be amenable to such "functionality" patches.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [December 14, 2022, 9:49am UTC](https://internals.rust-lang.org/t/msrv-specific-code/17045/19 "2022-12-14T09:49:32Z")

</div>

Closed on December 14, 2022, 9:49am UTC

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