Compiler bug?

If I declare an internal protocol and try to introduce a public extension on it, I will very reasonably get a compilation error:

internal protocol InternalProtocol {
}

/// Compilation error: "Extension of internal protocol cannot be declared public"
public extension InternalProtocol {
}

However, for the same protocol there is no compiler error if I add a public function in an internal extension:

internal extension InternalProtocol {
    /// No compiler error here.
    public var hello: String { "Hello" }
}

I can create something that conforms to the protocol:

public struct PublicThing: InternalProtocol {
    public init() {}
}

Now, if in a test that uses the regular import, I try to call the public hello, I get an compilation error:

    func testNewThing() {
        let thing = PublicThing()
        /// Compiler error here: "'hello' is inaccessible due to 'internal' protection level"
        _ = thing.hello
    }

It is unexpected to me that I don't get a compilation error when I try to declare something public in an extension given that it does not become public. Is this a bug, or does it make sense an I'm missing something here?

Thanks!

1 Like

You’re allowed to put a more visible access control modifier on a member of a less visible type. The actual access level of a member is then the minimum of the declared access levels of each outer scope.

1 Like

Amusingly enough, while this was generally deliberate, for extensions the proposed design as approved by the core team actually had this forbidden (for...reasons), but forbidding it was never implemented.

2 Likes