diff --git a/src/doc/src/reference/resolver.md b/src/doc/src/reference/resolver.md index fd835885bd6..21b66898b45 100644 --- a/src/doc/src/reference/resolver.md +++ b/src/doc/src/reference/resolver.md @@ -71,31 +71,48 @@ Key steps: Cargo may decide that it should prefer a specific version, falling back to the next version when backtracking. +### Version numbers + +Cargo prefers the highest version currently available. + +For example, if you had a package in the resolve graph with: +```toml +[dependencies] +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`. + +### Version requirements + +Package specify what versions they support, rejecting all others, through +[version requirements]. + +For example, if you had a package in the resolve graph with: +```toml +[dependencies] +bitflags = "1.0" # meaning `>=1.0.0,<2.0.0` +``` +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` because it is the +greatest within the compatibility range. If `2.0.0` is published, it will +still use `1.2.1` because `2.0.0` is considered incompatible. + +[version requirements]: specifying-dependencies.md#version-requirement-syntax + ### SemVer compatibility -Cargo uses [SemVer] for specifying version numbers. This establishes a common -convention for what is compatible between different versions of a package. See -the [SemVer Compatibility] chapter for guidance on what is considered a -"compatible" change. This notion of "compatibility" is important because Cargo -assumes it should be safe to update a dependency within a compatibility range -without breaking the build. - -Versions are considered compatible if their left-most non-zero -major/minor/patch component is the same. For example, `1.0.3` and `1.1.0` are -considered compatible, and thus it should be safe to update from the older -release to the newer one. However, an update from `1.1.0` to `2.0.0` would not -be allowed to be made automatically. This convention also applies to versions -with leading zeros. For example, `0.1.0` and `0.1.2` are compatible, but -`0.1.0` and `0.2.0` are not. Similarly, `0.0.1` and `0.0.2` are not -compatible. - -When multiple packages specify a dependency for a common package, the resolver -attempts to ensure that they use the same version of that common package, as -long as they are within a SemVer compatibility range. It also attempts to use -the greatest version currently available within that compatibility range. For -example, if there are two packages in the resolve graph with the following -requirements: +Cargo assumes packages follow [SemVer] and will unify dependency versions if they are +[SemVer] compatible according to the [Caret version requirements]. +If two compatible versions cannot be unified because of conflicting version requirements, +Cargo will error. + +See the [SemVer Compatibility] chapter for guidance on what is considered a +"compatible" change. +Examples: + +The following two packages will have their dependencies on `bitflags` unified because any version picked will be compatible with each other. ```toml # Package A [dependencies] @@ -106,15 +123,20 @@ bitflags = "1.0" # meaning `>=1.0.0,<2.0.0` bitflags = "1.1" # meaning `>=1.1.0,<2.0.0` ``` -If at the time the `Cargo.lock` file is generated, the greatest version of -`bitflags` is `1.2.1`, then both packages will use `1.2.1` because it is the -greatest within the compatibility range. If `2.0.0` is published, it will -still use `1.2.1` because `2.0.0` is considered incompatible. +The following packages will error because the version requirements conflict, selecting two distinct compatible versions. +```toml +# Package A +[dependencies] +log = "=0.4.11" -If multiple packages have a common dependency with semver-incompatible -versions, then Cargo will allow this, but will build two separate copies of -the dependency. For example: +# Package B +[dependencies] +log = "=0.4.8" +``` +The following two packages will not have their dependencies on `rand` unified because only incompatible versions are available for each. +Instead, two different versions (e.g. 0.6.5 and 0.7.3) will be resolved and built. +This can lead to potential problems, see the [Version-incompatibility hazards] section for more details. ```toml # Package A [dependencies] @@ -125,31 +147,23 @@ rand = "0.7" # meaning `>=0.7.0,<0.8.0` rand = "0.6" # meaning `>=0.6.0,<0.7.0` ``` -The above will result in Package A using the greatest `0.7` release (`0.7.3` -at the time of this writing) and Package B will use the greatest `0.6` release -(`0.6.5` for example). This can lead to potential problems, see the -[Version-incompatibility hazards] section for more details. - -Multiple versions within the same compatibility range are not allowed and will -result in a resolver error if it is constrained to two different versions -within a compatibility range. For example, if there are two packages in the -resolve graph with the following requirements: - +Generally, the following two packages will not have their dependencies unified because incompatible versions are available that satisfy the version requirements: +Instead, two different versions (e.g. 0.6.5 and 0.7.3) will be resolved and built. +The application of other constraints or heuristics may cause these to be unified, +picking one version (e.g. 0.6.5). ```toml # Package A [dependencies] -log = "=0.4.11" +rand = ">=0.6,<0.8.0" # Package B [dependencies] -log = "=0.4.8" +rand = "0.6" # meaning `>=0.6.0,<0.7.0` ``` -The above will fail because it is not allowed to have two separate copies of -the `0.4` release of the `log` package. - [SemVer]: https://semver.org/ [SemVer Compatibility]: semver.md +[Caret version requirements]: specifying-dependencies.md#default-requirements [Version-incompatibility hazards]: #version-incompatibility-hazards #### Version-incompatibility hazards