We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Modules, Visibility, Testing and Docs step 17 of 22
SemVer for Rust APIs: what actually breaks
This is the item that turns “I can write Rust” into “I can maintain a Rust library”, and it is where the visibility rules from 10.8 pay off. The public API is the reachable-path set, and a version bump is a claim about how that set changed.
pub fn classify(before: Vec<String>, after: Vec<String>) -> String
Return "major", "minor" or "patch" — the most severe applicable.
The API description language
Each line is one fact about the public surface.
struct Name exhaustive | non_exhaustive
enum Name exhaustive | non_exhaustive
field Struct.name pub | private
variant Enum.Name
trait Name
method Trait.name required | defaulted
fn name Bound+Bound (or `-` for no bounds)
Compare entities, not lines: struct S exhaustive becoming
struct S non_exhaustive is one entity changing, not a removal plus an
addition.
The table
Anything removed is major. A type, a field, a variant, a trait, a method, a function — if a path that used to work stops working, somebody’s build breaks.
Additions depend entirely on what was added.
| change | verdict | why |
|---|---|---|
| add a field to a struct whose fields are all public | major | breaks every struct literal and every exhaustive pattern |
| add a field to a struct that already had a private field | minor | nobody could build it with a literal anyway |
add a field to a #[non_exhaustive] struct |
minor | that is what the attribute is for |
| add a variant to a plain enum | major |
breaks every exhaustive match |
add a variant to a #[non_exhaustive] enum |
minor | downstream matches already need a wildcard |
| add a required trait method | major | every implementor stops compiling |
| add a defaulted trait method | minor | implementors inherit a body |
tighten a bound (Clone → Clone + Send) |
major |
callers whose type is not Send are locked out |
| loosen a bound | minor | strictly more callers |
| add a new type, trait or function | minor | |
add #[non_exhaustive] to an existing type |
major | it breaks exactly what it exists to prevent later |
remove #[non_exhaustive] |
minor | only relaxes |
field pub → private |
major | a readable field vanishes |
field private → pub |
minor | |
| nothing in the public surface changed | patch |
The first two rows are the pair worth remembering. The first private field in a struct is the breaking change, because it is the one that takes away literal construction. Every one after that is free.
Genuinely ambiguous cases, worth knowing about
These do not appear in the tests, because there is no correct answer to grade — but they are exactly the ones that will bite you.
Adding a defaulted trait method is listed as minor above and is what the reference says, but it can still break somebody: if a downstream type has an inherent method of the same name and the trait is in scope, the call becomes ambiguous. That is the E0659 machinery from 10.6 resurfacing as a compatibility hazard.
Raising your MSRV is treated as a minor bump by convention and breaks real
users on older toolchains. The community does not agree about this. The current
compromise is the rust-version field plus the MSRV-aware resolver (resolver 3,
implied by edition 2024), which will at least pick an older dependency version
rather than fail.
Auto-traits change silently. Adding an Rc to a private field can make your
type stop being Send, and every downstream spawn that moved it stops
compiling. There is no syntax to point at in the diff. cargo-semver-checks is
a very good mechanical guard and it cannot catch this, nor behavioural changes,
nor Drop semantics.
And one plain fact: #[non_exhaustive] has no effect within the defining
crate. In a single file — like every submission on this site — you can still
match a #[non_exhaustive] enum exhaustively with no wildcard and no warning.
The attribute is a promise to other crates.
Stuck?
Rust reference solution
Sign in to attempt this problem and reveal the reference solution.