mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-28 11:20:36 +00:00
docs(ref): Document MSRV-aware resolver
This commit is contained in:
parent
0498e84f89
commit
498d4df89f
@ -143,6 +143,9 @@ rpath = false # Sets the rpath linking option.
|
||||
[profile.<name>.package.<name>] # Override profile for a package.
|
||||
# Same keys for a normal profile (minus `panic`, `lto`, and `rpath`).
|
||||
|
||||
[resolver]
|
||||
incompatible-rust-versions = "allow" # Specifies how resolver reacts to these
|
||||
|
||||
[registries.<name>] # registries other than crates.io
|
||||
index = "…" # URL of the registry index
|
||||
token = "…" # authentication token for the registry
|
||||
@ -972,6 +975,30 @@ See [rpath](profiles.md#rpath).
|
||||
|
||||
See [strip](profiles.md#strip).
|
||||
|
||||
### `[resolver]`
|
||||
|
||||
The `[resolver]` table overrides [dependency resolution behavior](resolver.md) for local development (e.g. excludes `cargo install`).
|
||||
|
||||
#### `resolver.incompatible-rust-versions`
|
||||
* Type: string
|
||||
* Default: `"allow"`
|
||||
* Environment: `CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS`
|
||||
|
||||
When resolving which version of a dependency to use, select how versions with incompatible `package.rust-version`s are treated.
|
||||
Values include:
|
||||
- `allow`: treat `rust-version`-incompatible versions like any other version
|
||||
- `fallback`: only consider `rust-version`-incompatible versions if no other version matched
|
||||
|
||||
Can be overridden with
|
||||
- `--ignore-rust-version` CLI option
|
||||
- Setting the dependency's version requirement higher than any version with a compatible `rust-version`
|
||||
- Specifying the version to `cargo update` with `--precise`
|
||||
|
||||
See the [resolver](resolver.md#rust-version) chapter for more details.
|
||||
|
||||
> **MSRV:**
|
||||
> - `allow` is supported on any version
|
||||
> - `fallback` is respected as of 1.84
|
||||
|
||||
### `[registries]`
|
||||
|
||||
|
@ -73,7 +73,7 @@ Key steps:
|
||||
|
||||
### Version numbers
|
||||
|
||||
Cargo prefers the highest version currently available.
|
||||
Generally, Cargo prefers the highest version currently available.
|
||||
|
||||
For example, if you had a package in the resolve graph with:
|
||||
```toml
|
||||
@ -83,6 +83,8 @@ bitflags = "*"
|
||||
If at the time the `Cargo.lock` file is generated, the greatest version of
|
||||
`bitflags` is `1.2.1`, then the package will use `1.2.1`.
|
||||
|
||||
For an example of a possible exception, see [Rust version](#rust-version).
|
||||
|
||||
### Version requirements
|
||||
|
||||
Package specify what versions they support, rejecting all others, through
|
||||
@ -201,6 +203,88 @@ ecosystem if you publish a SemVer-incompatible version of a popular library.
|
||||
[semver trick]: https://github.com/dtolnay/semver-trick
|
||||
[`downcast_ref`]: ../../std/any/trait.Any.html#method.downcast_ref
|
||||
|
||||
### Rust version
|
||||
|
||||
To support developing software with a minimum supported [Rust version],
|
||||
the resolver can take into account a dependency version's compatibility with your Rust version.
|
||||
This is controlled by the config field [`resolver.incompatible-rust-versions`].
|
||||
|
||||
With the `fallback` setting, the resolver will prefer packages with a Rust version that is
|
||||
equal to or greater than your own Rust version.
|
||||
For example, you are using Rust 1.85 to develop the following package:
|
||||
```toml
|
||||
[package]
|
||||
name = "my-cli"
|
||||
rust-version = "1.62"
|
||||
|
||||
[dependencies]
|
||||
clap = "4.0" # resolves to 4.0.32
|
||||
```
|
||||
The resolver would pick version 4.0.32 because it has a Rust version of 1.60.0.
|
||||
- 4.0.0 is not picked because it is a [lower version number](#version-numbers) despite it also having a Rust version of 1.60.0.
|
||||
- 4.5.20 is not picked because it is incompatible with `my-cli`'s Rust version of 1.62 despite having a much [higher version](#version-numbers) and it has a Rust version of 1.74.0 which is compatible with your 1.85 toolchain.
|
||||
|
||||
If a version requirement does not include a Rust version compatible dependency version,
|
||||
the resolver won't error but will instead pick a version, even if its potentially suboptimal.
|
||||
For example, you change the dependency on `clap`:
|
||||
```toml
|
||||
[package]
|
||||
name = "my-cli"
|
||||
rust-version = "1.62"
|
||||
|
||||
[dependencies]
|
||||
clap = "4.2" # resolves to 4.5.20
|
||||
```
|
||||
No version of `clap` matches that [version requirement](#version-requirements)
|
||||
that is compatible with Rust version 1.62.
|
||||
The resolver will then pick an incompatible version, like 4.5.20 despite it having a Rust version of 1.74.
|
||||
|
||||
When the resolver selects a dependency version of a package,
|
||||
it does not know all the workspace members that will eventually have a transitive dependency on that version
|
||||
and so it cannot take into account only the Rust versions relevant for that dependency.
|
||||
The resolver has heuristics to find a "good enough" solution when workspace members have different Rust versions.
|
||||
This applies even for packages in a workspace without a Rust version.
|
||||
|
||||
When a workspace has members with different Rust versions,
|
||||
the resolver may pick a lower dependency version than necessary.
|
||||
For example, you have the following workspace members:
|
||||
```toml
|
||||
[package]
|
||||
name = "a"
|
||||
rust-version = "1.62"
|
||||
|
||||
[package]
|
||||
name = "b"
|
||||
|
||||
[dependencies]
|
||||
clap = "4.2" # resolves to 4.5.20
|
||||
```
|
||||
Though package `b` does not have a Rust version and could use a higher version like 4.5.20,
|
||||
4.0.32 will be selected because of package `a`'s Rust version of 1.62.
|
||||
|
||||
Or the resolver may pick too high of a version.
|
||||
For example, you have the following workspace members:
|
||||
```toml
|
||||
[package]
|
||||
name = "a"
|
||||
rust-version = "1.62"
|
||||
|
||||
[dependencies]
|
||||
clap = "4.2" # resolves to 4.5.20
|
||||
|
||||
[package]
|
||||
name = "b"
|
||||
|
||||
[dependencies]
|
||||
clap = "4.5" # resolves to 4.5.20
|
||||
```
|
||||
Though each package has a version requirement for `clap` that would meet its own Rust version,
|
||||
because of [version unification](#version-numbers),
|
||||
the resolver will need to pick one version that works in both cases and that would be a version like 4.5.20.
|
||||
|
||||
[Rust version]: rust-version.md
|
||||
[`resolver.incompatible-rust-versions`]: config.md#resolverincompatible-rust-versions
|
||||
|
||||
### Features
|
||||
|
||||
For the purpose of generating `Cargo.lock`, the resolver builds the dependency
|
||||
|
@ -29,6 +29,8 @@ benchmarks, etc.
|
||||
`cargo add` will auto-select the dependency's version requirement to be the latest version compatible with your `rust-version`.
|
||||
If that isn't the latest version, `cargo add` will inform users so they can make the choice on whether to keep it or update your `rust-version`.
|
||||
|
||||
The [resolver](resolver.md#rust-version) may take Rust version into account when picking dependencies.
|
||||
|
||||
Other tools may also take advantage of it, like `cargo clippy`'s
|
||||
[`incompatible_msrv` lint](https://rust-lang.github.io/rust-clippy/stable/index.html#/incompatible_msrv).
|
||||
|
||||
@ -131,6 +133,10 @@ potentially limiting access to features of the shared dependency for the workspa
|
||||
To allow users to patch a dependency on one of your workspace members,
|
||||
every package in the workspace would need to be loadable in the oldest Rust version supported by the workspace.
|
||||
|
||||
When using [`incompatible-rust-versions = "fallback"`](config.md#resolverincompatible-rust-versions),
|
||||
the Rust version of one package can affect dependency versions selected for another package with a different Rust version.
|
||||
See the [resolver](resolver.md#rust-version) chapter for more details.
|
||||
|
||||
### One or More Policies
|
||||
|
||||
One way to mitigate the downsides of supporting older Rust versions is to apply your policy to older major or minor versions of your package that you continue to support.
|
||||
|
@ -351,31 +351,7 @@ This was stabilized in 1.79 in [#13608](https://github.com/rust-lang/cargo/pull/
|
||||
|
||||
### MSRV-aware resolver
|
||||
|
||||
`-Zmsrv-policy` allows access to an MSRV-aware resolver which can be enabled with:
|
||||
- `resolver.incompatible-rust-versions` config field
|
||||
- `workspace.resolver = "3"` / `package.resolver = "3"`
|
||||
- `package.edition = "2024"` (only in workspace root)
|
||||
|
||||
The resolver will prefer dependencies with a `package.rust-version` that is the same or older than your project's MSRV.
|
||||
As the resolver is unable to determine which workspace members will eventually
|
||||
depend on a package when it is being selected, we prioritize versions based on
|
||||
how many workspace member MSRVs they are compatible with.
|
||||
If there is no MSRV set then your toolchain version will be used, allowing it to pick up the toolchain version from pinned in rustup (e.g. `rust-toolchain.toml`).
|
||||
|
||||
#### `resolver.incompatible-rust-versions`
|
||||
* Type: string
|
||||
* Default: `"allow"`
|
||||
* Environment: `CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS`
|
||||
|
||||
When resolving a version for a dependency, select how versions with incompatible `package.rust-version`s are treated.
|
||||
Values include:
|
||||
- `allow`: treat `rust-version`-incompatible versions like any other version
|
||||
- `fallback`: only consider `rust-version`-incompatible versions if no other version matched
|
||||
|
||||
Can be overridden with
|
||||
- `--ignore-rust-version` CLI option
|
||||
- Setting the dependency's version requirement higher than any version with a compatible `rust-version`
|
||||
- Specifying the version to `cargo update` with `--precise`
|
||||
This was stabilized in 1.83 in [#14639](https://github.com/rust-lang/cargo/pull/14639).
|
||||
|
||||
### Convert `incompatible_toolchain` error into a lint
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user