[swift-evolution] [Draft] Harmonize access modifiers for extensions

Xiaodi Wu xiaodi.wu at gmail.com
Mon Jul 18 10:54:07 CDT 2016


I have incorporated this new feedback and submitted a new PR. When (if?) it
comes up for review, I hope it will prove satisfactory. Thanks all!


On Mon, Jul 18, 2016 at 10:32 AM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:

> On Mon, Jul 18, 2016 at 6:09 AM, Adrian Zubarev via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> +1 :)
>>
>> Let’s analyze this: public > internal > fileprivate >= private
>>
>> 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.
>>
>> public struct A {}
>>
>> // I assume that we go with "must not match" here!
>>
>> // can't be public anymore -> no more
>> // <<implicitly>> public extension members
>> // -> breaking change -> I can live with that
>> extension A {}
>>
>> // no default access modifier -> extension
>> // follows the access rule by the extended type A
>> // -> here every extension member is internal by default
>> // -> can be overridden to public member wise
>> extension A {}
>>
>> // default access modifier acts as the upper bound
>> // inside an extended public type A
>> // -> every extension member are fileprivate
>> // -> extension member can be explicitly set to private
>> // -> these will be only visible inside this extension scope
>> fileprivate extension A {}
>>
>> // at file scope `private` acts like `fileprivate`
>> // (if `private` is allowed at filescope) - haven't read the extended SE-0025 yet
>> // -> I assume any member that are explicitly set to private
>> // will only be visible inside this extension scope
>> private extension A {}
>>
>> Let’s check internal types:
>>
>> internal struct B {}
>>
>> // "must not match" does not work here anymore
>> // do we use "must not exceed" here???
>>
>> // I assume the second.
>>
>> // doens't break anything
>> // works as before
>> // no default access modifier for internal types
>> // equals `internal extension A {}`
>> // members are default internal
>> // -> can be overridden to `fileprivate` or scope level `private`
>> extension B {}
>>
>> // same as for `public extension A`
>> fileprivate extension B {}
>>
>> // same as for `public extension A`
>> private extension B {}
>>
>> // that sounds fine right?
>>
>> // let's check if we'd go with "must not match" instead:
>>
>> // we cannot extend internal types with internal members
>> // anymore -> ups, that would be really strange
>> extension B {}
>>
>>
> Adrian, I propose only that _explicit_ access modifiers on extensions must
> not match the access level of the original type. This proposal does not
> touch what happens inside extensions without explicit access modifiers. I
> had to re-read SE-0025 a few times to fully understand its meaning.
> According to SE-0025, "extensions with explicit access modifiers continue
> to override the default `internal` access." This implies that members
> declared inside an extension without an explicit access modifier will have
> default `internal` access. Likewise, "the compiler will continue to warn on
> overly broad access within an extension with an explicit access modifier."
> This implies that, in the absence of an explicit access modifier, the
> compiler will not warn about overly broad access inside types, just as it
> will not for members inside types.
>
>
>> // same as for `public extension A`
>> fileprivate extension B {}
>>
>> // same as for `public extension A`
>> private extension B {}
>>
>> Just for the record we also check fileprivate and private:
>>
>> fileprivate struct C {}
>>
>> // "must not exceed" assumed
>>
>> // no default access modifier means all
>> // extension member will folow the upper bound by
>> // the extended type -> fileprivate by default
>>
>> (See discussion above.)
>
>>
>> // -> members can be set to be `private` and only
>> // visible inside this extension scope
>> // -> equivalent to `fileprivate extension B {}`
>> // and `private extension C {}`
>> extension C {}
>>
>> // "must not match" -> would break like it breaks the
>> // internal access model
>>
>>
> See above. Nothing breaks.
>
>  ``swift // at file scope acts likefileprivate` private struct D {}
>>
>> // “must not exceed” assumed
>>
>> // same as for fileprivate extension D {}
>>
>> // “must not match” -> would break ```
>>
>> Great compromise here!
>>
>> 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;
>>
>> We still can group internal and fileprivate with this, but it’s okay I
>> guess.
>>
>> Let’s re-check default protocol implementation:
>>
>> public protocol G {
>>     func foo()
>> }
>>
>> // currently we have 3 different ways to make them public
>> // #1
>> extension G {
>>     public func foo() { /* implement */ }
>> }
>>
>> // #2
>> public extension G {
>>     func foo() { /* implement */ }
>> }
>>
>> // #3
>> public extension G {
>>     public func foo() { /* implement */ }
>> }
>>
>> // with "must not match" for `public` only #1 will work
>> // but everyone will need to repeat `public`
>> // no laziness for `public` anymore - hurray
>> extension G {
>>     public func foo() { /* implement */ }
>> }
>>
>> // "must not exceed" doesn't solve the problem of `public` at all
>>
>> The last topic is conformance to protocols:
>>
>> public protocol P {}
>> internal protocol PI {}
>> fileprivate protocol PF {}
>> private protocol PP {}
>>
>> public type Y {}
>>
>> // "must not exceed" results in this, which is what it looks right now
>> extension Y : P {}
>>
>> // just fine here
>> // we still can grant `PI` members visibility up to `public`
>> // the lower bound for these is `internal`
>> extension Y : PI {}
>>
>> // same as `PI` but the lower bound is `fileprivate` now
>> extension Y : PF {}
>>
>> // same as `PI` but the lower bound is `private` now
>> extension Y : PP {}
>>
>> // this does not work atm.
>> // but should be allowed in general where we could grant visibility up to `internal`
>> internal extension Y : PI, PF, PP {}
>>
>> fileprivate extension Y : PF, PP {}
>>
>> There are a few more combinations I don’t want to type out here.
>>
>>
> As I mentioned previously, since explicit access modifiers are not
> currently permitted for conformance to protocols, any such change is
> additive and I do not include it within the scope of this proposal.
>
>
>> My conclusion it this:
>>
>>    -
>>
>>    “must not match” does solve a few problems with public but only
>>    allows explicit internal, fileprivate and private usage, which is
>>    kinda odd. This is a new exceptional rule that must be documented.
>>    -
>>
>>    “must not exceed” does not solve anything if it does not follow the
>>    typical public with default internal rule.
>>    1. With this exception it’s no more a default access modifier and
>>       totally useless on extensions, except if >>no access modifier<< would mean
>>       the upper bound is implicitly internal where you can’t grant
>>       visibility up to public and forced to use public extension if you
>>       wish to achieve this.
>>       2. With the exception in (1) we would need to allow access
>>       modifier on extension with protocol conformance to achieve the same result
>>       everywhere.
>>       3. With all that we’ll have to use #3 for default protocol
>>       implementations to make them public.
>>
>> That said we’re end up with the same upper- lower bound access control
>> model on extension I proposed, even if my proposal title and some of my
>> writing there caused a lot of confusion.
>>
>>
>>
>> --
>> Adrian Zubarev
>> Sent with Airmail
>>
>> Am 18. Juli 2016 um 11:14:09, David Hart (david at hartbit.com) schrieb:
>>
>> 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 <
>> swift-evolution at swift.org> 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 <xiaodi.wu at gmail.com> 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 <
>>> swift-evolution at swift.org> 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 (xiaodi.wu at gmail.com) 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 <
>>>> swift-evolution at swift.org> 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 (xiaodi.wu at gmail.com) 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 <
>>>>> swift-evolution at swift.org> 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 (
>>>>>> swift-evolution at swift.org) schrieb:
>>>>>>
>>>>>> On Sat, Jul 16, 2016 at 7:56 PM, Jose Cheyo Jimenez <
>>>>>> cheyo at masters3d.com> 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 <
>>>>>>> swift-evolution at swift.org> wrote:
>>>>>>>
>>>>>>> On Sat, Jul 16, 2016 at 6:10 PM, David Hart <david at hartbit.com>
>>>>>>> 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 <
>>>>>>>> swift-evolution at swift.org> 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
>>>>>>>>
>>>>>>>>    1. Declarations inside the extension will, like declarations
>>>>>>>>    inside types, have a default access level of internal.
>>>>>>>>    2. 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.
>>>>>>>>    3. An extension declared without an explicit access modifier
>>>>>>>>    will have the same access level as the type being extended.
>>>>>>>>    4. 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
>>>>>>>> swift-evolution at swift.org
>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>>
>>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> swift-evolution mailing list
>>>>>>> swift-evolution at swift.org
>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>
>>>>>>>
>>>>>> _______________________________________________
>>>>>> swift-evolution mailing list
>>>>>> swift-evolution at swift.org
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>
>>>>>>
>>>>>> _______________________________________________
>>>>>> swift-evolution mailing list
>>>>>> swift-evolution at swift.org
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>
>>>>>>
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> swift-evolution at swift.org
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>
>>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160718/bfb44c79/attachment.html>


More information about the swift-evolution mailing list