UPD: This proposal is published as RFC 2495.
rust field to package section which will be used to specify crate’s Minimum Supported Rust Version (MSRV):
[package] name = "foo" version = "0.1.0" rust = "1.30"
Currently crates have no way to formally specify MSRV. As a result users can’t be sure that crate can be built on their toolchain without building it. It also leads to the debate on how to handle crate version change on bumping MSRV, conservative approach is to consider such changes as breaking ones, which can hinder adoption of new features across ecosystem or result in version number inflation, which makes it harder to keep downstream crates up-to-date. More relaxed approach on another hand can result in broken crates for user of older compiler versions.
First stage: dumb field
We can start with the simple addition of
rust field which should respect minimal requirements:
- value should be a version in semver format or equal to “nigthly”
- version should not be bigger than the current stable toolchain
- version should not be smaller than 1.27 (version in which
package.rustfield became a warning instead of an error)
At first it can be simply a declarative field without any functionality behind it. The reason for it to reduce implementation cost of minimal viable version to the minimum and ideally ship it as part of Rust 2018. It will also allow crate authors who care about MSRV to start mark their crates early. Additionally
cargo init will add
rust field equal to a version of the used toolchain.
edition = "2018" will imply
rust = "1.30" if not specified otherwise. In case of 2015 edition it will be
rust="1.0". It will be an error to use
edition="2015" is a valid combination.
Second stage: versions resolution
Cargo will add
rust field as a constraint to dependency versions resolution. If user uses e.g. Rust 1.20 and uses crate
foo = "0.2", but all selected versions of
foo specify MSRV say equal 1.21 or bigger (or even nightly)
cargo will issue an error.
rust field value will be checked as well, on crate build
cargo will check if all upstream dependencies can be built with the specified MSRV. (i.e. it will check if there is exists solution for given crates and Rust versions constraints)
Yanked crates will be ignored in this process.
Implementing this functionality will allow to close the debate regarding MSRV handling in crate versions and will allow crate authors to feel less restrictive about bumping their crate’s MSRV.
Third stage: better crate checks
Here we introduce two level checks for crates. First level will check if all used items were stabilised before or on given MSRV using
#[stable(since=version)] attribute, issuing compile errors otherwise.
Second level will try to build crate with the specified MSRV on
cargo publish, i.e. words it will be required to install MSRV toolchain. (this check can be disabled)
While these two checks will not replace proper CI testing, they will help to reduce number of improper MSRV configuration to the minimum.
Extension: nightly versions
For some bleeding-edge crates which experience frequent breaks on Nightly updates (e.g.
rocket) it can be useful to specify exact Nigthly version(s) on which crate can be built. One way to achieve this is by using the following syntax:
- single version: `rust = “nightly: 2018-01-01”
- enumeration: “nightly: 2018-01-01, 2018-01-15”
- (inclusive) range: “nightly: 2018-01-01…2018-01-15”
- enumeration+range: “nightly: 2018-01-01, 2018-01-08…2018-01-15”
Such restrictions can be quite severe, but hopefully this functionality will be used only by handful of crates.
Since Rust 1.27 (or maybe earlier?) cargo issues only warning on unknown fields in
Cargo.toml, so impact of introducing
rust field will be minimal.
- Should we add additional checks?
- What MSRV value should
cargo inituse, current toolchain or edition min-version?
- Better description of versions resolution algorithm.
- How handle crate features which bump MSRV?