On Mon, Jul 18, 2016 at 1:24 PM, Nevin Brackett-Rozinsky < [email protected]> wrote:
> I remember it differently. The opposition to SE-0119 “Remove access > modifiers from extensions” was primarily because the proposal itself was > malformed and, to quote you from the review thread, “doesn’t do what it > says on the tin (aka in the title)”. > > In that thread Jordan Rose said “the proposal is unclear” and he > personally is against making “access modifiers on extensions set a maximum > level of access for members, like they do for types” because he doesn’t > think “people should think of extensions as first-class entities.” > > However, the core team as a whole never weighed in on the matter, and > Chris Lattner included “Revising access modifiers on extensions” in the > list of “open Swift 3 design topics”. > > If we had a proposal titled “Make all access modifiers act as upper > bounds” which explained that (since the follow-on of SE-0025) they already > behave this way on both types and members, and all that remains is to bring > the same behavior to extensions, I think it would gain substantial traction. > > Notably, this approach does not involve thinking of extensions as > “first-class entities”, but simply as a grouping and extending mechanism. > > The benefits include consistency and simplicity of the model, as well as > ensuring that public APIs must be marked `public` at the declaration site, > while still allowing “private extension” to work as expected. > > If you and I both agree that this is the sensible approach, and it has > never actually been reviewed on its merits, and it addresses an open Swift > 3 design topic, then I think we should push it forward. > > So far the only opposition that has been voiced to this approach was a > claim that it encouraged “thinking of extensions as first-class entities”. > I disagree with that assessment, and I do not think we should let such an > opinion preemptively derail the cogent and straightforward answer. > Sure; with the PR already in the queue, let's bring this up during review (assuming there will be one). I, for one, think it is a cogent argument. > > All that said, I am still not convinced there is anything wrong with the > way things work now. > > Nevin > > > On Mon, Jul 18, 2016 at 12:45 PM, Xiaodi Wu <[email protected]> wrote: > >> On Mon, Jul 18, 2016 at 11:25 AM, 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. >>> >> >> I agree. >> >> 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. >>> >> >> As discussed in SE-0119, there is no such thing as a private extension as >> a first-class entity. The default access modifier is *only* modifying the >> members declared within; therefore, using the "flipping a switch" analogy, >> it is not a switch but rather the default lightbulb; the only relevant >> switch is the access modifier of the original type. >> >> 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. >>> >> >> That requires no change, as it is already slated to be the rule after >> SE-0025. >> >> >>> The access modifier on an extension would serve as an upper bound on >>> visibility for its members, >>> >> >> That approach was my first instinct as well, but it was rejected in >> SE-0119. >> >> >>> 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. >>> >> >> It took me a while to understand what Jordan and John were saying in the >> review process for SE-0119, but I think I now understand. They and others >> reject the upper bound approach because, unlike types, extensions are not >> first-class entities. Therefore, because they do not exist, extensions >> should not be able to set bounds. >> >> >>> 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. >>> >> >> If you look back, that was indeed my first draft of this proposal. >> However, feedback has made it clear that only two options are potentially >> acceptable: access modifiers on extensions can either be eliminated, or >> they can continue to be a shorthand, but they cannot be harmonized to be >> upper bounds. >> >> >>> 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? >>> >> >> It sounded great to me, but it was shot down in SE-0119 and it was >> rejected again on the first draft of this proposal. >> >> >>> >>> 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
