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

Xiaodi Wu xiaodi.wu at gmail.com
Sun Jul 17 10:50:20 CDT 2016


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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160717/83f0eba8/attachment.html>


More information about the swift-evolution mailing list