I have a class called OperationQueue defined in FrameworkA
I created a typealias to point to FrameworkA.OperationQueuebut forgot to make OperationQueuepublic
Code:
FrameworkA:
import Foundation
class OperationQueue : Foundation.OperationQueue { } //Forgot to make it public
App:
import Foundation
import FrameworkA
typealias OperationQueue = FrameworkA.OperationQueue
let oq = OperationQueue()
Problem:
When I ran the project, FrameworkA.OperationQueue wasn't used instead Foundation's class was used because my class wasn't public. It works as expected when I defined it as public.
Question:
It is my mistake not making it public, but curious, would the compiler be able to spot that the class being pointed to (by typealias) is not accessible and throw a compilation error ?
It's not hard to check for that, but is it worth the time? You might have equally intended to use Foundation.OperationQueue. It is not recommended to load the compiler with warnings that are rather a guess than helpful. That is in contrast to, say, when you explicitly refer to an inaccessible declaration, i.e. FrameworkA.OperationQueue. Moreover, I wouldn't call shadowing top-level declarations from other modules good practice. On rare occasions it can be useful as a hack.
This looks like a straightforward bug to me. I can't see a reason why typealias OperationQueue = FrameworkA.OperationQueue should compile at all when FrameworkA.OperationQueue isn't visible in the app.
Um, yeah. If importing module A in module B doesn't imply A being part of B when referring to the latter. But I think it does, otherwise accessibility would be messed up with declarations in B that use A. If so, FrameworkA.OperationQueue resolves to Foundation.OperationQueue if FrameworkA imports Foundation and the other OperationQueue is inaccessible.
This was something that I stumbled upon while working on a framework, just felt it might add more transparency if it threw a compilation error if possible.
@xwu I also noticed something strange, not sure if I am making a blunder.
I tried to reference it directly without the typealias, the issue isn't with typealias but accessing classes defined in more than one framework.
Even when FrameworkA.OperationQueue() is explicitly mentioned while creating a variable, it still uses Foundation.OperationQueue()
Not sure if others are also facing the same issue or if I am missing something obvious.
FrameworkA
import Foundation
class OperationQueue { } //Forgot to make it public
class X {}
App:
import UIKit
import FrameworkA
let oq = FrameworkA.OperationQueue() //Uses Foundation.OperationQueue
//Following throw compilation errors:
let x1 = X() //Use of unresolved identifier 'X'
let x2 = FrameworkA.X() //Module 'FrameworkA' has no member named 'X'
You don't import a module into another module, you import a module into a source code file - a single compilation unit. For example, if module B has two source files: b1.swift and b2.swift, if I import module A into b1.swift its public types are visible in b1.swift but they are not visible in b2.swift. Although, having done some experimentation, it seems that if a public method returns an object of a type defined in A, that type seems to be exported from B as well, which I guess is needed so that callers can use the return result.
However, if you see code that says let foo = A.OperationQueue() the intent is clearly that you want an instance of A.OperationQueue and not Foundation.OperationQueue. That should be an error IMO.
I did not mean you could literally import a module into another module, nor did I use the 'into' preposition.
The method can be internal. This also applies to generics and any at least internal precedent of a visible declaration or ready-to-use object of a type that comes from A, as long as you don't have to manually instantiate it in the latter case. Public entities can be further propagated this way across modules.