This is less of a Swift PM issue and more of a "how modules are designed in Swift" issue. Unlike Java packages and similar modular concepts that define best practices like reverse-DNS form, Swift's design encourages short module names, and this makes it very easy for someone to define modules like "Basic" or "Utility" in isolation, making it easy to collide with modules in other projects once they start integrating other dependencies that they don't own.
At a minimum, we should be offering best practices for naming modules in a scalable way, especially if tools like SPM encourage you to break up your project into multiple small modules. For example, should everyone just prepend their project name to each of their modules for an extra layer of protection? That seems to be where SPM and the common-tools library that's being split out of it are headed. It's an improvement, but it feels like we've just taken the Objective-C prefix problem and moved it one layer up the chain
At Google, our Bazel build rules for Swift by default derive a module name from the path to the build target; for example, if the build manifest file
foo/bar/baz/BUILD defines a Swift target named
quux, then the module name is
foo_bar_baz_quux (since we're limited to identifier-valid characters). We mandate the use of auto-generated module names (except for third-party code, which needs to be built with the module name it was designed for), and since we have a monorepo, this is enough to more-or-less guarantee uniqueness. But it leaves us with some very ugly
I'm not sure what I'd recommend to improve the situation. I could say "let people use dots in module names and encourage reverse-DNS as a best practice", but maybe that's just a "feel good" solution since it's just trading one punctuation mark for another; I can say it looks better, but unless I have something more objective, it's not very convincing.
A bolder idea that @jrose and I discussed briefly once was to extend the private-discriminator concept for
fileprivate declarations to whole modules; the idea being that when you build the graph, you can specify unique discriminators for each module at compile time that would affect type lookup and also get encoded into the mangled symbol names (to avoid potential collisions between symbols in the object files). But that really only works if you're building all your dependencies from source, and it has its own complications (changing the mangled symbol names means you need to figure out how to handle runtime type lookup, etc.).