From 800825ccd0f5db7f58a063395dfd02b5b228bb60 Mon Sep 17 00:00:00 2001 From: newpavlov Date: Mon, 2 Jul 2018 17:47:25 +0300 Subject: [PATCH 01/19] msrv --- text/0000-min-rust-version.md | 178 ++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 text/0000-min-rust-version.md diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md new file mode 100644 index 00000000000..65b391d4996 --- /dev/null +++ b/text/0000-min-rust-version.md @@ -0,0 +1,178 @@ +- Feature Name: min_rust_version +- Start Date: 2018-06-28 +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary +[summary]: #summary + +Add `rust` field to the package section of `Cargo.toml` which will be used to +specify crate's Minimum Supported Rust Version (MSRV): +```toml +[package] +name = "foo" +version = "0.1.0" +rust = "1.30" +``` + +# Motivation +[motivation]: #motivation + +Currently crates have no way to formally specify MSRV. As a result users can't +check if 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. + +# Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +`cargo init` will automatically create `Cargo.toml` with `rust` field equal to +`rust="stable"` or `rust="nightly"` depending on the currently used toolcahin. +On `cargo publish` cargo will take currently used Rust compiler version and +will insert it before uploading the crate. In other words localy your `Cargo.toml` +willl still have `rust="stable"`, but version sent to crates.io will have +`rust="1.30"` if you've used Rust 1.30. This version will be used to determine if +crate can be used with the crate user's toolchain and to select appropriate +dependency versions. In case if you have `rust="stable"`, but execute +`cargo publish` with Nigthly toolcahin you will get an error. + +If you are sure that your crate supports older Rust versions (e.g. by using CI +testing) you can change `rust` field accordingly. On `cargo publish` it will be +checked that crate indeed can be built with the specified version. (though this +check can be disabled with `--no-verify` option) + +For example, lets imagine that your crate depends on crate `foo` with 10 published +versions from `0.1.0` to `0.1.10`, in versions from `0.1.0` to `0.1.5` `rust` +field in the `Cargo.toml` sent to crates.io equals to "1.30" and for others to +"1.40". Now if you'll build your project with Rust 1.33 `cargo` will select +`foo v0.1.5`, and `foo v0.1.10` if you'll build your project with Rust 1.30 or +later. But if you'll try to build your project with Rust 1.29 cargo will issue an +error. Although this check can be disabled with `--no-rust-check` option. + +`rust` field should respect the following minimal requirements: +- value should be equal to "stable", "nigthly" or to a version in semver format +("1.50" is a valid value and implies "1.50.0") +- version should not be bigger than the current stable toolchain +- version should not be smaller than 1.27 (version in which `package.rust` field +became a warning instead of an error) + +`rust` will be a required field. For crates uploaded before introduction of this +feature 2015 edition crates will imply `rust="1.0"` and 2018 ediiton will imply +`rust = "1.30"`. + +It will be an error to use `rust="1.27"` and `edition="2018"`, but `rust="1.40"` and `edition="2015"` is a valid combination. + +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation + +The describe functionality can be introduced in several stages: + + +## First stage: dumb field + +At first the `rust` field can be simply a declarative optional field without any +functionality behind it. The reason for it is to reduce implementation cost of +the first stage 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. + +## Second stage: versions resolution + +`rust` field becomes required and cargo will add it as a constraint to dependency +versions resolution. If user uses e.g. Rust 1.40 and uses crate `foo = "0.2"`, but +all selected versions of `foo` specify MSRV e.g. equal 1.41 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 hopefully 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. (though it can be a usefull +convention for post-1.0 crates to bump minor version on MSRV change to allow +publishing backports which fix serious issues using patch version) + +## Third stage: better crate checks + +Here we introduce two-level check 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 using `--no-verify` option) + +While these two checks will not replace proper CI testing, they will help to +reduce number of improper MSRV configuration to the minimum. + +Note that `rust` field must be equal to MSRV with default features for all +supported targets. + +## 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. + +## Extension: cfg based MSRV + +Some crates can have different MSRVs depending on target architecture or enabled +features. In such cases it can be usefull to extend `rust` field, e.g. in the +following way: +```toml +rust = "1.30" +rust-cases = [ + { cfg = "x86_64-pc-windows-gnu", version = "1.35" }, + { cfg = 'cfg(feature = "foo")', version = "1.33" }, +] +``` + +Version resolution will filter all cases with `cfg` equal to true and will take +max `version` value from them as a MSRV. If all `cfg`s are false, value in the +`rust` field will be used. + +# Drawbacks +[drawbacks]: #drawbacks + +- Declaration of MSRV and describe checks does not guarantee that, only +appropriate CI testing. +- More complex dependency versions resolution algorithm. +- MSRV selected by `cargo publish` can be overly conservative. +- MSRV checks will make compiler more complex. + +# Rationale and Alternatives +[alternatives]: #alternatives + +- Automatically calculate MSRV. +- Do nothing and rely on [LTS releases](https://github.com/rust-lang/rfcs/pull/2483) +for bumping crate MSRVs. + +# Prior art +[prior-art]: #prior-art + +Previous proposals: +- [RFC 1707](https://github.com/rust-lang/rfcs/pull/1707) +- [RFC 1709](https://github.com/rust-lang/rfcs/pull/1709) +- [RFC 1953](https://github.com/rust-lang/rfcs/pull/1953) +- [RFC 2182](https://github.com/rust-lang/rfcs/pull/2128) (arguably this one got off-track) + +# Unresolved questions +[unresolved]: #unresolved-questions + +- Name bike-shedding: `rust` vs `rustc` vs `min-rust-version` +- Additional checks? +- Better description of versions resolution algorithm. From 4ec9682a9f2c2697eedbdb06350fa5701fd0e862 Mon Sep 17 00:00:00 2001 From: newpavlov Date: Wed, 4 Jul 2018 18:10:28 +0300 Subject: [PATCH 02/19] drawbacks update --- text/0000-min-rust-version.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index 65b391d4996..300eb5cccb6 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -148,11 +148,12 @@ max `version` value from them as a MSRV. If all `cfg`s are false, value in the # Drawbacks [drawbacks]: #drawbacks -- Declaration of MSRV and describe checks does not guarantee that, only -appropriate CI testing. +- Declaration of MSRV, even with the checks, does not guarantee that crate +will work correctly on the specified MSRV, only appropriate CI testing can do that. - More complex dependency versions resolution algorithm. -- MSRV selected by `cargo publish` can be overly conservative. -- MSRV checks will make compiler more complex. +- MSRV selected by `cargo publish` with `rust = "stable"` can be too +conservative. +- Checking `#[stable(since=version)]` of used items will make compiler more complex. # Rationale and Alternatives [alternatives]: #alternatives From f9057da774a1b5fe4dc33f7658fd89f6d024d083 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Thu, 5 Jul 2018 22:25:36 +0300 Subject: [PATCH 03/19] reviews updates --- text/0000-min-rust-version.md | 51 ++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index 300eb5cccb6..fb19f99d023 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -38,12 +38,11 @@ willl still have `rust="stable"`, but version sent to crates.io will have `rust="1.30"` if you've used Rust 1.30. This version will be used to determine if crate can be used with the crate user's toolchain and to select appropriate dependency versions. In case if you have `rust="stable"`, but execute -`cargo publish` with Nigthly toolcahin you will get an error. +`cargo publish` with Nightly toolcahin you will get an error. If you are sure that your crate supports older Rust versions (e.g. by using CI testing) you can change `rust` field accordingly. On `cargo publish` it will be -checked that crate indeed can be built with the specified version. (though this -check can be disabled with `--no-verify` option) +checked that crate indeed can be built with the specified version. For example, lets imagine that your crate depends on crate `foo` with 10 published versions from `0.1.0` to `0.1.10`, in versions from `0.1.0` to `0.1.5` `rust` @@ -54,17 +53,18 @@ later. But if you'll try to build your project with Rust 1.29 cargo will issue a error. Although this check can be disabled with `--no-rust-check` option. `rust` field should respect the following minimal requirements: -- value should be equal to "stable", "nigthly" or to a version in semver format +- value should be equal to "stable", "nightly" or to a version in semver format ("1.50" is a valid value and implies "1.50.0") - version should not be bigger than the current stable toolchain - version should not be smaller than 1.27 (version in which `package.rust` field became a warning instead of an error) `rust` will be a required field. For crates uploaded before introduction of this -feature 2015 edition crates will imply `rust="1.0"` and 2018 ediiton will imply +feature 2015 edition crates will imply `rust="1.0"` and 2018 edition will imply `rust = "1.30"`. -It will be an error to use `rust="1.27"` and `edition="2018"`, but `rust="1.40"` and `edition="2015"` is a valid combination. +It will be an error to use `rust="1.27"` and `edition="2018"`, but `rust="1.40"` +and `edition="2015"` is a valid combination. # Reference-level explanation [reference-level-explanation]: #reference-level-explanation @@ -80,7 +80,25 @@ the first stage 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. -## Second stage: versions resolution + +## Second stage: `cargo publish` check + +The next step is for `cargo publish` to require use of the toolchain specified +in the `rust` field, for example crates with: +- `rust="stable"` can be published only with a stable toolchain, though not +necessarily with the latest one. Cargo will insert toolchain version before +publishing the crate as was described in the "guide-level explanation". +- `rust="nightly"` can be published only with a nightly toolchain. If finer +grained "nightly: ..." (see "nightly versions" section) is selected, then one +of the selected Nightly versions will have to be used. +- `rust="1.30"` can be published only with (stable) Rust 1.30, even if it's +not the latest stable Rust version. + +Using the usual build check `cargo publish` will verify that crate indeed can be +built using specified MSRV. This check can be used with exisiting `--no-verify` +option. + +## Third stage: versions resolution `rust` field becomes required and cargo will add it as a constraint to dependency versions resolution. If user uses e.g. Rust 1.40 and uses crate `foo = "0.2"`, but @@ -99,26 +117,10 @@ restrictive about bumping their crate's MSRV. (though it can be a usefull convention for post-1.0 crates to bump minor version on MSRV change to allow publishing backports which fix serious issues using patch version) -## Third stage: better crate checks - -Here we introduce two-level check 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 using `--no-verify` option) - -While these two checks will not replace proper CI testing, they will help to -reduce number of improper MSRV configuration to the minimum. - -Note that `rust` field must be equal to MSRV with default features for all -supported targets. - ## 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 +(e.g. `rocket`) it can be useful to specify exact Nightly 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" @@ -153,7 +155,6 @@ will work correctly on the specified MSRV, only appropriate CI testing can do th - More complex dependency versions resolution algorithm. - MSRV selected by `cargo publish` with `rust = "stable"` can be too conservative. -- Checking `#[stable(since=version)]` of used items will make compiler more complex. # Rationale and Alternatives [alternatives]: #alternatives From a43e9e13055f90b728cdccf46c78a463786806c2 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Sun, 8 Jul 2018 18:16:23 +0300 Subject: [PATCH 04/19] kennytm's review updates --- text/0000-min-rust-version.md | 76 ++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 29 deletions(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index fb19f99d023..ec62c4565ce 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -31,18 +31,27 @@ compiler versions. [guide-level-explanation]: #guide-level-explanation `cargo init` will automatically create `Cargo.toml` with `rust` field equal to -`rust="stable"` or `rust="nightly"` depending on the currently used toolcahin. +`rust="stable"` or `rust="nightly: *"` depending on the currently used toolcahin. On `cargo publish` cargo will take currently used Rust compiler version and will insert it before uploading the crate. In other words localy your `Cargo.toml` willl still have `rust="stable"`, but version sent to crates.io will have -`rust="1.30"` if you've used Rust 1.30. This version will be used to determine if -crate can be used with the crate user's toolchain and to select appropriate -dependency versions. In case if you have `rust="stable"`, but execute -`cargo publish` with Nightly toolcahin you will get an error. +`rust="1.30"` if you've used Rust 1.30. If "nightly: \*" is used, then `cargo` +will not select current Nightly version, but will assume that cratecan be built +with all Nightly versions. + +In case if you have `rust="stable"`, but execute `cargo publish` with Nightly +toolcahin you will get an error. Same goes for `rust="nightly: *"` which can be +published only using nightly toolchain. If you are sure that your crate supports older Rust versions (e.g. by using CI -testing) you can change `rust` field accordingly. On `cargo publish` it will be -checked that crate indeed can be built with the specified version. +testing) you can specify this version explicitly, e.g. `rust="1.30"`. +On `cargo publish` it will be checked that crate indeed can be built with the +specified version, i.e. the respective toolchain will have to be installed on +your computer. + +The value of `rust` field (explicit or autmatically selected by `cargo`) will +be used to determine if crate can be used with the crate user's toolchain and +to select appropriate dependency versions. For example, lets imagine that your crate depends on crate `foo` with 10 published versions from `0.1.0` to `0.1.10`, in versions from `0.1.0` to `0.1.5` `rust` @@ -53,8 +62,9 @@ later. But if you'll try to build your project with Rust 1.29 cargo will issue a error. Although this check can be disabled with `--no-rust-check` option. `rust` field should respect the following minimal requirements: -- value should be equal to "stable", "nightly" or to a version in semver format -("1.50" is a valid value and implies "1.50.0") +- value should be equal to "stable", "nightly: \*" or to a version in semver format. +Note that "1.50" is a valid value and implies "1.50.0". (also see "nightly versions" +extension) - version should not be bigger than the current stable toolchain - version should not be smaller than 1.27 (version in which `package.rust` field became a warning instead of an error) @@ -75,11 +85,10 @@ The describe functionality can be introduced in several stages: ## First stage: dumb field At first the `rust` field can be simply a declarative optional field without any -functionality behind it. The reason for it is to reduce implementation cost of -the first stage 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. - +functionality behind it with minimal checks. The reason for it is to reduce +implementation cost of the first stage 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. ## Second stage: `cargo publish` check @@ -88,7 +97,7 @@ in the `rust` field, for example crates with: - `rust="stable"` can be published only with a stable toolchain, though not necessarily with the latest one. Cargo will insert toolchain version before publishing the crate as was described in the "guide-level explanation". -- `rust="nightly"` can be published only with a nightly toolchain. If finer +- `rust="nightly: *"` can be published only with a nightly toolchain. If finer grained "nightly: ..." (see "nightly versions" section) is selected, then one of the selected Nightly versions will have to be used. - `rust="1.30"` can be published only with (stable) Rust 1.30, even if it's @@ -100,8 +109,8 @@ option. ## Third stage: versions resolution -`rust` field becomes required and cargo will add it as a constraint to dependency -versions resolution. If user uses e.g. Rust 1.40 and uses crate `foo = "0.2"`, but +`rust` field will be used as a constraint for dependency versions resolution. +If user uses e.g. Rust 1.40 and uses crate `foo = "0.2"`, but all selected versions of `foo` specify MSRV e.g. equal 1.41 or bigger (or even nightly) `cargo` will issue an error. @@ -122,10 +131,13 @@ publishing backports which fix serious issues using patch version) For some bleeding-edge crates which experience frequent breaks on Nightly updates (e.g. `rocket`) it can be useful to specify exact Nightly 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" +- auto-select: "nightly" This variant will behave in the same way as "stable", i.e. +it will take a current nightly version and will use it in a "more or equal" constraint. +- single version: "nightly: 2018-01-01" (tha main variant) - 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" +- semver-like conditions: "nightly: >=2018-01-01", "nightly: >=2018-01-01, <=2018-01-15", +"nightly: >=2018-01-01, <=2018-01-15, 2018-01-20". (the latter is interpreted as +"(version >= 2018-01-01 && version <= 2018-01-20) || version == 2018-01-20") Such restrictions can be quite severe, but hopefully this functionality will be used only by handful of crates. @@ -133,19 +145,24 @@ used only by handful of crates. ## Extension: cfg based MSRV Some crates can have different MSRVs depending on target architecture or enabled -features. In such cases it can be usefull to extend `rust` field, e.g. in the -following way: +features. In such cases it can be usefull to describe how MSRV depends on them, +e.g. in the following way: ```toml +[package] rust = "1.30" -rust-cases = [ - { cfg = "x86_64-pc-windows-gnu", version = "1.35" }, - { cfg = 'cfg(feature = "foo")', version = "1.33" }, -] + +[target.x86_64-pc-windows-gnu] +rust = "1.35" + +[target.'cfg(feature = "foo")'] +rust = "1.33" ``` -Version resolution will filter all cases with `cfg` equal to true and will take -max `version` value from them as a MSRV. If all `cfg`s are false, value in the -`rust` field will be used. +All `rust` values in the `target` sections should be equal or bigger to a `rust` value +specified in the `package` section. + +If target condition is true, then `cargo ` will use `rust` value from this section. +If several target section conditions are true, then maximum value will be used. # Drawbacks [drawbacks]: #drawbacks @@ -178,3 +195,4 @@ Previous proposals: - Name bike-shedding: `rust` vs `rustc` vs `min-rust-version` - Additional checks? - Better description of versions resolution algorithm. +- How nightly versions will work with "cfg based MSRV"? From 00a3022176ce22c4c51e75baefdab8756874fc17 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Wed, 11 Jul 2018 21:48:18 +0300 Subject: [PATCH 05/19] fixes, option addition, wording improvements - fixed typo and RFC link - improved wording a bit - added `--check-msrv-toolchain` option ( @phaylon ) --- text/0000-min-rust-version.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index ec62c4565ce..d23a191f82b 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -49,17 +49,24 @@ On `cargo publish` it will be checked that crate indeed can be built with the specified version, i.e. the respective toolchain will have to be installed on your computer. +By default toolchain check is disabled for `cargo publish`, `cargo check` and +`cargo test`, but it can be enabled with `--check-msrv-toolchain` option. +To disable this check for `cargo publish` you can use `--no-verify`option. + The value of `rust` field (explicit or autmatically selected by `cargo`) will be used to determine if crate can be used with the crate user's toolchain and to select appropriate dependency versions. For example, lets imagine that your crate depends on crate `foo` with 10 published -versions from `0.1.0` to `0.1.10`, in versions from `0.1.0` to `0.1.5` `rust` +versions from `0.1.0` to `0.1.9`, in versions from `0.1.0` to `0.1.5` `rust` field in the `Cargo.toml` sent to crates.io equals to "1.30" and for others to -"1.40". Now if you'll build your project with Rust 1.33 `cargo` will select -`foo v0.1.5`, and `foo v0.1.10` if you'll build your project with Rust 1.30 or -later. But if you'll try to build your project with Rust 1.29 cargo will issue an -error. Although this check can be disabled with `--no-rust-check` option. +"1.40". Now if you'll build your project with e.g. Rust 1.33, `cargo` will select +`foo v0.1.5`. `foo v0.1.9` will be selected only if you'll build your project with +Rust 1.40 or higher. But if you'll try to build your project with Rust 1.29 cargo +will issue an error. + +Note that described MSRV constraints and checks for dependency versions resolution +can be disabled with `--no-msrv-check` option. `rust` field should respect the following minimal requirements: - value should be equal to "stable", "nightly: \*" or to a version in semver format. @@ -187,7 +194,7 @@ Previous proposals: - [RFC 1707](https://github.com/rust-lang/rfcs/pull/1707) - [RFC 1709](https://github.com/rust-lang/rfcs/pull/1709) - [RFC 1953](https://github.com/rust-lang/rfcs/pull/1953) -- [RFC 2182](https://github.com/rust-lang/rfcs/pull/2128) (arguably this one got off-track) +- [RFC 2182](https://github.com/rust-lang/rfcs/pull/2182) (arguably this one got off-track) # Unresolved questions [unresolved]: #unresolved-questions From 1e37f4cfbc9565742f786dc4ea8cde03f0bea6d2 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Thu, 5 Sep 2019 00:48:47 +0000 Subject: [PATCH 06/19] center RFC around MVP, move everything else to "future work" --- text/0000-min-rust-version.md | 174 ++++++++++++++-------------------- 1 file changed, 73 insertions(+), 101 deletions(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index d23a191f82b..600466592a0 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -30,34 +30,39 @@ compiler versions. # Guide-level explanation [guide-level-explanation]: #guide-level-explanation -`cargo init` will automatically create `Cargo.toml` with `rust` field equal to -`rust="stable"` or `rust="nightly: *"` depending on the currently used toolcahin. -On `cargo publish` cargo will take currently used Rust compiler version and -will insert it before uploading the crate. In other words localy your `Cargo.toml` -willl still have `rust="stable"`, but version sent to crates.io will have -`rust="1.30"` if you've used Rust 1.30. If "nightly: \*" is used, then `cargo` -will not select current Nightly version, but will assume that cratecan be built -with all Nightly versions. - -In case if you have `rust="stable"`, but execute `cargo publish` with Nightly -toolcahin you will get an error. Same goes for `rust="nightly: *"` which can be -published only using nightly toolchain. - -If you are sure that your crate supports older Rust versions (e.g. by using CI -testing) you can specify this version explicitly, e.g. `rust="1.30"`. -On `cargo publish` it will be checked that crate indeed can be built with the -specified version, i.e. the respective toolchain will have to be installed on -your computer. - -By default toolchain check is disabled for `cargo publish`, `cargo check` and -`cargo test`, but it can be enabled with `--check-msrv-toolchain` option. -To disable this check for `cargo publish` you can use `--no-verify`option. +If you target a specific MSRV add a `rust` field to the `[package]` section of +your `Cargo.toml` with a value equal to the targeted Rust version. If you build +a crate with a dependency which has MSRV higher than the current version of your +toolchain, `cargo` will return a compilation error stating the dependency and +its MSRV. This behavior can be disabled by using `--no-msrv-check` flag. + +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation + +During build process (including `run`, `test`, `benchmark`, `verify` and `publish` +sub-commands) `cargo` will check MSRV requirements of all crates in a dependency +tree scheduled to be built or checked. Crates which are part of the dependency +tree, but will not be built are excluded from this check (e.g. target-dependent +or optional crates). + +`rust` field should respect the following minimal requirements: +- value should be a version in semver format WITHOUT range operators. Note that +"1.50" is a valid value and implies "1.50.0". +- version can not be bigger than the current stable toolchain +- version can not be smaller than 1.27 (version in which `package.rust` field +became a warning instead of an error) +- version can not be smaller than release version of a used edition, i.e. +combination of `rust = "1.27"` and `edition = "2018"` is an invalid one. + +# Future work (Extensions) +[future-work]: #future-work + +## Influencing version resolution The value of `rust` field (explicit or autmatically selected by `cargo`) will -be used to determine if crate can be used with the crate user's toolchain and -to select appropriate dependency versions. +be used to select appropriate dependency versions. -For example, lets imagine that your crate depends on crate `foo` with 10 published +For example, let's imagine that your crate depends on crate `foo` with 10 published versions from `0.1.0` to `0.1.9`, in versions from `0.1.0` to `0.1.5` `rust` field in the `Cargo.toml` sent to crates.io equals to "1.30" and for others to "1.40". Now if you'll build your project with e.g. Rust 1.33, `cargo` will select @@ -65,75 +70,64 @@ field in the `Cargo.toml` sent to crates.io equals to "1.30" and for others to Rust 1.40 or higher. But if you'll try to build your project with Rust 1.29 cargo will issue an error. -Note that described MSRV constraints and checks for dependency versions resolution -can be disabled with `--no-msrv-check` option. - -`rust` field should respect the following minimal requirements: -- value should be equal to "stable", "nightly: \*" or to a version in semver format. -Note that "1.50" is a valid value and implies "1.50.0". (also see "nightly versions" -extension) -- version should not be bigger than the current stable toolchain -- version should not be smaller than 1.27 (version in which `package.rust` field -became a warning instead of an error) - -`rust` will be a required field. For crates uploaded before introduction of this -feature 2015 edition crates will imply `rust="1.0"` and 2018 edition will imply -`rust = "1.30"`. +`rust` field value will be checked as well. During 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. -It will be an error to use `rust="1.27"` and `edition="2018"`, but `rust="1.40"` -and `edition="2015"` is a valid combination. +Implementing this functionality hopefully will allow us to close the long-standing +debate regarding whether MSRV bump is a breaking change or not and will allow +crate authors to feel less restrictive about bumping their crate's MSRV. (though +it may be a usefull convention for post-1.0 crates to bump minor version on MSRV +bump to allow publishing backports which fix serious issues using patch version) -# Reference-level explanation -[reference-level-explanation]: #reference-level-explanation +Note that described MSRV constraints and checks for dependency versions resolution +can be disabled with the `--no-msrv-check` option. -The describe functionality can be introduced in several stages: +## Checking MSRV during publishing +`cargo publish` will check that upload is done with a toolchain version specified +in the `rust` field. If toolchain version is different, `cargo` will refuse to +upload the crate. It will be a failsafe to prevent uses of incorrect `rust` values +due to unintended MSRV bumps. This check can be disabled by using the exisiting +`--no-verify` option. -## First stage: dumb field +## Making `rust` field mandatory -At first the `rust` field can be simply a declarative optional field without any -functionality behind it with minimal checks. The reason for it is to reduce -implementation cost of the first stage 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. +In future (probably in a next edition) we could make `rust` field mandatory for +a newly uploaded crates. MSRV for older crates will be determined by the `edition` +field. In other words `edition = "2018"` will imply `rust = "1.31"` and +`edition = "2015"` will imply `rust = "1.0"`. -## Second stage: `cargo publish` check +`cargo init` will use version of a currently used toolchain. -The next step is for `cargo publish` to require use of the toolchain specified -in the `rust` field, for example crates with: -- `rust="stable"` can be published only with a stable toolchain, though not -necessarily with the latest one. Cargo will insert toolchain version before -publishing the crate as was described in the "guide-level explanation". -- `rust="nightly: *"` can be published only with a nightly toolchain. If finer -grained "nightly: ..." (see "nightly versions" section) is selected, then one -of the selected Nightly versions will have to be used. -- `rust="1.30"` can be published only with (stable) Rust 1.30, even if it's -not the latest stable Rust version. +## `cfg`-based MSRVs -Using the usual build check `cargo publish` will verify that crate indeed can be -built using specified MSRV. This check can be used with exisiting `--no-verify` -option. +Some crates can have different MSRVs depending on target architecture or enabled +features. In such cases it can be usefull to describe how MSRV depends on them, +e.g. in the following way: +```toml +[package] +rust = "1.30" -## Third stage: versions resolution +[target.x86_64-pc-windows-gnu] +rust = "1.35" -`rust` field will be used as a constraint for dependency versions resolution. -If user uses e.g. Rust 1.40 and uses crate `foo = "0.2"`, but -all selected versions of `foo` specify MSRV e.g. equal 1.41 or bigger (or even -nightly) `cargo` will issue an error. +[target.'cfg(feature = "foo")'] +rust = "1.33" +``` -`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) +All `rust` values in the `target` sections should be equal or bigger to a `rust` value +specified in the `package` section. -Yanked crates will be ignored in this process. +If target condition is true, then `cargo ` will use `rust` value from this section. +If several target section conditions are true, then maximum value will be used. -Implementing this functionality hopefully 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. (though it can be a usefull -convention for post-1.0 crates to bump minor version on MSRV change to allow -publishing backports which fix serious issues using patch version) +# Nightly and stable versions -## Extension: nightly versions +Some crates may prefer to target only the most recent stable or nightly toolchain. +In addition to the versions we could allow `stable` and `nightly` values to declare +that maintainers do not track MSRV for the crate. For some bleeding-edge crates which experience frequent breaks on Nightly updates (e.g. `rocket`) it can be useful to specify exact Nightly version(s) on which @@ -149,28 +143,6 @@ it will take a current nightly version and will use it in a "more or equal" cons Such restrictions can be quite severe, but hopefully this functionality will be used only by handful of crates. -## Extension: cfg based MSRV - -Some crates can have different MSRVs depending on target architecture or enabled -features. In such cases it can be usefull to describe how MSRV depends on them, -e.g. in the following way: -```toml -[package] -rust = "1.30" - -[target.x86_64-pc-windows-gnu] -rust = "1.35" - -[target.'cfg(feature = "foo")'] -rust = "1.33" -``` - -All `rust` values in the `target` sections should be equal or bigger to a `rust` value -specified in the `package` section. - -If target condition is true, then `cargo ` will use `rust` value from this section. -If several target section conditions are true, then maximum value will be used. - # Drawbacks [drawbacks]: #drawbacks From a6e42daa25d0ab7bfb8ed52b75ede9fd92e5d52e Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Thu, 5 Sep 2019 00:49:49 +0000 Subject: [PATCH 07/19] fix sections --- text/0000-min-rust-version.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index 600466592a0..9ef91d37f11 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -1,4 +1,4 @@ -- Feature Name: min_rust_version +the minimum version- Feature Name: min_rust_version - Start Date: 2018-06-28 - RFC PR: (leave this empty) - Rust Issue: (leave this empty) @@ -54,7 +54,7 @@ became a warning instead of an error) - version can not be smaller than release version of a used edition, i.e. combination of `rust = "1.27"` and `edition = "2018"` is an invalid one. -# Future work (Extensions) +# Future work and extensions [future-work]: #future-work ## Influencing version resolution @@ -123,7 +123,7 @@ specified in the `package` section. If target condition is true, then `cargo ` will use `rust` value from this section. If several target section conditions are true, then maximum value will be used. -# Nightly and stable versions +## Nightly and stable versions Some crates may prefer to target only the most recent stable or nightly toolchain. In addition to the versions we could allow `stable` and `nightly` values to declare From e4c638ecca729f3771e8bd43b315aaa0d8dd4ea6 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Thu, 5 Sep 2019 01:04:03 +0000 Subject: [PATCH 08/19] fix list --- text/0000-min-rust-version.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index 9ef91d37f11..3f2bdf22991 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -46,12 +46,13 @@ tree, but will not be built are excluded from this check (e.g. target-dependent or optional crates). `rust` field should respect the following minimal requirements: -- value should be a version in semver format WITHOUT range operators. Note that -"1.50" is a valid value and implies "1.50.0". -- version can not be bigger than the current stable toolchain -- version can not be smaller than 1.27 (version in which `package.rust` field -became a warning instead of an error) -- version can not be smaller than release version of a used edition, i.e. +- Value should be a version in semver format **without** range operators. Note +that "1.50" is a valid value and implies "1.50.0". +- Version can not be bigger than a current stable toolchain (it will be checked +by crates.io during crate upload). +- Version can not be smaller than 1.27 (version in which `package.rust` field +became a warning instead of an error). +- Version can not be smaller than release version of a used edition, i.e. combination of `rust = "1.27"` and `edition = "2018"` is an invalid one. # Future work and extensions From 7580c202475349fb8a22ab721b7495093dec330d Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Fri, 20 Sep 2019 05:44:31 +0000 Subject: [PATCH 09/19] add RFC 2523 to the alternatives list --- text/0000-min-rust-version.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index 3f2bdf22991..5319975d60f 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -153,12 +153,13 @@ will work correctly on the specified MSRV, only appropriate CI testing can do th - MSRV selected by `cargo publish` with `rust = "stable"` can be too conservative. -# Rationale and Alternatives +# Alternatives [alternatives]: #alternatives - Automatically calculate MSRV. - Do nothing and rely on [LTS releases](https://github.com/rust-lang/rfcs/pull/2483) for bumping crate MSRVs. +- Allow version and path based `cfg` attributes as proposed in [RFC 2523](https://github.com/rust-lang/rfcs/pull/2523). # Prior art [prior-art]: #prior-art From 1aa64767f8caf9ae58962986629844b2bd9a542f Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Fri, 27 Sep 2019 23:45:52 +0000 Subject: [PATCH 10/19] Update text/0000-min-rust-version.md Co-Authored-By: Eric Huss --- text/0000-min-rust-version.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index 5319975d60f..90fe8c00e70 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -135,7 +135,7 @@ For some bleeding-edge crates which experience frequent breaks on Nightly update crate can be built. One way to achieve this is by using the following syntax: - auto-select: "nightly" This variant will behave in the same way as "stable", i.e. it will take a current nightly version and will use it in a "more or equal" constraint. -- single version: "nightly: 2018-01-01" (tha main variant) +- single version: "nightly: 2018-01-01" (the main variant) - enumeration: "nightly: 2018-01-01, 2018-01-15" - semver-like conditions: "nightly: >=2018-01-01", "nightly: >=2018-01-01, <=2018-01-15", "nightly: >=2018-01-01, <=2018-01-15, 2018-01-20". (the latter is interpreted as From 84aecf10f5432301a1a96733a30ab020dab3084e Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Fri, 27 Sep 2019 23:46:09 +0000 Subject: [PATCH 11/19] Update text/0000-min-rust-version.md Co-Authored-By: Eric Huss --- text/0000-min-rust-version.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index 90fe8c00e70..35ec6118dc1 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -90,7 +90,7 @@ can be disabled with the `--no-msrv-check` option. `cargo publish` will check that upload is done with a toolchain version specified in the `rust` field. If toolchain version is different, `cargo` will refuse to upload the crate. It will be a failsafe to prevent uses of incorrect `rust` values -due to unintended MSRV bumps. This check can be disabled by using the exisiting +due to unintended MSRV bumps. This check can be disabled by using the existing `--no-verify` option. ## Making `rust` field mandatory From a78e4b14128bf728732e6219dcde04beaf63691a Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Fri, 27 Sep 2019 23:46:21 +0000 Subject: [PATCH 12/19] Update text/0000-min-rust-version.md Co-Authored-By: Eric Huss --- text/0000-min-rust-version.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index 35ec6118dc1..3009019b719 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -105,7 +105,7 @@ field. In other words `edition = "2018"` will imply `rust = "1.31"` and ## `cfg`-based MSRVs Some crates can have different MSRVs depending on target architecture or enabled -features. In such cases it can be usefull to describe how MSRV depends on them, +features. In such cases it can be useful to describe how MSRV depends on them, e.g. in the following way: ```toml [package] From 73bdc96867be73290feab209771a690596e0daee Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Fri, 27 Sep 2019 23:46:35 +0000 Subject: [PATCH 13/19] Update text/0000-min-rust-version.md Co-Authored-By: Eric Huss --- text/0000-min-rust-version.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index 3009019b719..5db52d3cf17 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -79,7 +79,7 @@ Yanked crates will be ignored in this process. Implementing this functionality hopefully will allow us to close the long-standing debate regarding whether MSRV bump is a breaking change or not and will allow crate authors to feel less restrictive about bumping their crate's MSRV. (though -it may be a usefull convention for post-1.0 crates to bump minor version on MSRV +it may be a useful convention for post-1.0 crates to bump minor version on MSRV bump to allow publishing backports which fix serious issues using patch version) Note that described MSRV constraints and checks for dependency versions resolution From 7657ef4f6484879b87d956830f0689bb4b9bf6f9 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Fri, 27 Sep 2019 23:46:52 +0000 Subject: [PATCH 14/19] Update text/0000-min-rust-version.md Co-Authored-By: Eric Huss --- text/0000-min-rust-version.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index 5db52d3cf17..3847670c785 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -1,4 +1,4 @@ -the minimum version- Feature Name: min_rust_version +- Feature Name: min_rust_version - Start Date: 2018-06-28 - RFC PR: (leave this empty) - Rust Issue: (leave this empty) From ad12112a310dd9c8b214307ec7172522f2f19eb8 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Fri, 27 Sep 2019 23:47:04 +0000 Subject: [PATCH 15/19] Update text/0000-min-rust-version.md Co-Authored-By: Eric Huss --- text/0000-min-rust-version.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index 3847670c785..60ed797e0e3 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -60,7 +60,7 @@ combination of `rust = "1.27"` and `edition = "2018"` is an invalid one. ## Influencing version resolution -The value of `rust` field (explicit or autmatically selected by `cargo`) will +The value of `rust` field (explicit or automatically selected by `cargo`) will be used to select appropriate dependency versions. For example, let's imagine that your crate depends on crate `foo` with 10 published From 1a186ead4e4ac0d9b034c69e9b762080346370ff Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Tue, 1 Oct 2019 09:06:22 +0000 Subject: [PATCH 16/19] Update text/0000-min-rust-version.md Co-Authored-By: Chris Morgan --- text/0000-min-rust-version.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index 60ed797e0e3..8ad3d1832a9 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -100,7 +100,7 @@ a newly uploaded crates. MSRV for older crates will be determined by the `editio field. In other words `edition = "2018"` will imply `rust = "1.31"` and `edition = "2015"` will imply `rust = "1.0"`. -`cargo init` will use version of a currently used toolchain. +`cargo init` would use the version of the toolchain used. ## `cfg`-based MSRVs From 0cacbb68362a634fdeb2837f12409424ce128453 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Tue, 1 Oct 2019 09:06:52 +0000 Subject: [PATCH 17/19] Update text/0000-min-rust-version.md Co-Authored-By: Chris Morgan --- text/0000-min-rust-version.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index 8ad3d1832a9..d83161fbfc9 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -114,7 +114,7 @@ rust = "1.30" [target.x86_64-pc-windows-gnu] rust = "1.35" -[target.'cfg(feature = "foo")'] +[target.'cfg(feature = "foo")'.package] rust = "1.33" ``` From 386fd8a0faae618fb9959f08d5ffff2428e8f98b Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Tue, 1 Oct 2019 09:07:06 +0000 Subject: [PATCH 18/19] Update text/0000-min-rust-version.md Co-Authored-By: Chris Morgan --- text/0000-min-rust-version.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-min-rust-version.md b/text/0000-min-rust-version.md index d83161fbfc9..d1e3274fce9 100644 --- a/text/0000-min-rust-version.md +++ b/text/0000-min-rust-version.md @@ -111,7 +111,7 @@ e.g. in the following way: [package] rust = "1.30" -[target.x86_64-pc-windows-gnu] +[target.x86_64-pc-windows-gnu.package] rust = "1.35" [target.'cfg(feature = "foo")'.package] From 33ea5a7490297802d6affddaab55b587c933d3ae Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 10 Oct 2019 07:55:40 +0200 Subject: [PATCH 19/19] RFC 2495 --- text/{0000-min-rust-version.md => 2495-min-rust-version.md} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename text/{0000-min-rust-version.md => 2495-min-rust-version.md} (97%) diff --git a/text/0000-min-rust-version.md b/text/2495-min-rust-version.md similarity index 97% rename from text/0000-min-rust-version.md rename to text/2495-min-rust-version.md index d1e3274fce9..d952546ea12 100644 --- a/text/0000-min-rust-version.md +++ b/text/2495-min-rust-version.md @@ -1,7 +1,7 @@ -- Feature Name: min_rust_version +- Feature Name: `min_rust_version` - Start Date: 2018-06-28 -- RFC PR: (leave this empty) -- Rust Issue: (leave this empty) +- RFC PR: [rust-lang/rfcs#2495](https://github.com/rust-lang/rfcs/pull/2495) +- Rust Issue: [rust-lang/rust#](https://github.com/rust-lang/rust/issues/) # Summary [summary]: #summary