This compromise solution looks very good to me. Thanks Xiaodi for the effort 
put into working through our whining to come to the best solution IMHO.

> On 18 Jul 2016, at 09:50, Xiaodi Wu via swift-evolution 
> <[email protected]> wrote:
> 
> All righty, thanks for all of your feedback. I've worked on revising the 
> proposal this evening, re-reading previous documents and messages and 
> re-analyzing what people meant. I think Jose is absolutely right in the end, 
> and the proposal has turned out like he suggested. Here is the current draft 
> below:
> 
> Harmonize access modifiers for extensions
> 
> Proposal: SE-XXXX
> Author: Xiaodi Wu
> Status: Awaiting review
> Review manager: TBD
> Introduction
> 
> During discussion of SE-0119, some voiced concern that writing public 
> extension increases the default access level for members declared within that 
> extension, whereas writing public class or public struct does not do the same.
> 
> This behavior is explained as follows: since extensions have no runtime 
> representation and are not first-class entities, access modifiers on 
> extensions serve as a shorthand to set the default access level for members. 
> Certain members of the community have indicated that such behavior makes 
> extensions a natural grouping construct.
> 
> A general principle of Swift, recently strengthened by proposals such as 
> SE-0117, has been that public API commitments should require explicit opt-in. 
> Given the different behavior of classes and structs, the fact that extensions 
> allow public methods to be declared without spelling out public at the 
> declaration site has been called "confusing" or "odd."
> 
> The aim of this proposal is to, in as conservative a manner as possible, 
> require explicit use of public for public methods declared inside any 
> extension.
> 
> Swift-evolution threads:
> 
> [Proposal] Revising access modifiers on extensions
> [Review] SE-0119: Remove access modifiers from extensions
> [Draft] Harmonize access modifiers for extensions
> Motivation
> 
> Consider the following:
> 
> public struct foo {
>   func frobnicate() { } // internal
> }
> public extension foo { }
> 
> public struct bar { }
> public extension bar {
>   func frobnicate() { } // public
> }
> This outcome is explained by rules regarding access modifiers specifically on 
> extensions Swift 2, which is slated for preservation in Swift 3 as detailed 
> in SE-0025. However, it is arguably surprising that, of two declarations 
> spelled identically, one leads to a public API commitment while the other 
> does not.
> 
> Proposed solution
> 
> The proposed solution is to amend access modifier rules to eliminate the 
> possibility of defaulting the access level of members declared inside an 
> extension to public.
> 
> Detailed design
> 
> Amend access modifier rules as follows:
> 
> An extension may optionally be marked with an explicit access modifier that 
> specifies the default scope [see SE-0025]. However, such an explicit modifier 
> must not match (or exceed) the original type's access level.
> 
> This rule would preserve the possibility of using extensions as grouping 
> constructs. At the same time, it would (1) remove the possibility of writing 
> public extension to default the access level of members to public; and (2) 
> clarify the notion that an access modifier on an extension is a shorthand and 
> not a way to create a first-class entity by disallowing repeating of the 
> original type's access level.
> 
> Explicit access modifiers will continue to set the maximum allowed access 
> within an extension, as clarified in SE-0025.
> 
> Alternatives considered
> 
> One alternative is to eliminate explicit access modifiers on extensions 
> altogether. As an advantage, this would further clarify the mental model that 
> extensions are not their own first-class entities. As a disadvantage, 
> extensions cease to be an access modifier grouping construct, which some 
> users really like.
> 
> Acknowledgments
> 
> Thanks to all discussants on the list, especially Adrian Zubarev, Jose Cheyo 
> Jimenez, and Paul Cantrell.
> 
> 
> 
>> On Sun, Jul 17, 2016 at 11:08 AM, Xiaodi Wu <[email protected]> wrote:
>> I understand how it works.
>> 
>> By aligning access modifier rules inside extensions with those inside types, 
>> all other modifiers would continue to work as it does now (implicitly 
>> internal members would be limited by the upper bound). The only change in 
>> this respect is removing the ability to have public API without writing 
>> `public func`.
>> 
>>> On Sun, Jul 17, 2016 at 11:01 Adrian Zubarev via swift-evolution 
>>> <[email protected]> wrote:
>>> I tackled it as an upper bound but highly rejected by the community. That’s 
>>> exactly what my proposal was all about. An upper boundary would be more 
>>> elegant, but I still see arguments ‘because it’s not a type’.
>>> 
>>> I could live without access modifiers on extensions in general.
>>> 
>>> The default access modifier rule permits public methods to be written 
>>> without public func
>>> 
>>> You meant this?
>>> 
>>> public extension SomeType {
>>>     // I don't need to write public
>>>     func foo() {}
>>>     var computed: Type {}
>>> }
>>> This applies to all access modifiers which are not optional (like internal):
>>> 
>>> public SomeType
>>> fileprivate extension SomeType {
>>>     // I don't need to repeat fileprivate
>>>     func foo() {}
>>>     var computed: Type {}
>>> }
>>> 
>>> // which is more likely `fileprivate` because it's on file scope
>>> private extension SomeType {
>>>     // even if the inner access modifier would pretend to be private
>>>     // since the extension is on filescope, everything will be `fileprivate`
>>>     func foo() {}
>>>     var computed: Type {}
>>> }
>>> 
>>> 
>>> -- 
>>> Adrian Zubarev
>>> Sent with Airmail
>>> 
>>> Am 17. Juli 2016 um 17:50:31, Xiaodi Wu ([email protected]) schrieb:
>>> 
>>>> The proposal is that the access modifier for an extension will either be 
>>>> removed entirely or remain as an upper bound, losing its function as a 
>>>> default access modifier. The default access modifier rule permits public 
>>>> methods to be written without `public func`; this is a proposal to remove 
>>>> that feature because it is a source of confusion.
>>>>> On Sun, Jul 17, 2016 at 10:43 Adrian Zubarev via swift-evolution 
>>>>> <[email protected]> wrote:
>>>>> I still don’t catch to point here. There is no implicit public there. 
>>>>> It’s explicit set by the default access modifier of extensions. It’s how 
>>>>> they work and how they should remain (at least as long the community want 
>>>>> default access modifier to exist on extensions). Disallowing setting 
>>>>> public on extensions when you extend a public type makes no sense. If you 
>>>>> want your member to be internal like it’s in types, then remove the 
>>>>> access modifier from extension and all member will follow the type access 
>>>>> modifier.
>>>>> 
>>>>> 
>>>>> 
>>>>> -- 
>>>>> Adrian Zubarev
>>>>> Sent with Airmail
>>>>> 
>>>>> Am 17. Juli 2016 um 17:37:02, Xiaodi Wu ([email protected]) schrieb:
>>>>> 
>>>>>> That's a good point. I will incorporate these into a revised draft. Only 
>>>>>> two things will change:
>>>>>> 
>>>>>> ```
>>>>>> public struct Foo {
>>>>>>   // implicitly internal
>>>>>>   func frobnicate1() { }
>>>>>> }
>>>>>> public extension Foo {
>>>>>>   // currently implicitly public
>>>>>>   //
>>>>>>   // depending on which alternative is adopted,
>>>>>>   // the proposal will either prohibit `public extension`
>>>>>>   // or this method will be implicitly internal
>>>>>>   func frobnicate2() { }
>>>>>> }
>>>>>> ```
>>>>>> 
>>>>>> ```
>>>>>> internal struct Bar {
>>>>>>   // permitted by SE-0025 without a warning
>>>>>>   // this method can only be accessed within module anyway
>>>>>>   // because `internal struct` bounds access of its members
>>>>>>   public func frobnicate1() { }
>>>>>> }
>>>>>> extension Bar {
>>>>>>   // not permitted by SE-0025
>>>>>>   //
>>>>>>   // after proposal, this will also be permitted without a warning
>>>>>>   // and this method will also be accessible only within module
>>>>>>   public func frobnicate2() { }
>>>>>> }
>>>>>> ```
>>>>>> 
>>>>>>> On Sun, Jul 17, 2016 at 1:50 AM, Adrian Zubarev via swift-evolution 
>>>>>>> <[email protected]> wrote:
>>>>>>> I’m struggling to understand your proposal, can you provide some 
>>>>>>> specific code samples how it works now and what will change. The 
>>>>>>> example from the draft doesn’t help my understanding. :/
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> -- 
>>>>>>> Adrian Zubarev
>>>>>>> Sent with Airmail
>>>>>>> 
>>>>>>> Am 17. Juli 2016 um 04:40:45, Xiaodi Wu via swift-evolution 
>>>>>>> ([email protected]) schrieb:
>>>>>>> 
>>>>>>>>> On Sat, Jul 16, 2016 at 7:56 PM, Jose Cheyo Jimenez 
>>>>>>>>> <[email protected]> wrote:
>>>>>>>>> I think you can simplify this proposal by just saying something like 
>>>>>>>>> this and give a couple of examples that are easy to follow:
>>>>>>>>> 
>>>>>>>>> Disallow explicit public access modifier on non-protocol-conforming 
>>>>>>>>> type extensions.
>>>>>>>> 
>>>>>>>> It took me a while to process what you're trying to say here, but this 
>>>>>>>> is a good idea and would go along well with the first draft's proposed 
>>>>>>>> solution. I will spell it out. (If we say that you can use an explicit 
>>>>>>>> modifier only to lower the access level of members, then `public` as 
>>>>>>>> an explicit modifier could be entirely disallowed.)
>>>>>>>>  
>>>>>>>>> 
>>>>>>>>> I think if you only focus on that breaking change then the proposal 
>>>>>>>>> will have a good chance of getting accepted and fixing the immediate 
>>>>>>>>> issue of public. There is a reason why protocol conforming extensions 
>>>>>>>>> do not allow explicitly saying public 
>>>>>>>>> `public extension Type: Protocol {}` // public not allowed 
>>>>>>>> 
>>>>>>>> Actually, no modifiers are allowed in that scenario, IIUC.
>>>>>>>>> 
>>>>>>>>> In essence we will be asking for the same behavior for types. 
>>>>>>>>> 
>>>>>>>>> Allowing methods declared inside extensions to have a higher declared 
>>>>>>>>> visibility is not a breaking change and can be introduced later. 
>>>>>>>> 
>>>>>>>> It is a breaking change in that I am proposing that the rules be 
>>>>>>>> harmonized so that the implicit default access level will be 
>>>>>>>> notionally `internal` (there are follow-on benefits to this change). 
>>>>>>>> That cannot be changed later.
>>>>>>>>  
>>>>>>>>> Nobody wants private extensions or implicit internal extensions to go 
>>>>>>>>> away. :)
>>>>>>>> 
>>>>>>>> I know that there are people who don't want it to go away. That was 
>>>>>>>> why the first draft proposed keeping them, but it sounds like it would 
>>>>>>>> make for an illogical system. I know that Jordan and John have both 
>>>>>>>> indicated that they don't think it's worth keeping around but don't 
>>>>>>>> seem to feel too strongly about it, and I think I feel the same way 
>>>>>>>> (leaning towards not keeping them, but don't feel very strongly). I 
>>>>>>>> will definitely feature this concern (using extensions as access 
>>>>>>>> modifier groups) prominently in the proposal and hope for a robust 
>>>>>>>> discussion to see how it plays out with the community and core team.
>>>>>>>> 
>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> On Jul 16, 2016, at 4:22 PM, Xiaodi Wu via swift-evolution 
>>>>>>>>> <[email protected]> wrote:
>>>>>>>>> 
>>>>>>>>>>> On Sat, Jul 16, 2016 at 6:10 PM, David Hart <[email protected]> 
>>>>>>>>>>> wrote:
>>>>>>>>>>> This proposal really confuses me. Two comments:
>>>>>>>>>>> 
>>>>>>>>>>> 1) With the proposal, we loose the ability to use access modifiers 
>>>>>>>>>>> on extensions as a way of grouping members by access. That's a huge 
>>>>>>>>>>> loss for me.
>>>>>>>>>> 
>>>>>>>>>> You lose the ability to group public members only. That part is 
>>>>>>>>>> intentional, so that only methods declared with `public func` are 
>>>>>>>>>> public.
>>>>>>>>>>  
>>>>>>>>>>> 2) If we adopt the proposal, I now have no idea what explicit 
>>>>>>>>>>> access modifiers on extensions do.
>>>>>>>>>> 
>>>>>>>>>> I propose keeping explicit access modifiers because previous 
>>>>>>>>>> comments on this list have said that it's useful for grouping 
>>>>>>>>>> members by access. You can continue to use extensions to group 
>>>>>>>>>> fileprivate members of an internal type, or internal members of a 
>>>>>>>>>> public type.
>>>>>>>>>> 
>>>>>>>>>>  
>>>>>>>>>>> More generally, I don't understand this proposal as it's trying to 
>>>>>>>>>>> apply the same access modifier rules on extensions as for types but 
>>>>>>>>>>> extensions are not types. They are just a declaration for extending 
>>>>>>>>>>> types which already have an access level.
>>>>>>>>>>> 
>>>>>>>>>>> On 16 Jul 2016, at 20:04, Xiaodi Wu via swift-evolution 
>>>>>>>>>>> <[email protected]> wrote:
>>>>>>>>>>> 
>>>>>>>>>>>> With the impending withdrawal of SE-0119 and the closing window 
>>>>>>>>>>>> for (most) source-breaking changes, I thought I'd draft up a 
>>>>>>>>>>>> proposal to address some of the key points raised in that 
>>>>>>>>>>>> discussion.
>>>>>>>>>>>> 
>>>>>>>>>>>> The proposed changes are deliberately limited in scope to 
>>>>>>>>>>>> rationalizing access modifier rules without adding any new 
>>>>>>>>>>>> facilities (such as conformances of lower visibility than the 
>>>>>>>>>>>> type), which might be more appropriate for the Swift 4 timeline.
>>>>>>>>>>>> 
>>>>>>>>>>>> I hope this will prove satisfactory to the community :)
>>>>>>>>>>>> 
>>>>>>>>>>>> 
>>>>>>>>>>>> Harmonize access modifiers for extensions
>>>>>>>>>>>> 
>>>>>>>>>>>> Proposal: SE-XXXX
>>>>>>>>>>>> Author: Xiaodi Wu
>>>>>>>>>>>> Status: Awaiting review
>>>>>>>>>>>> Review manager: TBD
>>>>>>>>>>>> Introduction
>>>>>>>>>>>> 
>>>>>>>>>>>> During discussion of SE-0119, the community articulated the view 
>>>>>>>>>>>> that access modifiers for extensions were and should continue to 
>>>>>>>>>>>> be subject to the same rules as access modifiers for types. 
>>>>>>>>>>>> Unfortunately, it is not factually true today; this proposal aims 
>>>>>>>>>>>> to make it so.
>>>>>>>>>>>> 
>>>>>>>>>>>> Swift-evolution threads:
>>>>>>>>>>>> 
>>>>>>>>>>>> [Proposal] Revising access modifiers on extensions
>>>>>>>>>>>> [More to be added here]
>>>>>>>>>>>> Motivation
>>>>>>>>>>>> 
>>>>>>>>>>>> Consider the following:
>>>>>>>>>>>> 
>>>>>>>>>>>> public struct foo {
>>>>>>>>>>>>   func frobnicate() { } // implicitly internal
>>>>>>>>>>>> }
>>>>>>>>>>>> public extension foo { }
>>>>>>>>>>>> 
>>>>>>>>>>>> public struct bar { }
>>>>>>>>>>>> public extension bar {
>>>>>>>>>>>>   func frobnicate() { } // implicitly public, according to SE-0025
>>>>>>>>>>>> }
>>>>>>>>>>>> According to SE-0025, a method moved from the body of a public 
>>>>>>>>>>>> struct into a public extension becomes public without 
>>>>>>>>>>>> modification. This is surprising behavior contrary to Swift's 
>>>>>>>>>>>> general rule of not exposing public API by default.
>>>>>>>>>>>> 
>>>>>>>>>>>> Furthermore, SE-0025 now permits the owner of a type to design 
>>>>>>>>>>>> access for members as though the type will have a higher access 
>>>>>>>>>>>> level than it currently does. For example, users will be able to 
>>>>>>>>>>>> design public methods inside an internaltype before "flipping the 
>>>>>>>>>>>> switch" and making that type public. The same approach is 
>>>>>>>>>>>> prohibited by SE-0025 for extensions, although conceptually it 
>>>>>>>>>>>> need not be.
>>>>>>>>>>>> 
>>>>>>>>>>>> Proposed solution
>>>>>>>>>>>> 
>>>>>>>>>>>> The proposed solution is to change access modifier rules for 
>>>>>>>>>>>> extensions with the following effect: if any method (or computed 
>>>>>>>>>>>> property) declared within the body of a type at file scope is 
>>>>>>>>>>>> moved without modification into the body of an extension in the 
>>>>>>>>>>>> same file, the move will not change its accessibility.
>>>>>>>>>>>> 
>>>>>>>>>>>> In code:
>>>>>>>>>>>> 
>>>>>>>>>>>> struct foo {
>>>>>>>>>>>>   // Any method declared here...
>>>>>>>>>>>> }
>>>>>>>>>>>> extension foo {
>>>>>>>>>>>>   // ...should have the same visibility when moved here.
>>>>>>>>>>>> }
>>>>>>>>>>>> This implies that public API commitments will need to be annotated 
>>>>>>>>>>>> as public at declaration sites inside an extension just as it must 
>>>>>>>>>>>> be at declaration sites inside types.
>>>>>>>>>>>> 
>>>>>>>>>>>> Detailed design
>>>>>>>>>>>> 
>>>>>>>>>>>> Declarations inside the extension will, like declarations inside 
>>>>>>>>>>>> types, have a default access level of internal.
>>>>>>>>>>>> The compiler should not warn when a broader level of access 
>>>>>>>>>>>> control is used for a method (or computed property, etc.) declared 
>>>>>>>>>>>> within an extension with more restrictive access. This allows the 
>>>>>>>>>>>> owner of the extension to design the access level they would use 
>>>>>>>>>>>> for a method if the type or extension were to be made more widely 
>>>>>>>>>>>> accessible.
>>>>>>>>>>>> An extension declared without an explicit access modifier will 
>>>>>>>>>>>> have the same access level as the type being extended.
>>>>>>>>>>>> An extension declared without protocol conformance may optionally 
>>>>>>>>>>>> use an explicit access modifier to provide an upper bound for the 
>>>>>>>>>>>> visibility of its members.
>>>>>>>>>>>> Alternatives considered
>>>>>>>>>>>> 
>>>>>>>>>>>> One alternative, still open for consideration, is to eliminate #4 
>>>>>>>>>>>> and disallow explicit access modifiers on extensions. As an 
>>>>>>>>>>>> advantage, this would clarify the mental model that extensions are 
>>>>>>>>>>>> not their own entities, as they cannot be referred to by name and 
>>>>>>>>>>>> have no runtime representation. As a disadvantage, extensions 
>>>>>>>>>>>> cease to be an access modifier grouping construct, which some 
>>>>>>>>>>>> users really like.
>>>>>>>>>>>> Acknowledgments
>>>>>>>>>>>> 
>>>>>>>>>>>> Thanks to all discussants on the list, especially Adrian Zubarev 
>>>>>>>>>>>> and Jose Cheyo Jimenez.
>>>>>>>>>>>> 
>>>>>>>>>>>> _______________________________________________
>>>>>>>>>>>> swift-evolution mailing list
>>>>>>>>>>>> [email protected]
>>>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>>>> 
>>>>>>>>>> _______________________________________________
>>>>>>>>>> swift-evolution mailing list
>>>>>>>>>> [email protected]
>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>> 
>>>>>>>> _______________________________________________
>>>>>>>> swift-evolution mailing list
>>>>>>>> [email protected]
>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>> 
>>>>>>> _______________________________________________
>>>>>>> swift-evolution mailing list
>>>>>>> [email protected]
>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>> 
>>>>>> 
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> [email protected]
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected]
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to