> Presumably you mean compatible rather than incompatible there?
I've edited for clarity, I mean "because packages with different major versions should have incompatible APIs anyway."
> While you can specify upper bounds for the depdnency ranges, that is extremely uncommon in practice.
In https://github.com/rust-lang/crates.io-index I count just under 7000 upper bounds on dependency ranges that aren't just semver in disguise (e.g. not ">=1.0.0, <2.0.0"):
$ rg --no-filename -o '"req":"[^"]*<[^"]*"' . | grep -Ev '< ?=? ?([0-9]+(\.0){0,2}|0\.[0-9]+(\.0)?)"' | wc -l
6727
So it's definitely used. One person's non-breaking change is another's breaking change https://xkcd.com/1172/