Idea: Public Access Modifier Respected in Type Definition

Sent from my iPad

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 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.

···

On 3 Oct 2017, at 05:12, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Mon, Oct 2, 2017 at 9:16 PM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

On Oct 2, 2017, at 7:33 PM, Jordan Rose via swift-evolution <swift-evolution@swift.org> wrote:

On Oct 2, 2017, at 03:25, Vladimir.S via swift-evolution <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> wrote:

(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
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

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?

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.

···

On Oct 9, 2017, at 9:17 AM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:
On 07.10.2017 20:17, Nevin Brackett-Rozinsky via swift-evolution wrote:

Vladimir.

Nevin
_______________________________________________
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

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AccessControl.html

Says...

"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. This new default can still be overridden within the extension for individual type members."

And...

"Private access restricts the use of an entity to the enclosing declaration, and to extensions of that declaration that are in the same file. Use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration."

So... a private extension where the main entity is in the same file has its members act as "fileprivate", but (we can infer that) a private extension where the main entity is NOT in the same file should have its members act as "private".

Is that inference in accordance with the intentions of Swift's design?

If yes, then the compiler should enforce it. If not, then the documentation should be changed.

Does that summarize the proposal?

···

--
C. Keith Ray

* https://leanpub.com/wepntk <- buy my book?
* http://www.thirdfoundationsw.com/keith_ray_resume_2014_long.pdf
* http://agilesolutionspace.blogspot.com/

On Oct 9, 2017, at 10:36 AM, Jose Cheyo Jimenez via swift-evolution <swift-evolution@swift.org> wrote:

On Oct 9, 2017, at 9:17 AM, Vladimir.S via swift-evolution <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?

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
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

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?

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.

This idea was discussed previously and rejected. It’s outside of the narrow
topic here of the meaning of “private extension” specifically.

···

On Mon, Oct 9, 2017 at 12:36 Jose Cheyo Jimenez via swift-evolution < swift-evolution@swift.org> wrote:

On Oct 9, 2017, at 9:17 AM, Vladimir.S via swift-evolution < > swift-evolution@swift.org> wrote:
On 07.10.2017 20:17, Nevin Brackett-Rozinsky via swift-evolution wrote:

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
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

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AccessControl.html

Says...

"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. This new default can
still be overridden within the extension for individual type members."
And...

   -

   *"Private access* restricts the use of an entity to the enclosing
   declaration, and to extensions of that declaration that are in the same
   file. Use private access to hide the implementation details of a specific
   piece of functionality when those details are used only within a single
   declaration."

So... a private extension where the main entity is in the same file has
its members act as "fileprivate", but (we can infer that) a private
extension where the main entity is NOT in the same file should have its
members act as "private".

No, its members are fileprivate to the file in which the extension resides.

Is that inference in accordance with the intentions of Swift's design?

If yes, then the compiler should enforce it. If not, then the
documentation should be changed.

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.

Does that summarize the proposal?

···

On Mon, Oct 9, 2017 at 13:51 C. Keith Ray via swift-evolution < swift-evolution@swift.org> wrote:

--
C. Keith Ray

* https://leanpub.com/wepntk <- buy my book?
* http://www.thirdfoundationsw.com/keith_ray_resume_2014_long.pdf
* http://agilesolutionspace.blogspot.com/

On Oct 9, 2017, at 10:36 AM, Jose Cheyo Jimenez via swift-evolution < > swift-evolution@swift.org> wrote:

On Oct 9, 2017, at 9:17 AM, Vladimir.S via swift-evolution < > 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?

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
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

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.

···

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:

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

I don’t think I’ve ever used “private extension”, but if I did, I’d expect it to not mean “fileprivate extension”.

- Dave Sweeris

···

On Oct 2, 2017, at 6:52 PM, Tony Allevato via swift-evolution <swift-evolution@swift.org> wrote:

Thanks for hoisting this out into its own thread, Jordan. I was hesitant to elaborate more on another access level thread :slight_smile:

I think the change should absolutely be made. Even though the "private" keyword occurs at the file level, the description of the feature in the Swift documentation simply states: "you can mark an extension with an explicit access-level modifier to set a new default access level for all members defined within the extension." To me, that implies that "private extension Foo { func bar() }" should be identical to "extension Foo { private func bar() }", but today it becomes equivalent to "extension Foo { fileprivate func bar() }".

That seems fundamentally broken, because (1) it's inconsistent, (2) "private extension" and "fileprivate extension" are two ways of saying the same thing, non-intuitively, and (3) there's no way for someone to use the shorthand syntax to take advantage of the new meaning of private within same-file type extensions.

While I personally never use the shorthand extension access level feature (because I prefer the explicit form, and because of situations like this one), I definitely think it should be consistent for people who do want to use it.

I wonder how much existing code would be affected by this change. Do people use "private extension" when they really want "fileprivate extension"? I would hope the number of users affected would be few, at least.

Sent from my iPad

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 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

···

On Oct 2, 2017, at 9:59 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

On 3 Oct 2017, at 05:12, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Mon, Oct 2, 2017 at 9:16 PM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

On Oct 2, 2017, at 7:33 PM, Jordan Rose via swift-evolution <swift-evolution@swift.org> wrote:

On Oct 2, 2017, at 03:25, Vladimir.S via swift-evolution <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> wrote:

(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
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

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.

If the main motivation for changing the rules for `private extension` is because it can lead to bugs, then you can not just dismiss the elephant in the room that is `public extension`. Accidentally leaking a public interface is more damaging than accidentally using an implementation detail. SE-0119 was about completely removing extension modifiers.

I am all for fixing the inconsistencies but I do not believe that `private extension` is inconsistent.

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?

Go for it. I am completely against it but lets see what the community has to say.

···

On Oct 10, 2017, at 8:24 AM, Vladimir.S <svabox@gmail.com> wrote:
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:

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

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> wrote:

On Oct 2, 2017, at 9:59 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

On 3 Oct 2017, at 05:12, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Mon, Oct 2, 2017 at 9:16 PM, Matthew Johnson via swift-evolution <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> wrote:

On Oct 2, 2017, at 03:25, Vladimir.S via swift-evolution <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> 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 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
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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Just as one small data point, I had no idea private extensions still applied fileprivate access to all members (I thought that had changed when SE-0169 was implemented). I’ve been using private extensions extensively because I thought they *did* apply private access to everything, not fileprivate.

Now knowing this isn’t the case, I can only imagine how many other people would be tripped up be this (especially people who haven’t followed Swift Evolution). I definitely think this inconsistency needs to be fixed.

···

On Oct 4, 2017, at 8:48 PM, BJ Homer via swift-evolution <swift-evolution@swift.org> 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> wrote:

On Oct 2, 2017, at 9:59 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

On 3 Oct 2017, at 05:12, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Mon, Oct 2, 2017 at 9:16 PM, Matthew Johnson via swift-evolution <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> wrote:

On Oct 2, 2017, at 03:25, Vladimir.S via swift-evolution <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> 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 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
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

_______________________________________________
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

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 <bjhomer@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> wrote:

On Oct 2, 2017, at 9:59 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

On 3 Oct 2017, at 05:12, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Mon, Oct 2, 2017 at 9:16 PM, Matthew Johnson via swift-evolution <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> wrote:

On Oct 2, 2017, at 03:25, Vladimir.S via swift-evolution <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> 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 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
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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

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> 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 <bjhomer@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> wrote:

On Oct 2, 2017, at 9:59 PM, David Hart via swift-evolution < > swift-evolution@swift.org> wrote:

On 3 Oct 2017, at 05:12, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

On Mon, Oct 2, 2017 at 9:16 PM, Matthew Johnson via swift-evolution < > 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> wrote:

On Oct 2, 2017, at 03:25, Vladimir.S via swift-evolution < >> 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> 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
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

_______________________________________________
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

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.

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.allevato@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> 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 <bjhomer@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> wrote:

On Oct 2, 2017, at 9:59 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

On 3 Oct 2017, at 05:12, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Mon, Oct 2, 2017 at 9:16 PM, Matthew Johnson via swift-evolution <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> wrote:

On Oct 2, 2017, at 03:25, Vladimir.S via swift-evolution <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> 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 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
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

_______________________________________________
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

Yes, you're right about the history of "private extension"—I was forgetting
some of the details of what transpired during those proposals. Thanks for
the reminder.

That being said, I would still argue that it would be a shame if we decided
that the language should propagate a known inconsistency indefinitely
simply because it was overlooked during a proposal that could have fixed
it. I'd weigh the reduction of future user confusion as more valuable than
the cost for existing code to do a one-time migration, but that might be
easy for me to say because I don't use access levels on extensions at all
in my own code so I don't have any skin in the game. :slight_smile:

···

On Wed, Oct 4, 2017 at 10:33 PM Jose Cheyo Jimenez <cheyo@masters3d.com> 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.

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.allevato@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> 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 <bjhomer@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> wrote:

On Oct 2, 2017, at 9:59 PM, David Hart via swift-evolution < >> swift-evolution@swift.org> wrote:

On 3 Oct 2017, at 05:12, Xiaodi Wu via swift-evolution < >> swift-evolution@swift.org> wrote:

On Mon, Oct 2, 2017 at 9:16 PM, Matthew Johnson via swift-evolution < >> 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> wrote:

On Oct 2, 2017, at 03:25, Vladimir.S via swift-evolution < >>> 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> 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
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

_______________________________________________
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

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.

···

On 5 Oct 2017, at 07:34, Jose Cheyo Jimenez via swift-evolution <swift-evolution@swift.org> wrote:

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.allevato@gmail.com <mailto:tony.allevato@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>> 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 <bjhomer@gmail.com <mailto:bjhomer@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>> wrote:

On Oct 2, 2017, at 9:59 PM, David Hart via swift-evolution <swift-evolution@swift.org <mailto: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>> wrote:

On Mon, Oct 2, 2017 at 9:16 PM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto: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>> wrote:

On Oct 2, 2017, at 03:25, Vladimir.S via swift-evolution <swift-evolution@swift.org <mailto: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>> 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>
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 <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 <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

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.

···

On Oct 5, 2017, at 4:32 AM, David Hart <david@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>> wrote:

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.allevato@gmail.com <mailto:tony.allevato@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>> 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 <bjhomer@gmail.com <mailto:bjhomer@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>> wrote:

On Oct 2, 2017, at 9:59 PM, David Hart via swift-evolution <swift-evolution@swift.org <mailto: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>> wrote:

On Mon, Oct 2, 2017 at 9:16 PM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto: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>> wrote:

On Oct 2, 2017, at 03:25, Vladimir.S via swift-evolution <swift-evolution@swift.org <mailto: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>> 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>
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 <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 <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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

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.)
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"

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
}

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.

