<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><a href="https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AccessControl.html">https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AccessControl.html</a></div><div><br></div><div>Says...</div><div><br></div><div><p class="para" style="border: 0px; margin: 0px 0px 15px; outline: 0px; padding: 0px; vertical-align: baseline; line-height: 24.360000610351563px;"><span style="background-color: rgba(255, 255, 255, 0);">"Alternatively, you can mark an extension with an explicit access-level modifier (for example, <code class="code-voice" style="border: 0px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; word-break: break-all; word-wrap: break-word;">private extension</code>) to set a new default access level for all members defined within the extension. This new default can still be overridden within the extension for individual type members."</span></p><div>And...</div><div><br></div><div><ul class="list-bullet" style="border: 0px; margin: 0px 0px 12px 24px; outline: 0px; padding: 0px; vertical-align: baseline; list-style: none;"><li class="item" style="border: 0px; margin: 0px; outline: 0px; padding: 0px 0px 0px 1.3em; vertical-align: baseline; list-style-type: none; list-style-image: none; position: relative;"><p class="para" style="border: 0px; margin: 0px; outline: 0px; padding: 0px 0px 6px; vertical-align: baseline; line-height: 24.360000610351563px;"><span style="background-color: rgba(255, 255, 255, 0);"><em style="border: 0px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">"Private access</em> restricts the use of an entity to the enclosing declaration, and to extensions of that declaration that are in the same file. Use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration."</span></p><p class="para" style="border: 0px; margin: 0px; outline: 0px; padding: 0px 0px 6px; vertical-align: baseline; line-height: 24.360000610351563px;"><br></p></li></ul></div>So... a private extension where the main entity is in the same file has its members act as "fileprivate", but (we can infer that) a private extension where the main entity is NOT in the same file should have its members act as "private". </div><div><br></div><div>Is that inference in accordance with the intentions of Swift's design?</div><div><br></div><div>If yes, then the compiler should enforce it. If not, then the documentation should be changed.</div><div><br></div><div>Does that summarize the proposal?</div><div><br><div><span style="background-color: rgba(255, 255, 255, 0);">--<br>C. Keith Ray</span><div><span style="background-color: rgba(255, 255, 255, 0);"><br></span></div><div><span style="background-color: rgba(255, 255, 255, 0);">* <a href="https://leanpub.com/wepntk">https://leanpub.com/wepntk</a> <- buy my book?<br>* </span><a href="http://www.thirdfoundationsw.com/keith_ray_resume_2014_long.pdf">http://www.thirdfoundationsw.com/keith_ray_resume_2014_long.pdf</a><span style="background-color: rgba(255, 255, 255, 0);"><br>* <a href="http://agilesolutionspace.blogspot.com/">http://agilesolutionspace.blogspot.com/</a></span></div></div></div><div><br>On Oct 9, 2017, at 10:36 AM, Jose Cheyo Jimenez via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8"><br class=""><div><blockquote type="cite" class=""><div class="">On Oct 9, 2017, at 9:17 AM, Vladimir.S via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">On 07.10.2017 20:17, Nevin Brackett-Rozinsky via swift-evolution wrote:<br class=""><blockquote type="cite" class="">Two weeks ago I had a fairly strong opinion about “private extension” behavior. After following this discussion, I now have no opinion on the matter.<br class="">I would summarize the points on both sides as follows:<br class="">For the change:<br class="">• It is surprising to many people that members of a private extension are implicitly fileprivate. > • There is currently no way to make an extension whose members default to private.<br class=""></blockquote><br class="">I'd add this:<br class="">* Current rule for 'private extension' can lead to bugs, when you expect that private methods will be 'true' private but they are fileprivate, so could be called from not-expected code in the same file. Inverse situation(when you need fileprivate but 'private extension' means 'true' private) - can't cause bugs, you'll be notified by the compiler if you need a 'wider' access level.<br class="">* The change will make the access-control rule for extensions simpler, not harder to understand.<br class="">* 'fileprivate' access level for methods in extension will be used by *intention*, not just because "this is how 'private extension' works". If I understand correctly, it is not the 'fileprivate' *keyword* we want to see less, but the fileprivate *access level*, which should be rare and intentional.<br class=""></div></div></blockquote><div><br class=""></div><div>Top level private *is* private. Swift did not make a distinction between top level private and fileprivate so why should the programmer have to choose?</div><div><br class=""></div><div>If you explicitly declare something private at the top level you are going to get fileprivate semantics. This is how scope private works. If you disagree then that is a different conversation I think. If you wish for these not have an overlap then that is definitely a different proposal?</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class=""><blockquote type="cite" class="">Against the change:<br class="">• The proposal is source-breaking.<br class="">• The proposal makes “fileprivate” more common.<br class=""></blockquote><br class="">It depends on what most of Swift developers *mean* when writing 'private extension' - if they actually need 'fileprivate extension' - then yes, we'll see it more in code. But if in most cases the *intention* is to have a bunch of 'true private' methods - we'll have a small number of 'fileprivate extension'.<br class="">But in any case, what is the problem with this? If developer *needs* fileprivate access level for methods in extension - this will be clearly stated in code, not hidden under the cute title of 'private extension'<br class=""><br class=""><blockquote type="cite" class="">• A private extension and a (top-level) private type both currently have implicitly fileprivate members. The proposal breaks that symmetry.<br class=""></blockquote><br class="">Is it really good symmetry?<br class="">By definition, the rule for applying the access level to type is differ from the rule for extension. Here all symmetry already broken and we have 2 separate rules. And from my point of view, having a symmetry in *this particular* case is a bad thing, it can lead to wrong assumptions. Don't you want to apply the same 'symmetry' rule for the code below ? :<br class=""></div></div></blockquote><div><br class=""></div><div>I would be totally on board with making extensions work the same as types. So instead of enforcing a default ACL, the extension would work the same way as a type by just declaring the upper bound. This would effectively only allow extension to lower the upper bound while still making the default ACL to internal. This would also be a breaking change for public extensions that assume their members to be public. I believe that the behavior of public extension is more harmful and more likely to cause bugs because you are exposing a public API and may not be aware of it. This would remove the ability of open types to be extended with a default ACL of public. The same would happen to public types that are being extended with public modifier.</div><div><br class=""></div><div>The below would be symmetrical but now public extension are essentially the same as just extension without the modifier.</div><div><br class=""></div><div><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 11.9px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgb(246, 248, 250); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; color: rgb(36, 41, 46); font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">open</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">class</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">MyOpenClass</span> {}
<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">public</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">extension</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">MyOpenClass</span> { <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> upper bound public</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">func</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">myFunc</span>(){} <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> default internal, upperbound higher it stays internal. </span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>}
<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">internal</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">extension</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">MyOpenClass</span> { <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> upper bound internal</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">func</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">myFunc2</span>(){} <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> default internal</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>}
<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">fileprivate</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">extension</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">MyOpenClass</span> { <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> upper bound fileprivate</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">func</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">myFunc3</span>(){} <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> default internal but lowered to fileprivate</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>}
<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">private</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">extension</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">MyOpenClass</span> { <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> upper bound toplevel private</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">func</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">myFunc4</span>(){} <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> default internal but lowered to toplevel private</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>}</pre><div class=""><br class=""></div></div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class="">public class C {<br class=""> var i = 10<br class="">}<br class=""><br class="">public extension C {<br class=""> func j(){}<br class="">}<br class=""><br class="">,as you understand 'i' is internal, while 'j()' is public. So this could be a dangerous assumption.<br class=""><br class=""><br class=""><blockquote type="cite" class="">Notable questions:<br class="">• Currently “open” cannot be applied to an extension at all, should we allow it?<br class=""></blockquote><br class="">Probably. But this should be a separate pitch/proposal.<br class=""><br class=""><blockquote type="cite" class="">• Might we ever want to allow nested (non-top level) extensions, and if so how should access levels on them work?<br class=""></blockquote><br class="">Not sure if we need them, this is also a subject for separate pitch/proposal.<br class="">But if the rule for applying the access level for extension will be as currently(I don't believe we'll change it soon) - nested extensions should work the same "the access level keyword stated before the 'extension' keyword will be virtually copy&pasted to the beginning of each method declaration inside extension and then resolved", IMO this is a most clear rule we can have *in case rule for extensions is differ from rule for type”.<br class=""></div></div></blockquote><div><br class=""></div><div> “keyword will be virtually copy&pasted “ sound to me more like extension should take a parameter like ‘extension(private)’ or similar. Explicit declaration of a keyword should take precedence at the location that it was declare. </div><div><br class=""></div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div class=""><br class="">Vladimir.<br class=""><br class=""><blockquote type="cite" class="">Nevin<br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></blockquote>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></div></blockquote></div><br class=""></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></body></html>