<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><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="">https://lists.swift.org/mailman/listinfo/swift-evolution<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="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></div></blockquote></div><br class=""></body></html>