Alright, folks, it's time to take another crack at this.
There are a bunch of situations where one name shadowing another can make it impossible to address the declaration you want. One common example that comes up in module interfaces happens when a type has the same name as the module it belongs to:
// In module XCTest:
open class XCTest: NSObject { ... }
open class XCTestCase: XCTest { ... }
// In module MyTestHelpers:
import XCTest
extension XCTestCase {
public func myAssert(...) { ... }
}
// In generated MyTestHelpers.swiftinterface:
import XCTest
extension XCTest.XCTestCase { // Error--this looks for `XCTestCase` in `XCTest.XCTest`!
public func myAssert(...) { ... }
}
But there are a lot of minor variations on this theme that can come up in both module interfaces and human-written code.
To fix this, I propose adding a syntax called a "module selector" which always, unambiguously finds a top-level declaration in a given module. That way, the module interface can say something like this and get the right behavior:
import XCTest
extension XCTest::XCTestCase { // `XCTest::` is always interpreted as a module
public func myAssert(...) { ... }
}
I also propose supporting a module selector on member lookups:
_ = foo.Bar::baz() // calls the `baz()` declared in `Bar`, not one from an unrelated module
The full draft proposal is available here. This idea has previously been discussed in a pitch from 2019.