+1. Makes sense this way. > On Jul 18, 2016, at 9:50 AM, 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] > <mailto:[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] <mailto:[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] > <mailto:[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] <mailto:[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] >> <mailto:[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] <mailto:[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] <mailto:[email protected]>) schrieb: >>> >>>> On Sat, Jul 16, 2016 at 7:56 PM, Jose Cheyo Jimenez <[email protected] >>>> <mailto:[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] <mailto:[email protected]>> wrote: >>>> >>>>> On Sat, Jul 16, 2016 at 6:10 PM, David Hart <[email protected] >>>>> <mailto:[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] <mailto:[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 >>>>>> >>>>>> Declarations inside the extension will, like declarations inside types, >>>>>> have a default access level of internal. >>>>>> The compiler should not warn when a broader level of access control is >>>>>> used for a method (or computed property, etc.) declared within an >>>>>> extension with more restrictive access. This allows the owner of the >>>>>> extension to design the access level they would use for a method if the >>>>>> type or extension were to be made more widely accessible. >>>>>> An extension declared without an explicit access modifier will have the >>>>>> same access level as the type being extended. >>>>>> An extension declared without protocol conformance may optionally use an >>>>>> explicit access modifier to provide an upper bound for the visibility of >>>>>> its members. >>>>>> >>>>>> <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] <mailto:[email protected]> >>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>>> >>>>> _______________________________________________ >>>>> swift-evolution mailing list >>>>> [email protected] <mailto:[email protected]> >>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>> >>>> _______________________________________________ >>>> swift-evolution mailing list >>>> [email protected] <mailto:[email protected]> >>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] <mailto:[email protected]> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>> >>> >> _______________________________________________ >> swift-evolution mailing list >> [email protected] <mailto:[email protected]> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> <https://lists.swift.org/mailman/listinfo/swift-evolution> > _______________________________________________ > swift-evolution mailing list > [email protected] <mailto:[email protected]> > https://lists.swift.org/mailman/listinfo/swift-evolution > <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
