Skip to content

Commit 8775067

Browse files
authored
Merge pull request #2495 from newpavlov/msrv
RFC: Minimum Supported Rust Version
2 parents 2b0c911 + 33ea5a7 commit 8775067

File tree

1 file changed

+179
-0
lines changed

1 file changed

+179
-0
lines changed

text/2495-min-rust-version.md

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
- Feature Name: `min_rust_version`
2+
- Start Date: 2018-06-28
3+
- RFC PR: [rust-lang/rfcs#2495](https://github.com/rust-lang/rfcs/pull/2495)
4+
- Rust Issue: [rust-lang/rust#](https://github.com/rust-lang/rust/issues/)
5+
6+
# Summary
7+
[summary]: #summary
8+
9+
Add `rust` field to the package section of `Cargo.toml` which will be used to
10+
specify crate's Minimum Supported Rust Version (MSRV):
11+
```toml
12+
[package]
13+
name = "foo"
14+
version = "0.1.0"
15+
rust = "1.30"
16+
```
17+
18+
# Motivation
19+
[motivation]: #motivation
20+
21+
Currently crates have no way to formally specify MSRV. As a result users can't
22+
check if crate can be built on their toolchain without building it. It also
23+
leads to the debate on how to handle crate version change on bumping MSRV,
24+
conservative approach is to consider such changes as breaking ones, which can
25+
hinder adoption of new features across ecosystem or result in version number
26+
inflation, which makes it harder to keep downstream crates up-to-date. More
27+
relaxed approach on another hand can result in broken crates for user of older
28+
compiler versions.
29+
30+
# Guide-level explanation
31+
[guide-level-explanation]: #guide-level-explanation
32+
33+
If you target a specific MSRV add a `rust` field to the `[package]` section of
34+
your `Cargo.toml` with a value equal to the targeted Rust version. If you build
35+
a crate with a dependency which has MSRV higher than the current version of your
36+
toolchain, `cargo` will return a compilation error stating the dependency and
37+
its MSRV. This behavior can be disabled by using `--no-msrv-check` flag.
38+
39+
# Reference-level explanation
40+
[reference-level-explanation]: #reference-level-explanation
41+
42+
During build process (including `run`, `test`, `benchmark`, `verify` and `publish`
43+
sub-commands) `cargo` will check MSRV requirements of all crates in a dependency
44+
tree scheduled to be built or checked. Crates which are part of the dependency
45+
tree, but will not be built are excluded from this check (e.g. target-dependent
46+
or optional crates).
47+
48+
`rust` field should respect the following minimal requirements:
49+
- Value should be a version in semver format **without** range operators. Note
50+
that "1.50" is a valid value and implies "1.50.0".
51+
- Version can not be bigger than a current stable toolchain (it will be checked
52+
by crates.io during crate upload).
53+
- Version can not be smaller than 1.27 (version in which `package.rust` field
54+
became a warning instead of an error).
55+
- Version can not be smaller than release version of a used edition, i.e.
56+
combination of `rust = "1.27"` and `edition = "2018"` is an invalid one.
57+
58+
# Future work and extensions
59+
[future-work]: #future-work
60+
61+
## Influencing version resolution
62+
63+
The value of `rust` field (explicit or automatically selected by `cargo`) will
64+
be used to select appropriate dependency versions.
65+
66+
For example, let's imagine that your crate depends on crate `foo` with 10 published
67+
versions from `0.1.0` to `0.1.9`, in versions from `0.1.0` to `0.1.5` `rust`
68+
field in the `Cargo.toml` sent to crates.io equals to "1.30" and for others to
69+
"1.40". Now if you'll build your project with e.g. Rust 1.33, `cargo` will select
70+
`foo v0.1.5`. `foo v0.1.9` will be selected only if you'll build your project with
71+
Rust 1.40 or higher. But if you'll try to build your project with Rust 1.29 cargo
72+
will issue an error.
73+
74+
`rust` field value will be checked as well. During crate build `cargo` will check
75+
if all upstream dependencies can be built with the specified MSRV. (i.e. it will
76+
check if there is exists solution for given crates and Rust versions constraints)
77+
Yanked crates will be ignored in this process.
78+
79+
Implementing this functionality hopefully will allow us to close the long-standing
80+
debate regarding whether MSRV bump is a breaking change or not and will allow
81+
crate authors to feel less restrictive about bumping their crate's MSRV. (though
82+
it may be a useful convention for post-1.0 crates to bump minor version on MSRV
83+
bump to allow publishing backports which fix serious issues using patch version)
84+
85+
Note that described MSRV constraints and checks for dependency versions resolution
86+
can be disabled with the `--no-msrv-check` option.
87+
88+
## Checking MSRV during publishing
89+
90+
`cargo publish` will check that upload is done with a toolchain version specified
91+
in the `rust` field. If toolchain version is different, `cargo` will refuse to
92+
upload the crate. It will be a failsafe to prevent uses of incorrect `rust` values
93+
due to unintended MSRV bumps. This check can be disabled by using the existing
94+
`--no-verify` option.
95+
96+
## Making `rust` field mandatory
97+
98+
In future (probably in a next edition) we could make `rust` field mandatory for
99+
a newly uploaded crates. MSRV for older crates will be determined by the `edition`
100+
field. In other words `edition = "2018"` will imply `rust = "1.31"` and
101+
`edition = "2015"` will imply `rust = "1.0"`.
102+
103+
`cargo init` would use the version of the toolchain used.
104+
105+
## `cfg`-based MSRVs
106+
107+
Some crates can have different MSRVs depending on target architecture or enabled
108+
features. In such cases it can be useful to describe how MSRV depends on them,
109+
e.g. in the following way:
110+
```toml
111+
[package]
112+
rust = "1.30"
113+
114+
[target.x86_64-pc-windows-gnu.package]
115+
rust = "1.35"
116+
117+
[target.'cfg(feature = "foo")'.package]
118+
rust = "1.33"
119+
```
120+
121+
All `rust` values in the `target` sections should be equal or bigger to a `rust` value
122+
specified in the `package` section.
123+
124+
If target condition is true, then `cargo ` will use `rust` value from this section.
125+
If several target section conditions are true, then maximum value will be used.
126+
127+
## Nightly and stable versions
128+
129+
Some crates may prefer to target only the most recent stable or nightly toolchain.
130+
In addition to the versions we could allow `stable` and `nightly` values to declare
131+
that maintainers do not track MSRV for the crate.
132+
133+
For some bleeding-edge crates which experience frequent breaks on Nightly updates
134+
(e.g. `rocket`) it can be useful to specify exact Nightly version(s) on which
135+
crate can be built. One way to achieve this is by using the following syntax:
136+
- auto-select: "nightly" This variant will behave in the same way as "stable", i.e.
137+
it will take a current nightly version and will use it in a "more or equal" constraint.
138+
- single version: "nightly: 2018-01-01" (the main variant)
139+
- enumeration: "nightly: 2018-01-01, 2018-01-15"
140+
- semver-like conditions: "nightly: >=2018-01-01", "nightly: >=2018-01-01, <=2018-01-15",
141+
"nightly: >=2018-01-01, <=2018-01-15, 2018-01-20". (the latter is interpreted as
142+
"(version >= 2018-01-01 && version <= 2018-01-20) || version == 2018-01-20")
143+
144+
Such restrictions can be quite severe, but hopefully this functionality will be
145+
used only by handful of crates.
146+
147+
# Drawbacks
148+
[drawbacks]: #drawbacks
149+
150+
- Declaration of MSRV, even with the checks, does not guarantee that crate
151+
will work correctly on the specified MSRV, only appropriate CI testing can do that.
152+
- More complex dependency versions resolution algorithm.
153+
- MSRV selected by `cargo publish` with `rust = "stable"` can be too
154+
conservative.
155+
156+
# Alternatives
157+
[alternatives]: #alternatives
158+
159+
- Automatically calculate MSRV.
160+
- Do nothing and rely on [LTS releases](https://github.com/rust-lang/rfcs/pull/2483)
161+
for bumping crate MSRVs.
162+
- Allow version and path based `cfg` attributes as proposed in [RFC 2523](https://github.com/rust-lang/rfcs/pull/2523).
163+
164+
# Prior art
165+
[prior-art]: #prior-art
166+
167+
Previous proposals:
168+
- [RFC 1707](https://github.com/rust-lang/rfcs/pull/1707)
169+
- [RFC 1709](https://github.com/rust-lang/rfcs/pull/1709)
170+
- [RFC 1953](https://github.com/rust-lang/rfcs/pull/1953)
171+
- [RFC 2182](https://github.com/rust-lang/rfcs/pull/2182) (arguably this one got off-track)
172+
173+
# Unresolved questions
174+
[unresolved]: #unresolved-questions
175+
176+
- Name bike-shedding: `rust` vs `rustc` vs `min-rust-version`
177+
- Additional checks?
178+
- Better description of versions resolution algorithm.
179+
- How nightly versions will work with "cfg based MSRV"?

0 commit comments

Comments
 (0)