Hello list,

Matthew Johnson and I have been putting our proposals together towards a joint 
“let’s fix private access levels” proposal. As the community seems quite 
divided on the issue, we offer two solutions in our proposal to let the 
community debate and to let the core team make the final decision.

I’d like to concentrate this round of feedback on the quality of the proposal, 
and not on the merits of Solution 1 or 2. thoughts?

https://github.com/hartbit/swift-evolution/blob/fix-private-access-levels/proposals/XXXX-fix-private-access-levels.md

David.

Fix Private Access Levels

Proposal: SE-XXXX 
<https://github.com/hartbit/swift-evolution/blob/fix-private-access-levels/proposals>
Authors: David Hart <http://github.com/hartbit>, Matthew Johnson 
<https://github.com/anandabits>
Review Manager: TBD
Status: TBD
 
<https://github.com/hartbit/swift-evolution/tree/fix-private-access-levels#introduction>Introduction

This proposal presents the problems the came with the the access level 
modifications in SE-0025 
<https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md>
 and presents two community driven solutions to fix them. As a consensus will 
not easily emerge, this proposal will allow a last round of voting and let the 
core team decide. Once that is done, this proposal will be ammended to describe 
the chosen solution.

 
<https://github.com/hartbit/swift-evolution/tree/fix-private-access-levels#motivation>Motivation

Since the release of Swift 3, the access level change of SE-0025 was met with 
dissatisfaction by a substantial proportion of the general Swift community. 
Before offering solutions, lets discuss how and why it can be viewed as actiely 
harmful, the new requirement for syntax/API changes.

 
<https://github.com/hartbit/swift-evolution/tree/fix-private-access-levels#criticisms-of-se-0025>Criticisms
 of SE-0025

There are two primary criticism that have been offered.

The first is that private is a "soft default" access modifier for restricting 
access within a file. Scoped access is not a good behavior for a "soft default" 
because it is extremely common to use several extensions within a file. A "soft 
default" (and therefore private) should work well with this idiom. It is fair 
to say that changing the behavior of private such that it does not work well 
with extensions meets the criteria of actively harmful in the sense that it 
subtly encourages overuse of scoped access control and discourages the more 
reasonable default by giving it the awkward name fileprivate.

The second is that Swift's system of access control is too complex. Many people 
feel like restricting access control to scopes less than a file is of dubious 
value and therefore wish to simplify Swift's access control story by removing 
scoped access. However, there are many others who like the ability to have the 
compiler verify tighter access levels and believe it helps make it easier to 
reason about code which is protecting invariants.

 
<https://github.com/hartbit/swift-evolution/tree/fix-private-access-levels#detailed-design>Detailed
 design

Both authors agree that the private keyword should be reverted back to its 
Swift 2 file-based meaning, resolving the first criticism. But the authors 
disagree on what should be done about the scoped access level and the following 
solutions represent the two main opinions in the community:

 
<https://github.com/hartbit/swift-evolution/tree/fix-private-access-levels#solution-1-remove-the-scoped-access-level>Solution
 1: Remove the scoped access level

Compared to a file-based access level, the scoped-based access level adds 
meaningful information by hiding implementation details which do not concern 
other types or extensions in the same file. But is that distinction between 
private and fileprivate actively used by the larger community of Swift 
developers? And if it were used pervasively, would it be worth the cognitive 
load and complexity of keeping two very similar access levels in the language? 
This solution argues that answer to both questions is no and that the scoped 
access level should be removed to resolve the complexity criticism.

This solution has the added advantage of leaving the most design breathing-room 
for future discussions about access levels in regards to submodules.

 
<https://github.com/hartbit/swift-evolution/tree/fix-private-access-levels#solution-2-rename-the-scoped-access-level-to-scoped>Solution
 2: Rename the scoped access level to scoped

It is difficult to make the case that a feature which a nontrivial number of 
Swift users find valuable and which is easy for teams to avoid is actively 
harmful. It seems like something that falls more into the category of a debate 
over style (which could be addressed by a linter). Should we remove a feature 
whose utility is a question of style, but is not actively harmful in the sense 
of causing programmer error? The second solution argues against it and proposes 
renaming it to scoped.

The scoped keyword is a good choice not only because the community has been 
calling this feature “scoped access control” all along, but also because the 
principle underlying all of Swift’s access levels is the idea of a scope.

 
<https://github.com/hartbit/swift-evolution/tree/fix-private-access-levels#source-compatibility>Source
 compatibility

In Swift 3 compatibility mode, the compiler will continue to treat private and 
fileprivate as was previously the case.

In Swift 4 mode, the compiler will deprecate the fileprivate keyword and revert 
the semantics of the private access level to be file based. The migrator will 
rename all uses of fileprivate to private. In solution 2, the migrator will 
also rename all uses of private to scoped.

With solution 1 (and with solution 2 if the migrator is not run), cases where a 
type had private declarations with the same signature in different scopes will 
produce a compiler error. For example, the following piece of code compiles in 
Swift 3 compatibilty mode but generates a Invalid redeclaration of 'foo()' 
error in Swift 4 mode.

struct Foo {
    private func bar() {}
}

extension Foo {
    private func bar() {}
}
 
<https://github.com/hartbit/swift-evolution/tree/fix-private-access-levels#alternatives-considered>Alternatives
 Considered

Deprecate fileprivate and modify the semantics of private to include same-type 
extension scopes in the same file.
Deprecate fileprivate and modify the semantics of private to include same-type 
extension scopes in the same module.
The alternatives are potentially interesting but completely remove the file 
access level while making the new privateaccess level more complicated to 
explain and understand.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to