- Proposal: TBD
- Author(s): Erica Sadun
- Status: TBD
- Review manager: TBD
This proposal creates a way to resolve SwiftPM module conflicts. It introduces namespacing to handle the rare case of name overlaps without requiring a central package registry.
This proposal was discussed on the Swift-Dev and Swift-Build-Dev lists in the "Right List?" thread.
Swift offers a built in mechanism for distinguishing symbol conflicts. When working with NSView
, using Swift.print
outputs text to the console or stream. NSView
's print
creates a print job. Swift does not yet offer a solution for conflicting module names.
Like many other Swift developers, I have spent considerable time building utility packages. Mine use obvious names like SwiftString
and SwiftCollections
because simple clear naming is a hallmark of Swift design. At the same time, this style introduces the possibility of package name conflicts.
import SwiftString // mine
import SwiftString // someone else's. oops.
Two SwiftString
packages cannot be used simultaneously without some form of namespace resolution. Moving back to Cocoa-style namespacing, for example ESSwiftString
, feels ugly and antithetical to Swift. Swift should encourage recognizable, easy-to-understand module names. This proposal addresses this rare but possible conflict.
Under the current system, same-named modules:
import PackageDescription
let package = Package (
name: "myutility",
dependencies: [
.Package(url: "https://github.com/erica/SwiftString.git",
majorVersion: 1),
.Package(url: "https://github.com/nudas/SwiftString.git",
majorVersion: 1),
]
)
produce the following errors:
% swift build
Cloning Packages/SwiftString
Using version 1.0.5 of package SwiftString
Cloning Packages/SwiftString
/usr/bin/git clone --recursive --depth 10 https://github.com/nudas/SwiftString.git /home/erica/Work/test/Packages/SwiftString
fatal: destination path '/home/erica/Work/test/Packages/SwiftString' already exists and is not an empty directory.
swift-build: Failed to clone https://github.com/nudas/SwiftString.git to /home/erica/Work/test/Packages/SwiftString
Makefile:3: recipe for target 'all' failed
make: *** [all] Error 1
Under this proposal, the Swift Package manager uses reverse domain naming to differentiate otherwise identically-named items. The two conflicting packages in the following example:
import PackageDescription
let package = Package (
name: "MyUtility",
dependencies: [
.Package(url: "https://github.com/erica/SwiftString.git",
majorVersion: 1),
.Package(url: "https://github.com/bob/SwiftString.git",
majorVersion: 1),
]
)
unpack to Packages/com.github.erica.SwiftString
and Packages/com.github.bob.SwiftString
rather than Packages/SwiftString
.
These can then be imported using the full RDN notation:
import com.github.erica.SwiftString
import com.github.bob.SwiftString
Reverse domain names
- are rarely used outside the import statement and only to distinguish overlapping implementations
- are relatively short
- are already well established for Apple app distribution
- are tied to the hosting repo
However concise, using reverse domain names bring verbiage to name conflicts. Upon adopting this proposal, I intend following through with language specific proposals that allow either import as
or right-to-left namespacing.
A Swift import as
statement would allow a developer to rename a module on import:
import com.github.erica.SwiftString as EricaString
A right-to-left alternative would require only as much of the reverse domain name prefix as needed to distinguish one implementation from another, for example:
erica.SwiftString.print(x)
bob.SwiftString.print(x)
although presumably the fully specified RDN prefix could be used as well:
com.github.erica.SwiftString.print(x)
Thanks to Joe Groff, Ankit Aggarwal, Max Howell, Daniel Dunbar, Kostiantyn Koval
Modified per suggestions.
importAs
scans better, so I chose that. Added note about clashes (should cause compilation error)