rustrust-cargo

Why does Rust's Cargo not consider version 0.8.3 to have a compatible API with version 0.9.0?


I'm reading the Rust book. Specifically this section about Semantic Versioning used by Cargo.

What doesn't really make sense is this:

The number 0.8.3 is actually shorthand for ^0.8.3, which means any version that is at least 0.8.3 but below 0.9.0. Cargo considers these versions to have public APIs compatible with version 0.8.3, and this specification ensures you'll get the latest patch release that will still compile with the code in this chapter. Any version 0.9.0 or greater is not guaranteed to have the same API as what the following examples use.

According to the rules for semantic versioning, a change of the minor version (from 0.8.3 to 0.9.0) can NOT contain changes that break the public API. Why does Cargo think that the public API for these 2 versions may not be compatible? Is it because the major version happens to be 0? If we were dealing with a case where the major version was > 0 (Ex. 1.8.3), would specifying 1.8.3 in Cargo.toml allow Cargo to install version 1.9.0 then?


Solution

  • As documented in the Specifying Dependencies chapter of The Cargo Book (emphasis added):

    The string "0.1.12" is a semver version requirement. Since this string does not have any operators in it, it is interpreted the same way as if we had specified "^0.1.12", which is called a caret requirement.

    Caret requirements

    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.

    [...]

    This compatibility convention is different from SemVer in the way it treats versions before 1.0.0. While SemVer says there is no compatibility before 1.0.0, Cargo considers 0.x.y to be compatible with 0.x.z, where y ≥ z and x > 0.