On 09.10.2017 20:36, Jose Cheyo Jimenez wrote:
On Oct 9, 2017, at 9:17 AM, Vladimir.S via swift-evolution <swift-evolution@swift.org
<mailto:swift-evolution@swift.org>> wrote:
On 07.10.2017 20:17, Nevin Brackett-Rozinsky via swift-evolution wrote:
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.
I would summarize the points on both sides as follows:
For the change:
• 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.
I'd add this:
* 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.
* The change will make the access-control rule for extensions simpler, not
harder to understand.
* '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.
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?
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?
I'd like to reply with Xiaodi's words(I hope he will not be against this):
>---<
The documentation is correct. To interpret it, you must understand that extensions are not entities and therefore do not
have accessibility of their own; an access modifier in front of “extension” acts only as a shorthand to set the default
and maximum access level of contained members. This aspect of Swift is not up for change, only the question of what the
“private” shorthand means.
>---<
i.e. extension is another "thing" than type. You should not derive any rules/expectation of how access modifiers work
for extension based on rules for type. This could be even(as I showed) dangerous.
Given the *definition* (and the "spirit", as I undertand it) of how access modifiers work for extensions, and how this
rule *differs* from access modifiers for type, plus given the potential bugs produced by current rule for 'private
extension' but no problems if one declared 'true' private extension but needs fileprivate access level, and
over-complicated rules for access modifiers in Swift, and given we can't have a extension of true private members,
especially in the light of new visibility rules for private members in extensions in the same file - all this leads me
to conclusion that we need to make change. I understand that you have another opinion, but for me, it is clear that pros
of the change are much better than status quo and than possible cons of the change.
I.e. I do think current situation is harmful enough to be changed now, and now is the last chance to fix this for
observable future(i.e. after Swift 5).
As for changing the rules for access modifiers for extensions or their syntax, as Xiaodi already mentioned, this is out
of scope for current discussion and most likely will not be discussed ever soon.
Actually, I feel like we start to repeat the opinions/arguments regarding the subject, so probably we need to decide if
we need a formal proposal. Or probably we should collect even more opinions on this? Right now I feel like the most
opinions are positive, or I'm wrong?
Vladimir.
Against the change:
• The proposal is source-breaking.
• The proposal makes “fileprivate” more common.
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'.
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'
• A private extension and a (top-level) private type both currently have implicitly fileprivate members. The proposal
breaks that symmetry.
Is it really good symmetry?
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 ? :
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.
The below would be symmetrical but now public extension are essentially the
same as just extension without the modifier.
open class MyOpenClass {}
public extension MyOpenClass {// upper bound public
func myFunc(){}// default internal, upperbound higher it stays internal.
}
internal extension MyOpenClass {// upper bound internal
func myFunc2(){}// default internal
}
fileprivate extension MyOpenClass {// upper bound fileprivate
func myFunc3(){}// default internal but lowered to fileprivate
}
private extension MyOpenClass {// upper bound toplevel private
func myFunc4(){}// default internal but lowered to toplevel private
}
public class C {
var i = 10
}
public extension C {
func j(){}
}
,as you understand 'i' is internal, while 'j()' is public. So this could be a
dangerous assumption.
Notable questions:
• Currently “open” cannot be applied to an extension at all, should we allow it?
Probably. But this should be a separate pitch/proposal.
• Might we ever want to allow nested (non-top level) extensions, and if so how
should access levels on them work?
Not sure if we need them, this is also a subject for separate pitch/proposal.
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”.
“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.
Vladimir.
Nevin
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution