I'm implementing Rust Cargo version requirements. In general, I have trouble understanding caret requirements as specified. I found What's the difference between tilde(~) and caret(^) in package.json?, but this question is about npm version requirements of which I'm not sure if it is the same as Rust Cargo version requirements.
At https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#caret-requirements, I read:
Caret requirements allow SemVer compatible updates to a specified version. An update is allowed if the new version number does not modify the left-most non-zero digit in the major, minor, patch grouping. In this case, if we ran
cargo update -p time
, cargo should update us to version0.1.13
if it is the latest0.1.z
release, but would not update us to0.2.0
. If instead we had specified the version string as^1.0
, cargo should update to1.1
if it is the latest1.y
release, but not2.0
. The version0.0.x
is not considered compatible with any other version.
Here are some more examples of caret requirements and the versions that would be allowed with them:
^1.2.3 := >=1.2.3, <2.0.0 ^1.2 := >=1.2.0, <2.0.0 ^1 := >=1.0.0, <2.0.0 ^0.2.3 := >=0.2.3, <0.3.0 ^0.2 := >=0.2.0, <0.3.0 ^0.0.3 := >=0.0.3, <0.0.4 ^0.0 := >=0.0.0, <0.1.0 ^0 := >=0.0.0, <1.0.0
This compatibility convention is different from SemVer in the way it treats versions before
1.0.0
. While SemVer says there is no compatibility before1.0.0
, Cargo considers0.x.y
to be compatible with0.x.z
, wherey ≥ z
andx > 0
.
I'm confused about
In this case, if we ran
cargo update -p time
, cargo should update us to version0.1.13
if it is the latest0.1.z
release, but would not update us to0.2.0
.
With what version requirement is this the case? It seems left out of the sentence. It continues to refer to a seemingly missing caret version requirement:
If instead we had specified the version string as
^1.0
, cargo should update to1.1
if it is the latest1.y
release, but not2.0
.
In which it refers to >1.0
as the version string (which I miss in the sentence before).
If I dissect the examples, my reasoning is as follows:
^1.2.3 := >=1.2.3, <2.0.0 // same as >=1.2.3 AND 1.*
^1.2 := >=1.2.0, <2.0.0 // same as >=1.2 AND 1.*, which condenses into 1.2.*
^1 := >=1.0.0, <2.0.0 // same as 1.*
^0.2.3 := >=0.2.3, <0.3.0 // same as >=0.2.3 AND 0.2.*
^0.2 := >=0.2.0, <0.3.0 // same as 0.2.*, which condenses into 0.2.*
^0.0.3 := >=0.0.3, <0.0.4 // huh
^0.0 := >=0.0.0, <0.1.0 // same as >=0.0.0 AND 0.0.*
^0 := >=0.0.0, <1.0.0 // same as >=0.0.0 AND 0.*, which condenses into 0.*
So except for my understanding of the 6th example (^0.0.3
), my conclusion is that caret version requirements are exactly as wildcard version requirements, except when PATCH is specified in which the wildcard version requirement ANDs with the >= {version}
(equal or later then) comparison version requirement.
Is this understanding correct and why is example 6 as it is?