The issue is due to the interaction of several factors:
This crate allows a range of major versions of git2 and uses git2's types in its public API.
Even if the type's name and contents have not changed across major versions, rustc still considers types from different major versions to be completely different types and not interchangeable with each other. This also applies to enums and their variants: variants from different major versions are not interchangeable.
This crate's public API returns values that publicly contain git2 error types. When downstream crates interact with those types (for example, here), they may need to name git2 enum variants.
This crate does not re-export git2 or those git2 types, so downstream code has no way to say "use whichever git2 version crates-index uses." Instead, it is forced to guess the maximum git2 major version allowed by the crates-index range of supported git2 versions. When that guess in downstream code is correct, everything seems to work fine. If the guess is wrong, rustc correctly says that we're comparing two unrelated types and errors out.
In 0.x versions, cargo considers the x to be the major version number. And since cargo and Rust allow having multiple major versions of the same crate simultaneously, a bound like >=0.15, <0.17 is effectively always going to resolve to the most recent 0.16.x release. There's essentially nothing that a downstream crate can do to preventgit2 version 0.16 from being chosen for crates-index: even demanding git2 = 0.15 isn't enough — that will simply cause both 0.15 and 0.16 to be installed.
For v0.18.11, the maximum allowed git2 version was 0.15. The new v0.18.12 release was the first to allow (and because of above, the first to require) git2 version 0.16. Because of the above, this was a breaking change.
Here's what I'd recommend and would be happy to help with:
Yank 0.18.12 and re-release it as 0.19.0, which is a major version bump. All git2 major version changes in crates-index requirements are required to also be major bumps for crates-index to adhere to semver.
Re-export git2 to allow downstream crates to more safely interact with the contents of the Error enum by using the re-exported types.
Consider specifying a single major version of git2 as a requirement, since the maximal 0.x version allowed in the current range ends up currently being chosen anyway.
Consider adopting cargo-semver-checks as part of the release process (for example). While it couldn't have caught today's issue, it can catch 40 other common kinds of semver issues, and more lints are added all the time. You can read more about it here.
Thanks for all the work you're doing on this awesome crate! If there's any way I can help, please ping me at any time.
Hi! I'm the author of
cargo-semver-checks
, a Rust linter that ensures crates adhere to semantic versioning.The newly-released version 0.18.12 is semver-incompatible with prior 0.18.x releases due to breaking changes in the
Error
enum here, themselves caused by the dropped support forgit2
version 0.14 and the added support for version 0.16 here. Unfortunately,cargo-semver-checks
itself is affected by this break — you can see it here: https://github.com/obi1kenobi/cargo-semver-checks/issues/317The issue is due to the interaction of several factors:
git2
and usesgit2
's types in its public API.git2
error types. When downstream crates interact with those types (for example, here), they may need to namegit2
enum variants.git2
or thosegit2
types, so downstream code has no way to say "use whichevergit2
versioncrates-index
uses." Instead, it is forced to guess the maximumgit2
major version allowed by thecrates-index
range of supportedgit2
versions. When that guess in downstream code is correct, everything seems to work fine. If the guess is wrong, rustc correctly says that we're comparing two unrelated types and errors out.x
to be the major version number. And since cargo and Rust allow having multiple major versions of the same crate simultaneously, a bound like>=0.15, <0.17
is effectively always going to resolve to the most recent 0.16.x release. There's essentially nothing that a downstream crate can do to preventgit2
version 0.16 from being chosen forcrates-index
: even demandinggit2 = 0.15
isn't enough — that will simply cause both 0.15 and 0.16 to be installed.git2
version was 0.15. The new v0.18.12 release was the first to allow (and because of above, the first to require)git2
version 0.16. Because of the above, this was a breaking change.Here's what I'd recommend and would be happy to help with:
git2
major version changes incrates-index
requirements are required to also be major bumps forcrates-index
to adhere to semver.git2
to allow downstream crates to more safely interact with the contents of theError
enum by using the re-exported types.git2
as a requirement, since the maximal 0.x version allowed in the current range ends up currently being chosen anyway.cargo-semver-checks
as part of the release process (for example). While it couldn't have caught today's issue, it can catch 40 other common kinds of semver issues, and more lints are added all the time. You can read more about it here.Thanks for all the work you're doing on this awesome crate! If there's any way I can help, please ping me at any time.