An analysis of semver compliance in Rust finds accidental semver violations are common even in the most popular crates. Human error is not the cause, and better tooling is the way forward.
Is that even possible though? Sometimes you need a human to understand if something is a breaking change.
Imagine an API like fnthird_planet_from_sun() ->String, and an update is made where the output changes the value to be lowercase instead of capitalized. That should normally be considered a breaking change.
However, imagine fncurrent_version() ->String. That is by its definition meant to change outputs between versions, so it isn’t a breaking change since that’s part of its human, documentation based API contract.
Also, what if somw function which returns a String changes, but only one code path that is very hard to hit changes the output? How would a machine find that?
I guess the first example with Earth / version could use some attribute macro so devs can say the output is expected to change across versions, but then there is no way for a program to know what is a breaking change vs expected vs a bug.
To do it 100% probably isn’t possible, something something halting problem. However, you’d catch a lot of basic mistakes with proper typing. In your example, the first function should be typed like this: fnthird_planet_from_sun() -> Planet, where Planet is an enum. De/serializing it still has the same problem of interpreting an arbitrary string, but at least for deserializing it, you can be loose in what you allow and just lowercase it before matching it to the enum.
Is that even possible though? Sometimes you need a human to understand if something is a breaking change.
Imagine an API like
fn third_planet_from_sun() -> String
, and an update is made where the output changes the value to be lowercase instead of capitalized. That should normally be considered a breaking change.However, imagine
fn current_version() -> String
. That is by its definition meant to change outputs between versions, so it isn’t a breaking change since that’s part of its human, documentation based API contract.Also, what if somw function which returns a String changes, but only one code path that is very hard to hit changes the output? How would a machine find that?
I guess the first example with Earth / version could use some attribute macro so devs can say the output is expected to change across versions, but then there is no way for a program to know what is a breaking change vs expected vs a bug.
To do it 100% probably isn’t possible, something something halting problem. However, you’d catch a lot of basic mistakes with proper typing. In your example, the first function should be typed like this:
fn third_planet_from_sun() -> Planet
, wherePlanet
is an enum. De/serializing it still has the same problem of interpreting an arbitrary string, but at least for deserializing it, you can be loose in what you allow and just lowercase it before matching it to the enum.