[Accepted] SE-0169: Improve Interaction Between `private` Declarations and Extensions

Proposal Link: swift-evolution/0169-improve-interaction-between-private-declarations-and-extensions.md at master · apple/swift-evolution · GitHub

Hello Swift Community,

The review of SE-0169 "Improve Interaction Between `private` Declarations and Extensions” ran from April 6...11, 2017. The proposal is accepted.

This topic has been highly controversial for a long time, both during Swift 3’s development (when SE-0025 <https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md&gt; was introduced) and during Swift 4 (including SE-0159 <https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md&gt; and other <https://github.com/apple/swift-evolution/pull/680&gt; proposals <https://github.com/apple/swift-evolution/pull/681&gt;\). There is no solution that will make everyone happy: maintaining the status quo makes “fileprivate” too common and therefore not meaningful when it occurs in source; removing or diluting scope-level access control (as in SE-0159 <https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md&gt; and this proposal) takes away a tool that is in use by Swift developers; and adding more levels of access control complicates the language.

The core team feels that this proposal makes private access align more closely with the goals of the language:

It supports the notion that extensions are a code-organization tool: one should be able to break up a type’s definition into several extensions to improve the clarity of that code, without having to open up access or otherwise view the members in different extensions as completely-distinct entities. The core team expects future language evolution to reinforce the notion that extensions are more of a code organization tool than distinct entities, e.g., allowing stored properties to be introduced in an extension.
It makes private more usable as the default sub-internal access level, which supports progressive disclosure of the access control system and better matches with programmer’s expectations about what private access means.
It makes fileprivate more meaningful, because it is only needed for those cases where one is reaching across types (or among types and globals) within a file. It will also become more rare, which matches well with its longer, descriptive name.

The proposal’s acceptance includes one modification: extensions of a given type that reside in a single file that is different from the file that defines the type itself will have access to the private members of all other extensions in that file. For example:

// FileA.swift
struct A {
  private var aMember : Int
}

// FileB.swift
extension A {
    private func foo() {
        bar() // ok, foo() does have access to bar()
    }
}

extension A {
    private func bar() {
        aMember = 42 // not ok, private members may not be accessed outside their file.
    }
}

The proposal has already been updated to reflect this change, which better reflects the notion that extensions are a code-organization tool.

The core team considers the access-control matter closed for Swift 4 and will not be reviewing any further proposals in this area.

  - Doug
  Review Manager

1 Like

Extremely happy to see this outcome. Thank you Core Team for dealing with the seemingly never-ending arguments about access control, hopefully the majority of that is behind us now :^)

···

On Apr 17, 2017, at 5:25 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Proposal Link: https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md

Hello Swift Community,

The review of SE-0169 "Improve Interaction Between `private` Declarations and Extensions” ran from April 6...11, 2017. The proposal is accepted.

This topic has been highly controversial for a long time, both during Swift 3’s development (when SE-0025 was introduced) and during Swift 4 (including SE-0159 and other proposals). There is no solution that will make everyone happy: maintaining the status quo makes “fileprivate” too common and therefore not meaningful when it occurs in source; removing or diluting scope-level access control (as in SE-0159 and this proposal) takes away a tool that is in use by Swift developers; and adding more levels of access control complicates the language.

The core team feels that this proposal makes private access align more closely with the goals of the language:

It supports the notion that extensions are a code-organization tool: one should be able to break up a type’s definition into several extensions to improve the clarity of that code, without having to open up access or otherwise view the members in different extensions as completely-distinct entities. The core team expects future language evolution to reinforce the notion that extensions are more of a code organization tool than distinct entities, e.g., allowing stored properties to be introduced in an extension.
It makes private more usable as the default sub-internal access level, which supports progressive disclosure of the access control system and better matches with programmer’s expectations about what private access means.
It makes fileprivate more meaningful, because it is only needed for those cases where one is reaching across types (or among types and globals) within a file. It will also become more rare, which matches well with its longer, descriptive name.

The proposal’s acceptance includes one modification: extensions of a given type that reside in a single file that is different from the file that defines the type itself will have access to the private members of all other extensions in that file. For example:

// FileA.swift
struct A {
  private var aMember : Int
}

// FileB.swift
extension A {
    private func foo() {
        bar() // ok, foo() does have access to bar()
    }
}

extension A {
    private func bar() {
        aMember = 42 // not ok, private members may not be accessed outside their file.
    }
}

The proposal has already been updated to reflect this change, which better reflects the notion that extensions are a code-organization tool.

