<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 Jun 15, 2016, at 18:47, Charles Srstka via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><blockquote type="cite" class="">On Jun 15, 2016, at 8:36 PM, Robert Widmann &lt;<a href="mailto:devteam.codafi@gmail.com" class="">devteam.codafi@gmail.com</a>&gt; wrote:<br class=""></blockquote><div class=""><blockquote type="cite" class=""><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Point 3 is *not* how member lookup applies access control levels to unannotated properties of outer structures (see<span class="Apple-converted-space">&nbsp;</span></span><a href="https://github.com/CodaFi/swift/blob/fb9f9536a5760369457d0f9c49599415cbc36e07/lib/Sema/TypeCheckDecl.cpp#L1470" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">https://github.com/CodaFi/swift/blob/fb9f9536a5760369457d0f9c49599415cbc36e07/lib/Sema/TypeCheckDecl.cpp#L1470</a><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">) and makes no sense. &nbsp;They do not default to "internal" when unannotated, they default to the highest possible access level they can get given the decl they're in. &nbsp;A private structure will necessarily have private members. &nbsp;This is the whole point of me raising this issue. &nbsp;If we were to break containment we would break the very motivation for this proposal. &nbsp;And if we wish to do this to get this feature right, then the proposal needs to be amended to include that kind of caveat.</span></div></blockquote></div><br class=""><div class="">This isn’t correct. If the outer type is marked “public”, and its properties are not annotated, those properties will be internal, *not* public, and you will not be able to see them outside of the module.</div><div class=""><br class=""></div><div class="">The rule can basically be summed up as “internal by default, unless we can’t because our enclosing type is more restrictive than internal. Then, be as visible as the enclosing type is.”</div></div></div></blockquote><br class=""></div><div>Robert is correct in the current interpretation: the default access level of a members is the access level of the enclosing type, except that nothing is ever public by default, and so you get ‘internal’ if the type is public. This suggests a rule that the access level of a member is never greater than the access level for a type, and the compiler will warn if you break this rule.</div><div><br class=""></div><div>(Citation: I wrote both the implementation and the&nbsp;<a href="https://github.com/apple/swift/blob/master/docs/AccessControl.rst" class="">original proposal</a>&nbsp;for Swift access control. Please let’s not continue talking about the current (pre-SE-0025)&nbsp;behavior or its intent.)</div><div><br class=""></div><div>—</div><div><br class=""></div><div>As everyone has pointed out, this does not produce desirable behavior in the presence of the new ‘private’.</div><br class=""><div class="">Here is my understanding of the problem:</div><div class=""><br class=""></div><div class=""><b class="">- </b>Blindly applying the current rules, <b class="">the members of a&nbsp;‘private' type default to being&nbsp;‘private'.</b></div><div class=""><b class="">- </b>Blindly applying the current rules, <b class="">the members of a&nbsp;‘private' type </b><i style="font-weight: bold;" class="">cannot be marked as anything but&nbsp;‘private’</i>&nbsp;or the compiler will warn.</div><div class=""><br class=""></div><div class=""><div>(Thank you Robert for explaining the problem to me in person.)</div></div><div><br class=""></div><div>—</div><div><br class=""></div><div>I think Brent has done a great job of summing up the options with regard to ‘private’ on types:</div><div><br class=""></div><div><blockquote type="cite" class="">1. Having an extra, unutterable access modifier that floats relative to the other access levels.<br class=""></blockquote><blockquote type="cite" class=""><br class=""></blockquote><blockquote type="cite" class="">2. Having an extra access modifiers that floats relative to the other access levels, but has a name (like `default`).<br class=""><br class="">3. Having an extra, unutterable access modifier between `fileprivate` and `private`.<br class=""><br class="">4. Using `internal` whenever there's no access modifier, and not warning if the effective scope is smaller.<br class=""><br class="">5. Having an extra access modifier between `fileprivate` and `private`, but which has a name (like `inheritprivate`)&nbsp;<br class=""><br class="">6. Changing the definition of `fileprivate` to be within the surrounding private type if there is one, without changing the keyword.<br class=""><br class="">7. Changing the definition of `fileprivate` to be within the surrounding private type if there is one, and changing the keyword to&nbsp;match.<br class=""></blockquote></div><div class=""><br class=""></div><div class="">(The order is Brent’s preferred order, with higher numbers being more preferred.)</div><div class=""><br class=""></div><div class="">If the discussion on SE-0025 is any indication, it’s that Naming Is Hard and that I really don’t want to come up with a new name at this point. Therefore, my preferred solution is (6), followed by (4). The concrete change to the rules I outlined above would be as follows:</div><div class=""><br class=""></div><div class="">- The default level of members is ‘fileprivate’ for a private or fileprivate type, and ‘internal’ for an internal or public type.</div><div class="">- Any rule where something must be “as visible as the type” (such as minimum access for required initializers) must be ‘fileprivate’ for a private type (rather than private).</div><div class="">- As a consequence, the compiler will warn when the access level of a member is “too high”; that is, where the next level down wouldn’t change anything.</div><div class=""><br class=""></div><div class="">Note that there don’t actually need to be any changes to access rules to make this work; when a type is private, there won’t be any uses of it outside of the enclosing scope, and so nobody elsewhere in the file will be able to call one of those fileprivate members.</div><div class=""><br class=""></div><div class="">—</div><div class=""><br class=""></div><div class="">Ilya hasn’t been active on swift-evolution lately, so if no one has serious objections to (6) <i class="">besides</i>&nbsp;“I don’t like the name” Robert and I will write up an official amendment to SE-0025 and take it to Doug or Chris. If they think this is not a good idea to just move forward with, I’ll ask them whether they’d prefer a partial implementation that disallows ‘private’ on nominal types, or whether they want to kick the whole proposal back for review (and possibly slipping out of Swift 3).</div><div class=""><br class=""></div><div class="">I am not core team, but I do sit near them and have been able to convince them of things. :-) Hopefully we can get this resolved soon. Thanks again to Robert for bringing it up and everyone else for bringing their minds to bear on the problem!</div><div class=""><br class=""></div><div class="">Jordan</div><div class=""><br class=""></div></body></html>