Rust has tooling to automatically enforce semver. For example, this tool: https://github.com/rust-dev-tools/rust-semverver
Once you modify a Rust library, it downloads the last released version, compiles it and extracts its AST, and compares it with the AST of the current version.
The diff of the two ASTs tells you what the changes are, and there is a Rust book that documents which changes are semver breaking and which aren't. So if you only add a new function to your crate, the tool says that you can bump the semver patch version or minor version, but if you change the name of a public API, the tool requires you to make a new major semver release.
Setting this tool in CI is dead easy, and will make your CI fail if a PR changes the API of your crate without properly updating its semver version.