November 18, 2023 - 2882 words - 15 mins
cargo-semver-checks v0.25 squashes nearly all bugs related to
doc(hidden) items — its most common source of false-positives. What does
doc(hidden) mean in Rust, and why was handling it correctly so hard?
September 07, 2023 - 3270 words - 17 mins
This post is coauthored by Tomasz Nowak and Predrag Gruevski. It describes work the two of us did together with Bartosz Smolarczyk, Michał Staniewski, and Mieszko Grodzicki.
cargo-semver-checks is a helpful tool for preventing the semver violations that every so often cause ecosystem-wide pain.
This is why it earned a spot in the CI pipelines of key Rust crates like
tokio, and also why the
cargo team hopes to integrate it into
While anedotal evidence is nice, we wanted to get concrete data across a large sample of real-world Rust code.
May 08, 2023 - 3718 words - 19 mins
A few days ago, I started polls on Mastodon and Twitter whether adding a new private type, or an import, can ever be a major breaking change. The consensus was that this should be impossible.
I agree with that. It should be impossible.
I've discovered a way to cause a previously-public type or function to disappear from a crate's public API by making innocuous-seeming changes like adding a private type or adding an import, etc.
It is not a hypothetical problem, either — I've found at least one real-world Rust project that has been affected by it.
March 06, 2023 - 813 words - 5 mins
We've already explored some of the dark corners of Rust semantic versioning on this blog:
February 07, 2023 - 3926 words - 20 mins
This post describes work in progress: how
cargo-semver-checks will benefit from the upcoming query optimization API in the Trustfall query engine. Read on to learn how a modern linter works under the hood, and how ideas from the world of databases can improve its performance.
January 31, 2023 - 1194 words - 6 mins
I recently embarked on a quest: revamp the cargo-semver-checks import-handling system so that moving and re-exporting an item stops being incorrectly flagged as a major breaking change. This is how crate authors can reorganize or rename items: just re-export the items in the original location under …
January 26, 2023 - 1848 words - 10 mins
I've been saying for a while now that semantic versioning in Rust is tricky and full of unexpected edge cases.
My last post mentioned that some Rust structs can be converted into enums without requiring a major version bump. It introduced a non-exhaustive struct called Chameleon that had no public f…
January 24, 2023 - 1611 words - 9 mins
EDIT: The Rust API evolution RFC distinguishes between breaking changes and changes that require a new semver-major version (called major changes). All major changes are breaking, but not all breaking changes are major. Changing a struct to an enum is always breaking (as pointed out on r/rust) but i…
December 23, 2022 - 1946 words - 10 mins
cargo-semver-checks ends 2022 with 40,000 downloads from crates.io, able to prevent 30 different kinds of semver issues, and having done so in real-world use cases.
Inspired by Yoshua Wuyts' "Rust in 2023 (by Yosh)" post, here are my thoughts on cargo-semver-checks in 2022, and what I look…
August 25, 2022 - 1866 words - 10 mins
I recently built
cargo-semver-checks, a linter that ensures crates adhere to semantic versioning. This is why and how I built it.
Fearless development is a key theme throughout Rust.
"If it compiles, it works",
fearless concurrency, etc.
But there's one aspect of Rust (and nearly all other languages) that isn't entirely fearless yet:
cargo update, upgrading the versions of the project's dependencies.