Comment by Diggsey
They are different:
"0": ">=0.0.0, <1.0.0"
"0.9": ">=0.9.0, <1.0.0"
"0.9.3": ">=0.9.3, <1.0.0"
Notice how the the minimum bound changes while the upper bound is the same for all of them.The reason for this is that unless otherwise specified, the ^ operator is used, so "0.9" is actually "^0.9", which then gets translated into the kind of range specifier I showed above.
There are other operators you can use, these are the common ones:
(default) ^ Semver compatible, as described above
>= Inclusive lower bound only
< Exclusive upper bound only
= Exact bound
Note that while an exact bound will force that exact version to be used, it still doesn't allow two semver compatible versions of a crate to exist together. For example. If cargo can't find a single version that satisfies all constraints, it will just error.For this reason, if you are writing a library, you should in almost all cases stick to regular semver-compatible dependency specifications.
For binaries, it is more common to want exact control over versions and you don't have downstream consumers for whom your exact constraints would be a nightmare.