I think @shlim raised a valid question. Not only the Swift access control doc lacks the information explaining why the following code works, but also it apparently has incorrect information.
private class PrivateClass {
var x = 0
}
PrivateClass().x
In "Custom Types" section of the doc, it says
The access control level of a type also affects the default access level of that type’s members (its properties, methods, initializers, and subscripts). If you define a type’s access level as private or file private, the default access level of its members will also be private or file private.
Then it gives this example:
private class SomePrivateClass { // explicitly private class
func somePrivateMethod() {} // implicitly private class member
}
With the above information, it's impossible for one to understand why the example code works, because PrivateClass().x is neither in the declaration of PrivateClass nor its extension (that's the definition of private access in the Swift doc).
I find the answer in SE-0025. It has a dedicated section explaining the behavior.
When a type is defined with the private access modifier, things become a little more complicated. Of course the type itself is visible only within the lexical scope it is defined in, but what about members of the type?
If the members of a private type are themselves considered private, it is very clear that they cannot be used outside of the type itself. However, it is also not currently permitted for a member to have an access level greater than its enclosing type. This restriction produces a conundrum: the type can be referenced within its enclosing lexical scope, but none of its members can.
Ignoring formal concerns, the most likely expected behavior is that members not explicitly marked private are permitted to be accessed within the enclosing scope of the private type.
To achieve this goal, we relax a few of the existing rules:
- The default level of access control anywhere is internal.
...
That not only explains why the example code works, but also indicates the description in the Swift doc I quoted above is incorrect, because they conflict with the following design in SE-0025 (emphasis mine):
The default level of access control anywhere is internal.
I believe the Swift doc must have gone through many iterations of review by people who know the ins and outs of the language. Could it be that the doc was written before SE-0025 was implemented? Or the design in SE0025 was changed later? but I don't find SE doc for that change. Also, if the current implementation really worked in the way described by the Swift doc, I don't think the example code could work. So I suspect this is a bug in Swift doc. I'm copying to people in the document work group for their opinion. CC @franklin