A while ago I noticed private extension members became accessible from other extensions. As I discovered recently, the change happened before I joined the community, so I wasn't aware this went through the evolution process. I am raising this topic because I failed to see the compelling reason that lead to the
proposal's acceptance, or, rather, to the removal of scoped access as a byproduct. The proposal is named «Improve interaction between private declarations and extensions». Note there is no question of scoped access removal. Here is the problem stated therein:
In Swift 3, a declaration marked
private
may be accessed by anything nested in the scope of the private declaration. For example, a private property or method defined on a struct may be accessed by other methods defined within that struct.This model was introduced by SE-0025 and with nearly a year of experience using this model, it has worked well in almost all cases.
The primary case it falls down is when the implementation of a type is split into a base definition and a set of extensions. Because of the SE-0025 model, extensions to the type are not allowed to access private members defined on that type.
...
Swift encourages developers to use extensions as a logical grouping mechanism ...
Within a file, allowing extensions to access private members of the primary declaration actually makes sense: the primary declaration should not hide anything from an extension.
However, if Swift encourages logical grouping and it was in fact (prior to implementing the proposal) a very popular technique to isolate functionality via extensions, why does the proposal touch the extension-extension case as well? The proposal mentions that SE-159 was rejected because «scoped access is something that many developers use and value», but itself ends up not only solving the problem it states, but also needlessly removing scoped access as a feature completely. Neither allowing extensions to access private members on a type nor preventing prevalent fileprivate
usage requires removing scoped access between extensions or between a type declaration and an extension. What is the rationale for «improving interaction between private declarations and extensions» by removing an only partially related feature?
The prevalence of
fileprivate
in practice has caused mixed reactions from Swift developers, culminating in proposal SE-0159 which suggested reverting the access control model to Swift 2’s design. That proposal was rejected for two reasons: scoped access is something that many developers use and value, and because it was seen as too large of a change given Swift 4’s source compatibility goals.
Today, you can no longer declare a private helper method in an extension and expect it to be inaccessible from outside the extension without moving it to a separate file, which is rather frustrating.