There was this trick that VB5/VB6 could do in the old days. Basically, if you kept a compiled version of a library around, you could point the compiler at it and basically say “make sure I’m binary-compatible with that”. I believe that was to keep things like vtable layouts and the like consistent, not full on rejecting incompatible changes.
Theoretically, a tool could do something like this by dumping the public interface of a crate in some stable format, and having a way to diff two of them. Cargo could build on that to warn when there’s an (apparently) incompatible change without a corresponding change to the version number.
That said, I think some other things need to happen first. For one, I’d really like to be able to use stability markers. I’d definitely want to be able to deprecate things. Otherwise, it would be impossible to make anything public without an implicit “you can’t ever change this now” contract (currently, the best you can do is to also flag something in the docs, but this tool might create a stronger expectation of general stability).