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
