+1. Makes sense this way.

> On Jul 18, 2016, at 9:50 AM, 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 
> <https://github.com/xwu/swift-evolution/blob/harmonize-access-modifiers/proposals/XXXX-harmonize-access-modifiers.md>
> Author: Xiaodi Wu <https://github.com/xwu>
> Status: Awaiting review
> Review manager: TBD
>  
> <https://github.com/xwu/swift-evolution/blob/harmonize-access-modifiers/proposals/XXXX-harmonize-access-modifiers.md#introduction>Introduction
> 
> During discussion of SE-0119 
> <https://github.com/xwu/swift-evolution/blob/harmonize-access-modifiers/proposals/0119-extensions-access-modifiers.md>,
>  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 
> <https://github.com/xwu/swift-evolution/blob/harmonize-access-modifiers/proposals/0117-non-public-subclassable-by-default.md>,
>  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 
> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160620/022144.html>
> [Review] SE-0119: Remove access modifiers from extensions 
> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160711/024224.html>
> [Draft] Harmonize access modifiers for extensions 
> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160711/024522.html>
>  
> <https://github.com/xwu/swift-evolution/blob/harmonize-access-modifiers/proposals/XXXX-harmonize-access-modifiers.md#motivation>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 
> <https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AccessControl.html>,
>  which is slated for preservation in Swift 3 as detailed in SE-0025 
> <https://github.com/xwu/swift-evolution/blob/harmonize-access-modifiers/proposals/0025-scoped-access-level.md>.
>  However, it is arguably surprising that, of two declarations spelled 
> identically, one leads to a public API commitment while the other does not.
> 
>  
> <https://github.com/xwu/swift-evolution/blob/harmonize-access-modifiers/proposals/XXXX-harmonize-access-modifiers.md#proposed-solution>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.
> 
>  
> <https://github.com/xwu/swift-evolution/blob/harmonize-access-modifiers/proposals/XXXX-harmonize-access-modifiers.md#detailed-design>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.
> 
>  
> <https://github.com/xwu/swift-evolution/blob/harmonize-access-modifiers/proposals/XXXX-harmonize-access-modifiers.md#alternatives-considered>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.
> 
>  
> <https://github.com/xwu/swift-evolution/blob/harmonize-access-modifiers/proposals/XXXX-harmonize-access-modifiers.md#acknowledgments>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] 
> <mailto:[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] <mailto:[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] 
> <mailto:[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] <mailto:[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] 
>> <mailto:[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] <mailto:[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] <mailto:[email protected]>) schrieb:
>>> 
>>>> On Sat, Jul 16, 2016 at 7:56 PM, Jose Cheyo Jimenez <[email protected] 
>>>> <mailto:[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] <mailto:[email protected]>> wrote:
>>>> 
>>>>> On Sat, Jul 16, 2016 at 6:10 PM, David Hart <[email protected] 
>>>>> <mailto:[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] <mailto:[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 
>>>>>> <https://github.com/xwu/swift-evolution/blob/harmonize-access-modifiers/proposals/XXXX-harmonize-access-modifiers.md>
>>>>>> Author: Xiaodi Wu <https://github.com/xwu>
>>>>>> Status: Awaiting review
>>>>>> Review manager: TBD
>>>>>>  
>>>>>> <https://github.com/xwu/swift-evolution/tree/harmonize-access-modifiers#introduction>Introduction
>>>>>> 
>>>>>> During discussion of SE-0119 
>>>>>> <https://github.com/xwu/swift-evolution/blob/harmonize-access-modifiers/proposals/0119-extensions-access-modifiers>,
>>>>>>  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 
>>>>>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160620/022144.html>
>>>>>> [More to be added here]
>>>>>>  
>>>>>> <https://github.com/xwu/swift-evolution/tree/harmonize-access-modifiers#motivation>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.
>>>>>> 
>>>>>>  
>>>>>> <https://github.com/xwu/swift-evolution/tree/harmonize-access-modifiers#proposed-solution>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.
>>>>>> 
>>>>>>  
>>>>>> <https://github.com/xwu/swift-evolution/tree/harmonize-access-modifiers#detailed-design>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.
>>>>>>  
>>>>>> <https://github.com/xwu/swift-evolution/tree/harmonize-access-modifiers#alternatives-considered>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.
>>>>>>  
>>>>>> <https://github.com/xwu/swift-evolution/tree/harmonize-access-modifiers#acknowledgments>Acknowledgments
>>>>>> 
>>>>>> Thanks to all discussants on the list, especially Adrian Zubarev and 
>>>>>> Jose Cheyo Jimenez.
>>>>>> 
>>>>>> _______________________________________________
>>>>>> swift-evolution mailing list
>>>>>> [email protected] <mailto:[email protected]>
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>> 
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> [email protected] <mailto:[email protected]>
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>> 
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> [email protected] <mailto:[email protected]>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>> 
>>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> _______________________________________________
> swift-evolution mailing list
> [email protected] <mailto:[email protected]>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <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