Vladimir.

···

On 05.10.2017 20:52, Jose Cheyo Jimenez via swift-evolution wrote:

On Oct 5, 2017, at 4:32 AM, David Hart <david@hartbit.com <mailto:david@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>> wrote:

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.allevato@gmail.com <mailto:tony.allevato@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>> 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 <bjhomer@gmail.com <mailto:bjhomer@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>> wrote:

    On Oct 2, 2017, at 9:59 PM, David Hart via swift-evolution <swift-evolution@swift.org >>>>>> <mailto: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>> wrote:

    On Mon, Oct 2, 2017 at 9:16 PM, Matthew Johnson via swift-evolution<swift-evolution@swift.org >>>>>>>> <mailto: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>> wrote:

        On Oct 2, 2017, at 03:25, Vladimir.S via swift-evolution <swift-evolution@swift.org >>>>>>>>>> <mailto: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>> 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>
        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 <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 <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 <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

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? :slight_smile:

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.

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 :slight_smile:

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.

···

On Oct 6, 2017, at 7:10 AM, Vladimir.S <svabox@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 <david@hartbit.com <mailto:david@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>> wrote:

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.allevato@gmail.com <mailto:tony.allevato@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>> 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 <bjhomer@gmail.com <mailto:bjhomer@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>> wrote:

   On Oct 2, 2017, at 9:59 PM, David Hart via swift-evolution <swift-evolution@swift.org >>>>>>> <mailto: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>> wrote:

   On Mon, Oct 2, 2017 at 9:16 PM, Matthew Johnson via swift-evolution<swift-evolution@swift.org >>>>>>>>> <mailto: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>> wrote:

       On Oct 2, 2017, at 03:25, Vladimir.S via swift-evolution <swift-evolution@swift.org >>>>>>>>>>> <mailto: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>> 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>
       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 <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 <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 <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

These exceed the confines of the narrow discussion we are trying to have
here about private extensions. We are not going to rehash the ugliness of
fileprivate.

···

On Fri, Oct 6, 2017 at 12:16 Jose Cheyo Jimenez via swift-evolution < swift-evolution@swift.org> wrote:

On Oct 6, 2017, at 7:10 AM, Vladimir.S <svabox@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 <david@hartbit.com < > mailto:david@hartbit.com <david@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? :slight_smile:

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.

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 :slight_smile:

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.allevato@gmail.com < > mailto:tony.allevato@gmail.com <tony.allevato@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 <bjhomer@gmail.com < > mailto:bjhomer@gmail.com <bjhomer@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