The core team considers the access-control matter closed for Swift 4 and will not be reviewing any further proposals in this area.

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

I am glad that “private” will become usable again in Swift 4. This
eliminates most of the pain caused by “fileprivate”.

However, I do not understand why this solution was chosen over renaming the
keywords. The discussion of alternatives here does not mention it, and the
only explanation given after SE-0159 is that renaming would cause “churn”.
Yet that renaming would be completely automatable by a migrator with no
change to semantics, whereas SE-0169 will require developers to manually
investigate each occurrence of “private” to see if the new meaning is still
appropriate, and introduce helper types to hide implementation details
where it is not.

Furthermore, I remain concerned that the mere act and fact of defining
“private” specifically to hide implementation details from other types in
the file will lead developers to put unrelated types together in a single
file, because that appears to be the intended purpose of the keyword.

At a meta-level, since mistakes like SE–0025 will be much more costly in
the source-stable future, we ought to consider adding a step to the Swift
Evolution process whereby accepted proposals are implemented in a beta
version of Swift, and a second review period can happen if new problems
become apparent in actual usage that were unforeseen during the initial
discussion. That way we are much more likely to catch emergent issues
before release.

Nevin

Thanks a lot for closing this topic with this simple and reasonable decision!

Gwendal Roué

···

Le 18 avr. 2017 à 02:25, Douglas Gregor via swift-evolution <swift-evolution@swift.org> a écrit :

Proposal Link: https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md

Hello Swift Community,

The review of SE-0169 "Improve Interaction Between `private` Declarations and Extensions” ran from April 6...11, 2017. The proposal is accepted.
[...]
The core team considers the access-control matter closed for Swift 4 and will not be reviewing any further proposals in this area.

Does the acceptance of SE-0169 imply any change to rules for `private
extension` members, or does the core team intend such members to continue
defaulting to fileprivate visibility?

···

On Mon, Apr 17, 2017 at 19:25 Douglas Gregor via swift-evolution < swift-evolution@swift.org> wrote:

Proposal Link:
https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md

Hello Swift Community,

The review of SE-0169 "Improve Interaction Between `private` Declarations
and Extensions” ran from April 6...11, 2017. The proposal is *accepted*.

This topic has been highly controversial for a long time, both during
Swift 3’s development (when SE-0025
<https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md&gt; was
introduced) and during Swift 4 (including SE-0159
<https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md&gt;
and other <https://github.com/apple/swift-evolution/pull/680&gt; proposals
<https://github.com/apple/swift-evolution/pull/681&gt;\). There is no
solution that will make everyone happy: maintaining the status quo makes
“fileprivate” too common and therefore not meaningful when it occurs in
source; removing or diluting scope-level access control (as in SE-0159
<https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md&gt; and
this proposal) takes away a tool that is in use by Swift developers; and
adding more levels of access control complicates the language.

The core team feels that this proposal makes private access align more
closely with the goals of the language:

   - It supports the notion that extensions are a code-organization tool:
   one should be able to break up a type’s definition into several extensions
   to improve the clarity of that code, without having to open up access or
   otherwise view the members in different extensions as completely-distinct
   entities. The core team expects future language evolution to reinforce the
   notion that extensions are more of a code organization tool than distinct
   entities, e.g., allowing stored properties to be introduced in an extension.
   - It makes private more usable as the default sub-internal access
   level, which supports progressive disclosure of the access control system
   and better matches with programmer’s expectations about what private
   access means.
   - It makes fileprivate more meaningful, because it is only needed for
   those cases where one is reaching across types (or among types and globals)
   within a file. It will also become more rare, which matches well with its
   longer, descriptive name.

The proposal’s acceptance includes one modification: extensions of a given
type that reside in a single file that is different from the file that
defines the type itself will have access to the private members of all
other extensions in that file. For example:

// FileA.swiftstruct A {
  private var aMember : Int
}
// FileB.swiftextension A {
    private func foo() {
        bar() // ok, foo() does have access to bar() }
}
extension A {
    private func bar() {
        aMember = 42 // not ok, private members may not be accessed outside their file. }
}

The proposal has already been updated to reflect this change, which better
reflects the notion that extensions are a code-organization tool.

The core team considers the access-control matter closed for Swift 4 and
will not be reviewing any further proposals in this area.

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

I see the benefit, but I'd have to think about it more before claiming to have an informed opinion.

- Dave Sweeris

···

On Apr 17, 2017, at 18:53, Nevin Brackett-Rozinsky via swift-evolution <swift-evolution@swift.org> wrote:

At a meta-level, since mistakes like SE–0025 will be much more costly in the source-stable future, we ought to consider adding a step to the Swift Evolution process whereby accepted proposals are implemented in a beta version of Swift, and a second review period can happen if new problems become apparent in actual usage that were unforeseen during the initial discussion. That way we are much more likely to catch emergent issues before release.

Does the acceptance of SE-0169 imply any change to rules for `private extension` members, or does the core team intend such members to continue defaulting to fileprivate visibility?

It does imply a change to "private extension" semantics: the members of such an extension would be "private", so they'd be visible to other extensions (and possibly the definition of) the extended type that occur in the same file.

This makes the private/fileprivate distinction meaningful for extensions. I think also bans the use of "private" at global scope for non-nominal types or extensions thereof. A clarifying update to the proposal is in order, so developers can better understand the semantics.

Hey, and this gives me another reason why

  extension P where Self : Q { }

Might be a better spelling than

  extension P & Q { }

Despite the latter being more obvious :)

  - Doug

···

Sent from my iPhone

On Apr 18, 2017, at 6:58 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Mon, Apr 17, 2017 at 19:25 Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:
Proposal Link: https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md

Hello Swift Community,

The review of SE-0169 "Improve Interaction Between `private` Declarations and Extensions” ran from April 6...11, 2017. The proposal is accepted.

This topic has been highly controversial for a long time, both during Swift 3’s development (when SE-0025 was introduced) and during Swift 4 (including SE-0159 and other proposals). There is no solution that will make everyone happy: maintaining the status quo makes “fileprivate” too common and therefore not meaningful when it occurs in source; removing or diluting scope-level access control (as in SE-0159 and this proposal) takes away a tool that is in use by Swift developers; and adding more levels of access control complicates the language.

The core team feels that this proposal makes private access align more closely with the goals of the language:

It supports the notion that extensions are a code-organization tool: one should be able to break up a type’s definition into several extensions to improve the clarity of that code, without having to open up access or otherwise view the members in different extensions as completely-distinct entities. The core team expects future language evolution to reinforce the notion that extensions are more of a code organization tool than distinct entities, e.g., allowing stored properties to be introduced in an extension.
It makes private more usable as the default sub-internal access level, which supports progressive disclosure of the access control system and better matches with programmer’s expectations about what private access means.
It makes fileprivate more meaningful, because it is only needed for those cases where one is reaching across types (or among types and globals) within a file. It will also become more rare, which matches well with its longer, descriptive name.

The proposal’s acceptance includes one modification: extensions of a given type that reside in a single file that is different from the file that defines the type itself will have access to the private members of all other extensions in that file. For example:

// FileA.swift
struct A {
  private var aMember : Int
}

// FileB.swift
extension A {
    private func foo() {
        bar() // ok, foo() does have access to bar()
    }
}

extension A {
    private func bar() {
        aMember = 42 // not ok, private members may not be accessed outside their file.
    }
}

The proposal has already been updated to reflect this change, which better reflects the notion that extensions are a code-organization tool.

The core team considers the access-control matter closed for Swift 4 and will not be reviewing any further proposals in this area.

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

Wait, hang on, then people have to write 'fileprivate' instead of 'private' for top-level typealiases (and functions?). Apart from whether or not that's desirable, it's not backwards-compatible.

Jordan

···

On Apr 18, 2017, at 20:40, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

This makes the private/fileprivate distinction meaningful for extensions. I think also bans the use of "private" at global scope for non-nominal types or extensions thereof. A clarifying update to the proposal is in order, so developers can better understand the semantics.

This makes the private/fileprivate distinction meaningful for extensions. I think also bans the use of "private" at global scope for non-nominal types or extensions thereof. A clarifying update to the proposal is in order, so developers can better understand the semantics.

Wait, hang on, then people have to write 'fileprivate' instead of 'private' for top-level typealiases (and functions?).

That seems like the correct behavior; private is about members with SE-0169. What do you think?

Apart from whether or not that's desirable, it's not backwards-compatible.

Very true! It’s an easy thing to migrate, but it’s a source break nonetheless. Let’s decide if it’s desirable and bring it up with the core team.

  - Doug

···

On Apr 20, 2017, at 11:33 AM, Jordan Rose <jordan_rose@apple.com> wrote:

On Apr 18, 2017, at 20:40, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This makes the private/fileprivate distinction meaningful for extensions.
I think also bans the use of "private" at global scope for non-nominal
types or extensions thereof. A clarifying update to the proposal is in
order, so developers can better understand the semantics.

Wait, hang on, then people have to write 'fileprivate' instead of
'private' for top-level typealiases (and functions?).

That seems like the correct behavior; private is about members with
SE-0169. What do you think?

...that seems suboptimal, given that the goal has been to make it possible
for people to use `private` more and not less frequently. IMO, there's no
need for `private typealias` at the global level to be prohibited.

···

On Thu, Apr 20, 2017 at 5:03 PM, Douglas Gregor <dgregor@apple.com> wrote:

On Apr 20, 2017, at 11:33 AM, Jordan Rose <jordan_rose@apple.com> wrote:
On Apr 18, 2017, at 20:40, Douglas Gregor via swift-evolution < > swift-evolution@swift.org> wrote:

Apart from whether or not that's desirable, it's not backwards-compatible.

Very true! It’s an easy thing to migrate, but it’s a source break
nonetheless. Let’s decide if it’s desirable and bring it up with the core
team.

- Doug

This makes the private/fileprivate distinction meaningful for extensions. I think also bans the use of "private" at global scope for non-nominal types or extensions thereof. A clarifying update to the proposal is in order, so developers can better understand the semantics.

Wait, hang on, then people have to write 'fileprivate' instead of 'private' for top-level typealiases (and functions?).

That seems like the correct behavior; private is about members with SE-0169. What do you think?

...that seems suboptimal, given that the goal has been to make it possible for people to use `private` more and not less frequently. IMO, there's no need for `private typealias` at the global level to be prohibited.

Yeah, I see no reason for this to change the behavior of private extensions to be more restrictive than before.

John.

···

On Apr 20, 2017, at 6:35 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:
On Thu, Apr 20, 2017 at 5:03 PM, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:

On Apr 20, 2017, at 11:33 AM, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:

On Apr 18, 2017, at 20:40, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Apart from whether or not that's desirable, it's not backwards-compatible.

Very true! It’s an easy thing to migrate, but it’s a source break nonetheless. Let’s decide if it’s desirable and bring it up with the core team.

  - Doug

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

So you’re okay with:

  private extension X {
    func foo() { }
  }

being equivalent to

  extension X {
    fileprivate func foo() { }
  }

rather than

  extension X {
    private func foo() { }
  }

?

That seems unintuitive at best.

  - Doug

···

On Apr 20, 2017, at 3:39 PM, John McCall <rjmccall@apple.com> wrote:

On Apr 20, 2017, at 6:35 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
On Thu, Apr 20, 2017 at 5:03 PM, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:

On Apr 20, 2017, at 11:33 AM, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:

On Apr 18, 2017, at 20:40, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This makes the private/fileprivate distinction meaningful for extensions. I think also bans the use of "private" at global scope for non-nominal types or extensions thereof. A clarifying update to the proposal is in order, so developers can better understand the semantics.

Wait, hang on, then people have to write 'fileprivate' instead of 'private' for top-level typealiases (and functions?).

That seems like the correct behavior; private is about members with SE-0169. What do you think?

...that seems suboptimal, given that the goal has been to make it possible for people to use `private` more and not less frequently. IMO, there's no need for `private typealias` at the global level to be prohibited.

Yeah, I see no reason for this to change the behavior of private extensions to be more restrictive than before.

Agree, but the rules for access modifiers in front of extensions have
always been different from those for everything else. Surely, we can
rationalize extensions here as you suggest without having to prohibit
private typealiases.

···

On Thu, Apr 20, 2017 at 6:31 PM, Douglas Gregor <dgregor@apple.com> wrote:

On Apr 20, 2017, at 3:39 PM, John McCall <rjmccall@apple.com> wrote:

On Apr 20, 2017, at 6:35 PM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:
On Thu, Apr 20, 2017 at 5:03 PM, Douglas Gregor <dgregor@apple.com> wrote:

On Apr 20, 2017, at 11:33 AM, Jordan Rose <jordan_rose@apple.com> wrote:

On Apr 18, 2017, at 20:40, Douglas Gregor via swift-evolution < >> swift-evolution@swift.org> wrote:

This makes the private/fileprivate distinction meaningful for extensions.
I think also bans the use of "private" at global scope for non-nominal
types or extensions thereof. A clarifying update to the proposal is in
order, so developers can better understand the semantics.

Wait, hang on, then people have to write 'fileprivate' instead of
'private' for top-level typealiases (and functions?).

That seems like the correct behavior; private is about members with
SE-0169. What do you think?

...that seems suboptimal, given that the goal has been to make it possible
for people to use `private` more and not less frequently. IMO, there's no
need for `private typealias` at the global level to be prohibited.

Yeah, I see no reason for this to change the behavior of private
extensions to be more restrictive than before.

So you’re okay with:

private extension X {
  func foo() { }
}

being equivalent to

extension X {
  fileprivate func foo() { }
}

rather than

extension X {
  private func foo() { }
}

?

That seems unintuitive at best.

Perhaps, but it's existing unintuitive behavior. Are you suggesting that SE-0169 rationalizes changing it because (1) it's likely that a private extension is just meant for the use of other extensions of that type in the current file and (2) SE-0169 already allows such uses and so justifies the stricter rule? That is an interesting theory, but I'm not sure I believe (1). More importantly, though, SE-0169 didn't actually propose changing this behavior, and it's a very substantial shift in behavior, and we haven't actually discussed or gathered any community feedback about it, so I'm really struggling to see why it wouldn't need to be a separate evolution proposal. And that would be difficult because, as a wise man once said to me, the core team considers the access-control matter closed for Swift 4 and will not be reviewing any further proposals in this area. :)

John.

···

On Apr 20, 2017, at 7:31 PM, Douglas Gregor <dgregor@apple.com> wrote:

On Apr 20, 2017, at 3:39 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Apr 20, 2017, at 6:35 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
On Thu, Apr 20, 2017 at 5:03 PM, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:

On Apr 20, 2017, at 11:33 AM, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:

On Apr 18, 2017, at 20:40, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This makes the private/fileprivate distinction meaningful for extensions. I think also bans the use of "private" at global scope for non-nominal types or extensions thereof. A clarifying update to the proposal is in order, so developers can better understand the semantics.

Wait, hang on, then people have to write 'fileprivate' instead of 'private' for top-level typealiases (and functions?).

That seems like the correct behavior; private is about members with SE-0169. What do you think?

...that seems suboptimal, given that the goal has been to make it possible for people to use `private` more and not less frequently. IMO, there's no need for `private typealias` at the global level to be prohibited.

Yeah, I see no reason for this to change the behavior of private extensions to be more restrictive than before.

So you’re okay with:

  private extension X {
    func foo() { }
  }

being equivalent to

  extension X {
    fileprivate func foo() { }
  }

rather than

  extension X {
    private func foo() { }
  }

?

That seems unintuitive at best.

This makes the private/fileprivate distinction meaningful for extensions. I think also bans the use of "private" at global scope for non-nominal types or extensions thereof. A clarifying update to the proposal is in order, so developers can better understand the semantics.

Wait, hang on, then people have to write 'fileprivate' instead of 'private' for top-level typealiases (and functions?).

That seems like the correct behavior; private is about members with SE-0169. What do you think?

...that seems suboptimal, given that the goal has been to make it possible for people to use `private` more and not less frequently. IMO, there's no need for `private typealias` at the global level to be prohibited.

Yeah, I see no reason for this to change the behavior of private extensions to be more restrictive than before.

So you’re okay with:

  private extension X {
    func foo() { }
  }

being equivalent to

  extension X {
    fileprivate func foo() { }
  }

rather than

  extension X {
    private func foo() { }
  }

?

That seems unintuitive at best.

It's more than unintuitive, it goes against the reasons we fought for having a more useful private. I want to use the pattern where I declare an extension as private to set all functions inside it as private to create a "private zone".

···

On 21 Apr 2017, at 01:31, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 20, 2017, at 3:39 PM, John McCall <rjmccall@apple.com> wrote:
On Apr 20, 2017, at 6:35 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Thu, Apr 20, 2017 at 5:03 PM, Douglas Gregor <dgregor@apple.com> wrote:

On Apr 20, 2017, at 11:33 AM, Jordan Rose <jordan_rose@apple.com> wrote:
On Apr 18, 2017, at 20:40, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

  - Doug

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

This makes the private/fileprivate distinction meaningful for extensions. I think also bans the use of "private" at global scope for non-nominal types or extensions thereof. A clarifying update to the proposal is in order, so developers can better understand the semantics.

Wait, hang on, then people have to write 'fileprivate' instead of 'private' for top-level typealiases (and functions?).

That seems like the correct behavior; private is about members with SE-0169. What do you think?

...that seems suboptimal, given that the goal has been to make it possible for people to use `private` more and not less frequently. IMO, there's no need for `private typealias` at the global level to be prohibited.

Yeah, I see no reason for this to change the behavior of private extensions to be more restrictive than before.

So you’re okay with:

  private extension X {
    func foo() { }
  }

being equivalent to

  extension X {
    fileprivate func foo() { }
  }

rather than

  extension X {
    private func foo() { }
  }

?

That seems unintuitive at best.

Perhaps, but it's existing unintuitive behavior. Are you suggesting that SE-0169 rationalizes changing it because (1) it's likely that a private extension is just meant for the use of other extensions of that type in the current file and (2) SE-0169 already allows such uses and so justifies the stricter rule? That is an interesting theory, but I'm not sure I believe (1).

I’m saying (2), and I suspect (1) is most often the case… but I agree that we’re likely to end up breaking code here.

More importantly, though, SE-0169 didn't actually propose changing this behavior, and it's a very substantial shift in behavior, and we haven't actually discussed or gathered any community feedback about it, so I'm really struggling to see why it wouldn't need to be a separate evolution proposal.

I was interpreting SE-0169 to mean this, but you are correct: SE-0169 doesn’t spell out a change here.

And that would be difficult because, as a wise man once said to me, the core team considers the access-control matter closed for Swift 4 and will not be reviewing any further proposals in this area. :)

Never put stock in charlatans or compiler writers.

  - Doug

···

On Apr 20, 2017, at 7:53 PM, John McCall <rjmccall@apple.com> wrote:

On Apr 20, 2017, at 7:31 PM, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:

On Apr 20, 2017, at 3:39 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Apr 20, 2017, at 6:35 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
On Thu, Apr 20, 2017 at 5:03 PM, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:

On Apr 20, 2017, at 11:33 AM, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:

On Apr 18, 2017, at 20:40, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The "Access Control" section of the Swift 3 book says the following:

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.

The behavior of "private extension" in Swift 3 was a deviation from that model, justified because "private" as a default would have meant that nothing in the extension could ever be called. But it was still contrary to the model suggested by the Swift documentation.

Given the highly restrictive behavior of "private" in Swift 3 and the documentation quoted above, it seems unlikely that a developer would intentionally use "private extension" to mean "please make all this stuff visible to the entire file"—it would have worked, but it seems an odd way to write it. If that were the intention, I think "fileprivate extension" would have been more likely.

I think the change to the behavior of "private extension" is in line with the model proposed by SE-0169, in line with the documented behavior of access control on extensions, and in line with user expectations.

-BJ

···

On Apr 21, 2017, at 9:30 AM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 20, 2017, at 7:53 PM, John McCall <rjmccall@apple.com> wrote:

On Apr 20, 2017, at 7:31 PM, Douglas Gregor <dgregor@apple.com> wrote:

On Apr 20, 2017, at 3:39 PM, John McCall <rjmccall@apple.com> wrote:

On Apr 20, 2017, at 6:35 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Thu, Apr 20, 2017 at 5:03 PM, Douglas Gregor <dgregor@apple.com> wrote:

On Apr 20, 2017, at 11:33 AM, Jordan Rose <jordan_rose@apple.com> wrote:

On Apr 18, 2017, at 20:40, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

This makes the private/fileprivate distinction meaningful for extensions. I think also bans the use of "private" at global scope for non-nominal types or extensions thereof. A clarifying update to the proposal is in order, so developers can better understand the semantics.

Wait, hang on, then people have to write 'fileprivate' instead of 'private' for top-level typealiases (and functions?).

That seems like the correct behavior; private is about members with SE-0169. What do you think?

...that seems suboptimal, given that the goal has been to make it possible for people to use `private` more and not less frequently. IMO, there's no need for `private typealias` at the global level to be prohibited.

Yeah, I see no reason for this to change the behavior of private extensions to be more restrictive than before.

So you’re okay with:

  private extension X {
    func foo() { }
  }

being equivalent to

  extension X {
    fileprivate func foo() { }
  }

rather than

  extension X {
    private func foo() { }
  }

?

That seems unintuitive at best.

Perhaps, but it's existing unintuitive behavior. Are you suggesting that SE-0169 rationalizes changing it because (1) it's likely that a private extension is just meant for the use of other extensions of that type in the current file and (2) SE-0169 already allows such uses and so justifies the stricter rule? That is an interesting theory, but I'm not sure I believe (1).

I’m saying (2), and I suspect (1) is most often the case… but I agree that we’re likely to end up breaking code here.

More importantly, though, SE-0169 didn't actually propose changing this behavior, and it's a very substantial shift in behavior, and we haven't actually discussed or gathered any community feedback about it, so I'm really struggling to see why it wouldn't need to be a separate evolution proposal.

I was interpreting SE-0169 to mean this, but you are correct: SE-0169 doesn’t spell out a change here.

And that would be difficult because, as a wise man once said to me, the core team considers the access-control matter closed for Swift 4 and will not be reviewing any further proposals in this area. :)

Never put stock in charlatans or compiler writers.

  - Doug

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

The "Access Control" section of the Swift 3 book says the following:

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.

The behavior of "private extension" in Swift 3 was a deviation from that model, justified because "private" as a default would have meant that nothing in the extension could ever be called. But it was still contrary to the model suggested by the Swift documentation.

Given the highly restrictive behavior of "private" in Swift 3 and the documentation quoted above, it seems unlikely that a developer would intentionally use "private extension" to mean "please make all this stuff visible to the entire file"—it would have worked, but it seems an odd way to write it. If that were the intention, I think "fileprivate extension" would have been more likely.

I think the change to the behavior of "private extension" is in line with the model proposed by SE-0169, in line with the documented behavior of access control on extensions, and in line with user expectations.

-BJ

I understand your point. Another aspect of SE-0169 is that fileprivate should be more rare and thus meaningful when used. The current behavior stays true to the goal of making fileprivate rare.

A top level private scope is effectively fileprivate so it is not totally weird for the extension members to inherit the top level private scope.

When extensions gain the ability to contain properties, we should not allow the access level modifiers to the extensions in the same way protocol extensions prohibit its use.

···

On Apr 21, 2017, at 8:41 PM, BJ Homer via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 21, 2017, at 9:30 AM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 20, 2017, at 7:53 PM, John McCall <rjmccall@apple.com> wrote:

On Apr 20, 2017, at 7:31 PM, Douglas Gregor <dgregor@apple.com> wrote:

On Apr 20, 2017, at 3:39 PM, John McCall <rjmccall@apple.com> wrote:

On Apr 20, 2017, at 6:35 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Thu, Apr 20, 2017 at 5:03 PM, Douglas Gregor <dgregor@apple.com> wrote:

On Apr 20, 2017, at 11:33 AM, Jordan Rose <jordan_rose@apple.com> wrote:

On Apr 18, 2017, at 20:40, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

This makes the private/fileprivate distinction meaningful for extensions. I think also bans the use of "private" at global scope for non-nominal types or extensions thereof. A clarifying update to the proposal is in order, so developers can better understand the semantics.

Wait, hang on, then people have to write 'fileprivate' instead of 'private' for top-level typealiases (and functions?).

That seems like the correct behavior; private is about members with SE-0169. What do you think?

...that seems suboptimal, given that the goal has been to make it possible for people to use `private` more and not less frequently. IMO, there's no need for `private typealias` at the global level to be prohibited.

Yeah, I see no reason for this to change the behavior of private extensions to be more restrictive than before.

So you’re okay with:

  private extension X {
    func foo() { }
  }

being equivalent to

  extension X {
    fileprivate func foo() { }
  }

rather than

  extension X {
    private func foo() { }
  }

?

That seems unintuitive at best.

Perhaps, but it's existing unintuitive behavior. Are you suggesting that SE-0169 rationalizes changing it because (1) it's likely that a private extension is just meant for the use of other extensions of that type in the current file and (2) SE-0169 already allows such uses and so justifies the stricter rule? That is an interesting theory, but I'm not sure I believe (1).

I’m saying (2), and I suspect (1) is most often the case… but I agree that we’re likely to end up breaking code here.

More importantly, though, SE-0169 didn't actually propose changing this behavior, and it's a very substantial shift in behavior, and we haven't actually discussed or gathered any community feedback about it, so I'm really struggling to see why it wouldn't need to be a separate evolution proposal.

I was interpreting SE-0169 to mean this, but you are correct: SE-0169 doesn’t spell out a change here.

And that would be difficult because, as a wise man once said to me, the core team considers the access-control matter closed for Swift 4 and will not be reviewing any further proposals in this area. :)

Never put stock in charlatans or compiler writers.

  - Doug

_______________________________________________
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

The "Access Control" section of the Swift 3 book says the following:

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.

The behavior of "private extension" in Swift 3 was a deviation from that model, justified because "private" as a default would have meant that nothing in the extension could ever be called. But it was still contrary to the model suggested by the Swift documentation.

Given the highly restrictive behavior of "private" in Swift 3 and the documentation quoted above, it seems unlikely that a developer would intentionally use "private extension" to mean "please make all this stuff visible to the entire file"—it would have worked, but it seems an odd way to write it. If that were the intention, I think "fileprivate extension" would have been more likely.

I think the change to the behavior of "private extension" is in line with the model proposed by SE-0169, in line with the documented behavior of access control on extensions, and in line with user expectations.

+1

-Thorsten

···

Am 22.04.2017 um 05:41 schrieb BJ Homer via swift-evolution <swift-evolution@swift.org>:

-BJ

On Apr 21, 2017, at 9:30 AM, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Apr 20, 2017, at 7:53 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Apr 20, 2017, at 7:31 PM, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:

On Apr 20, 2017, at 3:39 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Apr 20, 2017, at 6:35 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
On Thu, Apr 20, 2017 at 5:03 PM, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:

On Apr 20, 2017, at 11:33 AM, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:

On Apr 18, 2017, at 20:40, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This makes the private/fileprivate distinction meaningful for extensions. I think also bans the use of "private" at global scope for non-nominal types or extensions thereof. A clarifying update to the proposal is in order, so developers can better understand the semantics.

Wait, hang on, then people have to write 'fileprivate' instead of 'private' for top-level typealiases (and functions?).

That seems like the correct behavior; private is about members with SE-0169. What do you think?

...that seems suboptimal, given that the goal has been to make it possible for people to use `private` more and not less frequently. IMO, there's no need for `private typealias` at the global level to be prohibited.

Yeah, I see no reason for this to change the behavior of private extensions to be more restrictive than before.

So you’re okay with:

  private extension X {
    func foo() { }
  }

being equivalent to

  extension X {
    fileprivate func foo() { }
  }

rather than

  extension X {
    private func foo() { }
  }

?

That seems unintuitive at best.

Perhaps, but it's existing unintuitive behavior. Are you suggesting that SE-0169 rationalizes changing it because (1) it's likely that a private extension is just meant for the use of other extensions of that type in the current file and (2) SE-0169 already allows such uses and so justifies the stricter rule? That is an interesting theory, but I'm not sure I believe (1).

I’m saying (2), and I suspect (1) is most often the case… but I agree that we’re likely to end up breaking code here.

More importantly, though, SE-0169 didn't actually propose changing this behavior, and it's a very substantial shift in behavior, and we haven't actually discussed or gathered any community feedback about it, so I'm really struggling to see why it wouldn't need to be a separate evolution proposal.

I was interpreting SE-0169 to mean this, but you are correct: SE-0169 doesn’t spell out a change here.

And that would be difficult because, as a wise man once said to me, the core team considers the access-control matter closed for Swift 4 and will not be reviewing any further proposals in this area. :)

Never put stock in charlatans or compiler writers.

  - Doug

_______________________________________________
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

That idea would be my preference too, but it has been already written up as
a proposal, considered, and rejected.

···

On Sat, Apr 22, 2017 at 11:51 AM, Jose Cheyo Jimenez via swift-evolution < swift-evolution@swift.org> wrote:

On Apr 21, 2017, at 8:41 PM, BJ Homer via swift-evolution < > swift-evolution@swift.org> wrote:

The "Access Control" section of the Swift 3 book says the following:

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.

The behavior of "private extension" in Swift 3 was a deviation from that
model, justified because "private" as a default would have meant that
nothing in the extension could ever be called. But it was still contrary to
the model suggested by the Swift documentation.

Given the highly restrictive behavior of "private" in Swift 3 and the
documentation quoted above, it seems unlikely that a developer would
intentionally use "private extension" to mean "please make all this stuff
visible to the entire file"—it would have worked, but it seems an odd way
to write it. If that were the intention, I think "fileprivate extension"
would have been more likely.

I think the change to the behavior of "private extension" is in line with
the model proposed by SE-0169, in line with the documented behavior of
access control on extensions, and in line with user expectations.
-BJ

I understand your point. Another aspect of SE-0169 is that fileprivate
should be more rare and thus meaningful when used. The current behavior
stays true to the goal of making fileprivate rare.

A top level private scope is effectively fileprivate so it is not totally
weird for the extension members to inherit the top level private scope.

When extensions gain the ability to contain properties, we should not
allow the access level modifiers to the extensions in the same way protocol
extensions prohibit its use.