> > Now if the struct’s visibility is changed, each extension member will be > accessible up to the maximum availability of the type, the extension, and > itself.
…I of course meant “minimum” here. Nevin On Mon, Jul 18, 2016 at 12:25 PM, Nevin Brackett-Rozinsky < [email protected]> wrote: > My understanding is that “being able to change access levels by > simply flipping a switch on the type itself” is a positive goal of Swift. > > Therefore, it emphatically *should* be allowed to set the default > visibility for an extension the same as (or higher than!) the type it > extends. For example, a private type can be given a private extension, so > later making the type internal will preserve the privacy of the extension > members. > > If any change is to be made in this area, it should simply be that “the > default access level of extension members is `internal`”, which means > public members of an extension must be explicitly marked public. > > The access modifier on an extension would serve as an upper bound on > visibility for its members, so the default (implicit) modifier for > extensions would be “public”. Members of a public extension would be > implicitly internal, as noted above. > > The visibility of a type is an upper bound on its members’ visibility as > well, so in a sense we would be making all access modifiers, including > those on member declarations, act as upper bounds. This allows designs like > the following: > > [internal] struct makePublicInTheFuture { ... } > [public] extension makePublicInTheFuture { > private var _p > fileprivate var _f > [internal] var _i > public var x > ... > } > > Now if the struct’s visibility is changed, each extension member will be > accessible up to the maximum availability of the type, the extension, and > itself. > > That seems like the most consistent approach to me. > > However, I am still not convinced that any change is required at all. The > only “problem case” now is `public extension` making its member public by > default. I am not a framework designer, so I do not know how useful or > non-useful this may be. > > But if any change is to be made, I think “extension members default to > internal” is the simplest. > > All access modifier act as upper bounds, extensions are implicitly > `public`, and other declarations (including types) are implicitly > `internal`. > > Then programmers can set access levels to “where they should be” in > preparation for “flipping the switch” on a type or extension’s visibility > in the future, and public APIs must be explicitly marked `public` at the > declaration site. > > How does this sound? > > Nevin > > > > > On Mon, Jul 18, 2016 at 11:32 AM, Xiaodi Wu via swift-evolution < > [email protected]> wrote: > >> On Mon, Jul 18, 2016 at 6:09 AM, Adrian Zubarev via swift-evolution < >> [email protected]> 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 ([email protected]) 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 < >>> [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]> 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 >>>>>>>>> >>>>>>>>> <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 >>>>>>>>> [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 >>> >>> >> >> _______________________________________________ >> 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
