On Fri, Oct 6, 2017 at 7:07 PM Jose Cheyo Jimenez <ch...@masters3d.com> wrote:
> On Oct 6, 2017, at 11:07 AM, Tony Allevato <tony.allev...@gmail.com> > wrote: > > On Fri, Oct 6, 2017 at 10:16 AM Jose Cheyo Jimenez via swift-evolution < > swift-evolution@swift.org> wrote: > >> On Oct 6, 2017, at 7:10 AM, Vladimir.S <sva...@gmail.com> wrote: >> >> On 05.10.2017 20:52, Jose Cheyo Jimenez via swift-evolution wrote: >> >> On Oct 5, 2017, at 4:32 AM, David Hart <da...@hartbit.com< >> mailto:da...@hartbit.com <da...@hartbit.com>>> wrote: >> >> >> On 5 Oct 2017, at 07:34, Jose Cheyo Jimenez via swift-evolution < >> swift-evolution@swift.org <mailto:swift-evolution@swift.org >> <swift-evolution@swift.org>>> wrote: >> >> I appreciate the enthusiasm but this is not a bug. This was a deliberate >> change in swift 3 to make `private extension` usable. If this was a bug >> then during swift 3 we should have disallowed `private extension` and only >> allowed `fileprivate extension` but that is not what happened. `private >> extension` has worked the same since swift 1. I’ve always used `private >> extension` when I want to add methods to String or other build in types. >> >> >> It’s not a bug, but its unfortunate the behaviour wasn’t changed at the >> same time as SE-0169, and it now is very inconsistent. I also don’t have to >> rehash previous discussions, but if a Core Team member (Chris) is okay with >> going ahead with this, perhaps we should consider it. >> >> This could have not been part of 169 because it would've required to >> lower the visibility of the private extension modifier. >> “No migration will be necessary as this proposal merely broadens the >> visibility of|private|.” >> There was a corner case mentioned when dealing with functions with the >> same name and that was understandable. >> private extension is consistent to the way the private scope rules work. >> The word private is explicit at the top level because extensions can only >> be declared at top level. Top level private is always fileprivate. The >> inconsistency is that we have 1 scope ALC and the rest are not. An explicit >> declaration should always take precedence when declaring something like an >> access level override. >> >> >> FWIW, I can't agree with this. 'private extension' is a real point of >> additional confusion for access levels in Swift. >> Extension *by itself* has no access level, we only can specify the >> *default* (and the top most) access level for inner methods. >> I.e. 'private' access modifier for extension has not the same meaning as >> 'private' func/type/variable at file scope. >> (Yes, I also believe we should disallow 'private' keyword at file level >> and allow it only for extensions, so 'fileprivate' should be used >> explicitly if one needs this. At least warning should be raised. This is >> the *root* of the problem we discuss now. But unfortunately I don't expect >> this could be supported.) >> >> >> Wouldn't that just add a *special* rule to extensions? :) >> >> The latter is 'direct' access level for the func/type/variable and here >> we apply the standard rule for scoped private, so 'private' for file scope >> --> 'fileprivate'. >> >> The former means 'the default(and top most) modifier that will be >> auto-inserted by compiler for all nested methods in extension'. This >> relatively simple rule should not be complicated by additional rule as ", >> but if it is private extension, result access level will be fileprivate, >> you can't have extensions with private methods” >> >> >> Private as it exist in swift now is the scope access control label. The >> compiler does not insert the modifier without having to first compute what >> access control level would be applied to the members of the extension. >> Doing it the other way would be counterintuitive for an scope access label. >> In my code base I disallow top level fileprivate because private top level >> is fileprivate. This is a matter of taste and a linter here would help like >> a mentioned up thread. >> > > This is the sticking point, which is why there are two possible > interpretations of "private extension": > > Choice 1) Attach-then-evaluate. "ACL extension { ... }" is a syntactic > shortcut for "extension { ACL ... }". Under that definition, the ACL is > evaluated as if it were attached to each declaration, so "private > extension" would expand to "private" in front of each decl. > > Choice 2) Evaluate-then-attach. "ACL extension { ... }" is evaluated such > that "ACL" takes on the meaning based on its scope; since it's equivalent > to "fileprivate" there, that is what is attached to each declaration inside > the extension. > > > Yep. This is the issue. Nice summary! > > > The phrasing in the official Swift language guide doesn't specifically > state it, but I think most readers would interpret the following as #1: > > > "Alternatively, you can mark an extension with an explicit access-level > modifier (for example, `private extension`) to set a new default access > level for all members defined within the extension." > > I personally find that choice to be the clearer interpretation of the > rule, because it's based entirely on what words are in the source file and > not about how they interact in special edge cases. > > > Documentation is hard to keep in sync. > > https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md#complications-with-private-types > > > At the time SE-0025 was accepted, "private extension" would have been meaningless if it did not mean "fileprivate" because it predated the SE-0169 behavior extending "private" to extensions in the same file. The very issue being debated here is whether the oversight that SE-0169 did not consider extensions—now that "private extension" *could* have a meaningful use separate from "fileprivate extension"—is something that is worth correcting. If the documentation is out-of-date and needs to be updated to list describe unintuitive special behavior, why not use the opportunity to make the behavior intuitive and consistent instead? > I also think it's hard to rationalize "private extension" working like #2 > because compared to #1, it's both duplicative ("private extension" and > "fileprivate extension" are awkwardly the same) _and_ it is strictly less > flexible (there is _no_ way using that syntax to define an extension whose > members are private, which is an inconsistent hole in the language). > > > This compiles on an Xcode 9 playground. SE-0025 doesn't only affect > extensions. > ``MyClass.myFunc()` looks like (Choice 2) to me. Same as `private > extension MyClass2`. > > > > private class MyClass { > static func myFunc(){ > print(“Acts likes fileprivate") > } > } > > private class MyClass2 { > } > > private extension MyClass2{ > static func myFunc2(){ > print("Same as MyClass.myFunc") > } > } > > > MyClass.myFunc() // Acts likes fileprivate > MyClass2.myFunc2() // Same as MyClass.myFunc > > > This example is somewhat irrelevant to what's being discussed here—it's purely about SE-0025 behavior rather than, as the original message said, the extremely narrow specific case of access control for extensions. > > >> >> And, as was already said, this inconsistency leads to *relaxed* access >> level, which can lead to bugs. If one expects 'private extension' means >> 'fileprivate extension' - compiler will show(with error) that this >> assumption is wrong just after the first attempt to access methods from >> outside of the extended type. >> But if one expects true 'private' access level - the methods from private >> extension could be called from any other code in the same file(by mistake, >> or because code was written a long time ago, or by another developer) and >> this clearly could produce complex bugs. >> >> Also, isn't it a strange code below: >> >> private extension MyType { >> func foo() {} >> private bar() {} >> fileprivate baz() {} // note that "usually" fileprivate is 'wider' >> access level >> } >> >> >> This is also strange too :) >> >> fileprivate class MyType { >> open func foo(){} // Is this open or fileprivate? >> public func bar(){} >> } >> >> open class MyType2 { >> } >> >> open extension MyType2 { // Error: Extensions cannot use 'open' as their >> default access; use 'public' >> func baz(){} >> } >> >> >> >> but it has *currently* a sense - 'foo' is fileprivate, and 'bar' is >> 'true' private. >> Yes, currently we have a warning about 'baz': "warning: declaring a >> fileprivate instance method in a private extension", but then we have a >> question "Why?", as private at top level == fileprivate. and this does not >> produce any warnings: >> fileprivate extension MyType { >> fileprivate func foo() {} >> } >> >> Even more, someone can think "why we need 'private' declaration in >> private extension, probably this is a mistake i.e. unnecessary duplication >> of code, I'll refactor this and delete this explicit 'private' because >> extension is already private' and so will open doors for future problems. >> >> So I do believe we really need to remove that ugly inconsistency and make >> Swift better to write, understand and support the code. >> >> >> This is matter of taste. For example I think fileprivate is ugly and >> having both private and fileprivate makes the code hard to understand. >> >> >> Vladimir. >> >> >> private is different because it is scoped so because of that it is also >> different when dealing with extensions. Top level private is always the >> same as fileprivate thanks to its scoped nature. >> >> Making private the scope ACL was a mistake but that ship has sailed and >> so has this one imo. >> >> >> >> On Oct 4, 2017, at 10:05 PM, Tony Allevato <tony.allev...@gmail.com < >> mailto:tony.allev...@gmail.com <tony.allev...@gmail.com>>> wrote: >> >> Trust me, I'm the last person who wants to rehash access levels in Swift >> again. But that's not what's happening here, IMO, and fixing bugs is not >> just "a change for the sake of changing." >> >> The current behavior of "private extension" is *incorrect*, because it's >> entirely inconsistent with how access levels on extensions are documented >> to behave and it's inconsistent with how other access levels apply to >> extensions. >> >> Can anyone think of a reason—other than "it's too late to change it"—why >> "private extension" and "fileprivate extension" should behave the same, and >> why "X extension { decl }" should be identical to "extension { X decl }" >> for all X *except* "private"? >> >> Yes, it's absolutely unfortunate that this oversight was not addressed >> when the other access level changes were made. But we shouldn't have to >> live with bugs in the language because we're afraid of some unknown amount >> of churn among code that is already written incorrectly. Nor is fixing this >> bug declaring open season on other, unrelated access level debates. Do you >> have data that shows that the amount of code broken because it's using >> "private" when it really should be saying "fileprivate" is high enough that >> we should just leave the bug there? >> >> On Wed, Oct 4, 2017 at 9:51 PM Jose Cheyo Jimenez via swift-evolution < >> swift-evolution@swift.org <mailto:swift-evolution@swift.org >> <swift-evolution@swift.org>>> wrote: >> >> There was a high bar for breaking changes in swift 4 and is even >> higher for swift 5. se-110 was approved and >> implemented on the premises that it was not a big change but it was >> breaking code so it got reverted. Sure the >> migrator was making this easier but the result was a usability >> regression. I think this is a change just for the >> sake of changing. This will cause unnecessary churn. Let’s leave ACLs >> alone for the next few versions of swift >> unless we have a way better system. >> >> >> https://lists.swift.org/pipermail/swift-evolution-announce/2017-June/000386.html >> >> >> >> >> >> On Oct 4, 2017, at 8:47 PM, BJ Homer <bjho...@gmail.com< >> mailto:bjho...@gmail.com <bjho...@gmail.com>>> wrote: >> >> It certainly could break *some* code. But it only breaks code written >> by an author who wrote ‘private >> extension’ knowing that ‘fileprivate extension’ was also an option, >> but still intended it to be shared with the >> whole file. (If that code was from Swift 2, it would have already been >> migrated to ‘fileprivate extension’ by >> the 2->3 migrator.) >> >> So existing code that says ‘private extension’ was written in a Swift >> 3 or 4 era when ‘fileprivate’ was an >> option. If the goal was specifically to share it with the whole file, >> it seems likely that most authors would >> have used ‘fileprivate extension’ instead of ‘private extension’, as >> that better communicates the intention. >> Regardless, though, we could check against the Swift source >> compatibility test suite to see how widespread that is. >> >> Regardless, I think this change makes Swift a better language, and I’m >> in favor of it. >> >> -BJ >> >> On Oct 4, 2017, at 9:10 PM, Jose Cheyo Jimenez via swift-evolution < >> swift-evolution@swift.org >> <mailto:swift-evolution@swift.org <swift-evolution@swift.org>>> wrote: >> >> >> >> On Oct 2, 2017, at 9:59 PM, David Hart via swift-evolution < >> swift-evolution@swift.org >> <mailto:swift-evolution@swift.org <swift-evolution@swift.org>>> wrote: >> >> >> >> On 3 Oct 2017, at 05:12, Xiaodi Wu via swift-evolution < >> swift-evolution@swift.org >> <mailto:swift-evolution@swift.org <swift-evolution@swift.org>>> wrote: >> >> On Mon, Oct 2, 2017 at 9:16 PM, Matthew Johnson via swift-evolution< >> swift-evolution@swift.org >> <mailto:swift-evolution@swift.org <swift-evolution@swift.org>>>wrote: >> >> >> >> Sent from my iPad >> >> On Oct 2, 2017, at 7:33 PM, Jordan Rose via swift-evolution < >> swift-evolution@swift.org >> <mailto:swift-evolution@swift.org <swift-evolution@swift.org>>> >> wrote: >> >> >> >> On Oct 2, 2017, at 03:25, Vladimir.S via swift-evolution < >> swift-evolution@swift.org >> <mailto:swift-evolution@swift.org <swift-evolution@swift.org>>> >> wrote: >> >> On 01.10.2017 1:18, Chris Lattner wrote: >> >> On Sep 29, 2017, at 10:42 AM, Xiaodi Wu via swift-evolution < >> swift-evolution@swift.org >> <mailto:swift-evolution@swift.org <swift-evolution@swift.org>>> >> wrote: >> >> Vladimir, I agree with you on that change, but it’s a separate >> topic from this one. >> >> Tony is absolutely correct that this topic has already been >> discussed. It is a deliberate design >> decision that public types do not automatically expose members >> without explicit access modifiers; >> this has been brought up on this list, and it is clearly not in >> scope for discussion as no new >> insight can arise this late in the game. The inconsistency with >> public extensions was brought up, >> the proposed solution was to remove modifiers for extensions, but >> this proposal was rejected. So, >> the final design is what we have. >> >> Agreed. The core team would only consider a refinement or change >> to access control if there were >> something actively broken that mattered for ABI stability. >> >> >> So we have to live with *protected* extension inconsistency for >> very long time just because core team >> don't want to even discuss _this particular_ inconsistency(when >> access level in *private extension* >> must be private, not fileprivate)? >> >> Yes, we decided that access level for extension will mean a >> default and top most access level for >> nested methods, OK. But even in this rule, which already differ >> from access modifiers for types, we >> have another one special case for 'private extension'. >> >> Don't you think this is not normal situation and actually there >> IMO can't be any reason to keep this >> bug-producing inconsistency in Swift? (especially given Swift 5 >> seems like is a last moment to fix this) >> >> >> I hate to say it but I'm inclined to agree with Vladimir on this. >> "private extension" has a useful >> meaning now distinct from "fileprivate extension", and it was an >> oversight that SE-0169 >> < >> https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md> >> didn't >> include a fix here. On this/very narrow, very specific/access >> control issue I think it would still be >> worth discussing; like Xiaodi said it's not related to James' >> original thread-starter. >> >> >> I agree with this in principle but would not want to see it become >> a slippery slope back into extremely >> long access control discussions. >> >> >> As I've said elsewhere, I too agree with this in principle. I agree >> with Jordan that the current state of >> things is justifiable but the alternative would be somewhat superior, >> agree that in a vacuum this very >> narrow and specific discussion might be warranted, and agree also that >> this could be a very slippery slide >> down a very steep slope. >> >> >> Same here. It’s the only grudge I have left with the current access >> control situation. I remember Doug Gregor >> and John McCall discussing this during the last access control >> proposal. And I wouldn’t mind having a very >> narrow discussion about only this. >> >> I organize my types into extensions for each conformance and for each >> access control. I can currently >> implicitly apply public or fileprivate to all members of an extension >> but I have no way of doing the same for >> private. That’s why I think it should be fixed. >> >> >> This will break a bunch of code because `private extension` >> has_always_meant `fileprivate extension`.Even >> Swift 3 had this same behavior. Lowering the access level of the >> extension members will hide a bunch of code >> that was visible to the file. >> >> 169 was not a breaking change but this “fix” would have made it a >> breaking change. I doubt 169 would had been >> accepted if it was a breaking change. I don’t think it’s worth it. >> >> >> >> https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md >> >> >> >> >> >> (I maintain that the current model does/not/ include a special >> case; it simply means the 'private' is >> resolved at the level of the extension rather than the level of >> its members. But that isn't what people >> expect and it's not as useful.) >> >> >> I agree that changing the behavior of/all/ access modifiers on >> extensions is out of scope. (I also >> agree that it is a bad idea. Sorry, James, but wanting 'pubic' >> here indicates that your mental model of >> extensions does not match what Swift is actually doing, and that >> could get you into trouble.) >> >> Jordan >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org >> <swift-evolution@swift.org>> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org >> <swift-evolution@swift.org>> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org >> <swift-evolution@swift.org>> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org >> <swift-evolution@swift.org>> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org >> <swift-evolution@swift.org>> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org >> <swift-evolution@swift.org>> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org >> <swift-evolution@swift.org>> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution > >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution