You would build it with error with Xcode 15.4 and Xcode 16.(Xcode 15.2 would build success.)
If you remove the import PassKit in Test.swift, it will build success.
If you change the Package name from Network to something like NetworkApi, it will build success.
Looks like the PassKit is incompatible with swift package with named Network.
This isn't necessarily a Swift compiler issue so you might have better luck on the Apple developer forums, but I suspect that you're hitting this problem because Network is the name of a framework in Apple's SDKs, and you giving your own module the same name is confusing the compiler somewhere during module loading. You should choose a different name for your module that doesn't collide with those on the system.
Thank you for the suggestion. But how would it compile with Xcode 15.2 but error with Xcode 15.4?
And if this issue cause by the same name with Apple SDK and my own package, I can change my package name, but what if that is a third party framework, if it would suddenly compile fail because same name with Apple SDK and need to change the whole name, I don't think it's a good solution.
The compiler should provide a way to deal with it. Just like the namespace in Swift.
The problem doesn't just exist with Apple's SDK modules. You can't have two modules with the same name anywhere in your build graph because their symbols might collide, whether they're Apple SDK modules or modules from different Swift packages. So, the recommendation is usually to avoid very generic names for your modules by prepending them with some more-likely-to-be-unique identifier, like the name of your project.
It's a good defense, IMO. If you're working on a project named, say, Gribnar, then using names like GribnarUI, GribnarCommon, GribnarModels is going to make things a lot less painful in the future. It avoids a situation where you have a module named something like Support or Utils and then later you add a new third-party dependency that has something named Utils deep in its dependency graph.
-module-alias can help somewhat with that, but I think it's even better to just defensively name things to reduce the chances of it happening in the first place.
Ultimately developers in any language need to use something to distinguish symbols that are going to be linked into the same binary or loaded into the same address space from other symbols that they don't control. A name prefix is just one method to do that. While arguments can be made that something like filesystem/path/style or cpp::style::namespaces or com.reverse.domain names would "look cleaner" than juxtaposing the words, those are all still just different forms of name prefixes.