This gets often suggested every time the version bounds topic comes up (to some degree, that's the direction backpack is going btw). But unfortunately this does not work:
Because what this argument ignores is that you get a similar problem you have with duck-typing on a different level: You assume that the same name & type-signature provides the same semantics. However, the types usually leave too much degree of freedom to provide a proper contract. And you have to find a way to encode that contract.
The best-bang-for-buck way we currently have to encode this contract is... well... the PVP! Version numbers announce the contract, while version bounds define which contract you rely on.
Unless we have a better way to solve this, there's no alternative to the PVP. Unfortunately, so far I have not heard any workable solution from PVP complainers. So that's that.