Natalie Weizenbaum and I used SemVer when we created pub, the package manager for Dart. It was a good choice, but we definitely ran into some subtle problems over the years. Briefly:
* Like Steve notes, Semver doesn't specify any syntax and semantics ranges, constraints, or other "groups of versions". Every package manager just rolls its own thing, hopefully in a mostly compatible way.
* SemVer used to specify an ordering for build versions ("1.2.3+1" versus "1.2.3+2") and then later removed that. Pub still uses the older semantics because a package manager has to do something. If the user requests "foo 1.2.3" and both "1.2.3+1" and "1.2.3+2" exist, what's the package manager supposed to do? Pick randomly? So we still technically use the older SemVer spec where this ordering is defined.
* It's hard for a package to transition into a period of experimental development. Let's say you maintain foo which has lots of users. Foo 1.2.3 is out and lots of people are using it. You want to start working on a major, breaking revision to foo. You need to do that in a way that doesn't spontaneously break existing users, but you also want to ship something so that you can get feedback from early adopters.
Right now, the way you do this is by shipping a series of pre-release versions like 2.0.0-dev.1, etc. That works, but users are often confused that a range like ">=2.0.0" does not include those dev versions, nor does "<2.0.0". It doesn't feel to me that SemVer gracefully handles the idea that previously stable packages may go through periods of instability. Pre-releases are sort of the imaginary numbers of SemVer where they don't really fit the natural linearization of version numbers.
Many projects now have "channels" of development where users can indicate whether they want to be on "stable", "dev", "bleeding edge", etc. When it comes to pre-releases and experimental versions, I think users generally want to indicate whether they want to be on the bleeding edge or not. Today, at least in pub, they have to indicate that using some carefully crafted version constraint that only includes pre-releases. It would be nice if that was a more direct way to express that.
(The fact that SemVer doesn't define ranges compounds this. I think our interpretation of ranges mostly follows npm.)