<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 23, 2016, at 20:40, John McCall &lt;<a href="mailto:rjmccall@apple.com" class="">rjmccall@apple.com</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=""><div class=""><blockquote type="cite" class=""><div class="">On Jun 23, 2016, at 6:03 PM, Jordan Rose via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><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 class="">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 class=""><br class=""></div><div class="">(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 class=""><br class=""></div><div class="">—</div><div class=""><br class=""></div><div class="">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 class="">(Thank you Robert for explaining the problem to me in person.)</div></div><div class=""><br class=""></div><div class="">—</div></div></div></blockquote><div class=""><br class=""></div>Right. &nbsp;I think the basic problem is that a rule mandating things by lexical nesting cannot interwork successfully with an access level that is also based on lexical nesting.</div><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">I think Brent has done a great job of summing up the options with regard to ‘private’ on types:</div><div class=""><br class=""></div><div class=""><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></div></blockquote><div class=""><br class=""></div>Have you considered just removing this no-greater-access rule? &nbsp;It seems kind of low-value to me, certainly a worthy check for a linter or maybe a warning but an unnecessarily pedantic check to be a hard error. &nbsp;Just let the actual visibility of a member be limited by the visibility of its context; you might think that would regress diagnostics, but QoI here is pretty easy, e.g. "cannot access member of a private extension from a different file" instead of "cannot access private member from a different file". &nbsp;As it is, you can't just drop the visibility of a type without fixing all of its members.</div></div></div></blockquote><br class=""></div><div>It is just a warning already, but I think it’s a useful one: "you marked this thing public but the type isn’t, did you make a mistake?” Even with what little coding I get to do in Swift I’ve hit this, though usually the mistake is “I meant to mark the type public too.”</div><div><br class=""></div><div>Jordan</div><br class=""></body></html>