<div><br><div class="gmail_quote"><div dir="auto">On Mon, Oct 9, 2017 at 12:36 Jose Cheyo Jimenez via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><blockquote type="cite"><div>On Oct 9, 2017, at 9:17 AM, Vladimir.S via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_4110599934984967752Apple-interchange-newline"><div><div>On 07.10.2017 20:17, Nevin Brackett-Rozinsky via swift-evolution wrote:<br><blockquote type="cite">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>I would summarize the points on both sides as follows:<br>For the change:<br>• It is surprising to many people that members of a private extension are implicitly fileprivate. &gt; • There is currently no way to make an extension whose members default to private.<br></blockquote><br>I&#39;d add this:<br>* Current rule for &#39;private extension&#39; can lead to bugs, when you expect that private methods will be &#39;true&#39; private but they are fileprivate, so could be called from not-expected code in the same file. Inverse situation(when you need fileprivate but &#39;private extension&#39; means &#39;true&#39; private) - can&#39;t cause bugs, you&#39;ll be notified by the compiler if you need a &#39;wider&#39; access level.<br>* The change will make the access-control rule for extensions simpler, not harder to understand.<br>* &#39;fileprivate&#39; access level for methods in extension will be used by *intention*, not just because &quot;this is how &#39;private extension&#39; works&quot;. If I understand correctly, it is not the &#39;fileprivate&#39; *keyword* we want to see less, but the fileprivate *access level*, which should be rare and intentional.<br></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><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></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></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div><br><blockquote type="cite">Against the change:<br>• The proposal is source-breaking.<br>• The proposal makes “fileprivate” more common.<br></blockquote><br>It depends on what most of Swift developers *mean* when writing &#39;private extension&#39; - if they actually need &#39;fileprivate extension&#39; - then yes, we&#39;ll see it more in code. But if in most cases the *intention* is to have a bunch of &#39;true private&#39; methods - we&#39;ll have a small number of &#39;fileprivate extension&#39;.<br>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 &#39;private extension&#39;<br><br><blockquote type="cite">• A private extension and a (top-level) private type both currently have implicitly fileprivate members. The proposal breaks that symmetry.<br></blockquote><br>Is it really good symmetry?<br>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&#39;t you want to apply the same &#39;symmetry&#39; rule for the code below ? :<br></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><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></div></div></div></blockquote><div dir="auto"><br></div><div dir="auto">This idea was discussed previously and rejected. It’s outside of the narrow topic here of the meaning of “private extension” specifically.</div><div dir="auto"><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div><br></div><div>The below would be symmetrical but now public extension are essentially the same as just extension without the modifier.</div><div><br></div><div><pre style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,&#39;Liberation Mono&#39;,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"><span class="m_4110599934984967752pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">open</span> <span class="m_4110599934984967752pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">class</span> <span class="m_4110599934984967752pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">MyOpenClass</span> {}

<span class="m_4110599934984967752pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">public</span> <span class="m_4110599934984967752pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">extension</span> <span class="m_4110599934984967752pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">MyOpenClass</span> { <span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"><span class="m_4110599934984967752pl-c" style="box-sizing:border-box">//</span> upper bound public</span>
<span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"></span>    <span class="m_4110599934984967752pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_4110599934984967752pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">myFunc</span>(){} <span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"><span class="m_4110599934984967752pl-c" style="box-sizing:border-box">//</span> default internal, upperbound higher it stays internal. </span>
<span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"></span>}
<span class="m_4110599934984967752pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">internal</span> <span class="m_4110599934984967752pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">extension</span> <span class="m_4110599934984967752pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">MyOpenClass</span> { <span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"><span class="m_4110599934984967752pl-c" style="box-sizing:border-box">//</span> upper bound internal</span>
<span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"></span>    <span class="m_4110599934984967752pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_4110599934984967752pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">myFunc2</span>(){} <span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"><span class="m_4110599934984967752pl-c" style="box-sizing:border-box">//</span> default internal</span>
<span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"></span>}

<span class="m_4110599934984967752pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">fileprivate</span> <span class="m_4110599934984967752pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">extension</span> <span class="m_4110599934984967752pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">MyOpenClass</span> { <span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"><span class="m_4110599934984967752pl-c" style="box-sizing:border-box">//</span> upper bound fileprivate</span>
<span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"></span>    <span class="m_4110599934984967752pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_4110599934984967752pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">myFunc3</span>(){} <span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"><span class="m_4110599934984967752pl-c" style="box-sizing:border-box">//</span> default internal but lowered to fileprivate</span>
<span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"></span>}

<span class="m_4110599934984967752pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">private</span> <span class="m_4110599934984967752pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">extension</span> <span class="m_4110599934984967752pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">MyOpenClass</span> { <span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"><span class="m_4110599934984967752pl-c" style="box-sizing:border-box">//</span> upper bound toplevel private</span>
<span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"></span>    <span class="m_4110599934984967752pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_4110599934984967752pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">myFunc4</span>(){} <span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"><span class="m_4110599934984967752pl-c" style="box-sizing:border-box">//</span> default internal but lowered to toplevel private</span>
<span class="m_4110599934984967752pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"></span>}</pre><div><br></div></div></div></div><div style="word-wrap:break-word"><div><div><br></div><br><blockquote type="cite"><div><div><br>public class C {<br>    var i = 10<br>}<br><br>public extension C {<br>    func j(){}<br>}<br><br>,as you understand &#39;i&#39; is internal, while &#39;j()&#39; is public. So this could be a dangerous assumption.<br><br><br><blockquote type="cite">Notable questions:<br>• Currently “open” cannot be applied to an extension at all, should we allow it?<br></blockquote><br>Probably. But this should be a separate pitch/proposal.<br><br><blockquote type="cite">• Might we ever want to allow nested (non-top level) extensions, and if so how should access levels on them work?<br></blockquote><br>Not sure if we need them, this is also a subject for separate pitch/proposal.<br>But if the rule for applying the access level for extension will be as currently(I don&#39;t believe we&#39;ll change it soon) - nested extensions should work the same &quot;the access level keyword stated before the &#39;extension&#39; keyword will be virtually copy&amp;pasted to the beginning of each method declaration inside extension and then resolved&quot;, IMO this is a most clear rule we can have *in case rule for extensions is differ from rule for type”.<br></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div> “keyword will be virtually copy&amp;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></div><div style="word-wrap:break-word"><div><div><br></div><div><br></div><blockquote type="cite"><div><div><br>Vladimir.<br><br><blockquote type="cite">Nevin<br>_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></blockquote>_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></div></blockquote></div></div>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</blockquote></div></div>