<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 9, 2017, at 10:33 AM, Adrian Zubarev <<a href="mailto:adrian.zubarev@devandartist.com" class="">adrian.zubarev@devandartist.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="bloop_markdown" style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254);"><p style="margin: 15px 0px; -webkit-margin-before: 0px;" class="">The last explanation is great, now I could follow the idea behind the proposed<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;" class="">closed</code><span class="Apple-converted-space"> </span>keyword/access modifier. I do now understand the contract on enums, but I’m struggling to understand how<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal;" class="">closed</code><span class="Apple-converted-space"> </span>would work in my own codebase. Assume I had a closed (not the<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal;" class="">public</code><span class="Apple-converted-space"> </span>meaning of your proposal) protocol.</p><ul style="margin: 15px 0px;" class=""><li style="margin: 15px 0px; -webkit-margin-before: 0px;" class=""><p style="margin: 15px 0px; -webkit-margin-before: 0px;" class="">Am I allowed to conform to that protocol inside my library? If it’s a version controlled feature, how to prevent further conformance to that protocol in a newer version?</p></li></ul></div></div></blockquote>Yes, you are allowed to have as many conforming types inside the library as you wish, as long as the conformances are introduced alongside the protocol. New conformances may not be added in future versions.</div><div><br class=""></div><div>I don’t know exactly what the enforcement mechanism would look like, but I imagine it would be similar or identical to the mechanism used for `closed` enums. Maybe someone from the core team can elaborate on what this will look like.<br class=""><blockquote type="cite" class=""><div class=""><div class="bloop_markdown" style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254);"><ul style="margin: 15px 0px;" class=""><li style="margin: 15px 0px;" class=""><p style="margin: 15px 0px; -webkit-margin-before: 0px;" class="">What would an access modifier like<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;" class="">closed</code><span class="Apple-converted-space"> </span>mean on type members (<code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal;" class="">final public</code>)? If it’s only a type scope access modifier, it leans towards being an attribute instead.</p></li></ul></div></div></blockquote>I hadn’t considered this yet but it’s a good question. I don’t have time to consider it deeply, but I think the implication for members is that all overrides are public and no new overrides will be added in the future. It isn’t likely to be useful in this case, but I think we could provide a clear definition.<br class=""><blockquote type="cite" class=""><div class=""><div class="bloop_markdown" style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254);"><ul style="margin: 15px 0px;" class=""><li style="margin: 15px 0px;" class="">If it’s not an access modifier, would<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;" class="">closed</code><span class="Apple-converted-space"> </span>have some versioning paramerters?<ul style="margin: 15px 0px;" class=""><li style="margin: 15px 0px; -webkit-margin-before: 0px;" class="">Bikeshedding:<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;" class="">@closed(1.0.0)</code><span class="Apple-converted-space"> </span>(The version, the type was closed)</li><li style="margin: 15px 0px;" class="">On current enums:<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;" class="">@closed(*)</code><span class="Apple-converted-space"> </span>(From the start)</li></ul></li></ul></div></div></blockquote><div>Good question. This is what the Library Evolution document has to say:</div><div><br class=""></div><div><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">@closed</code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""> is a versioned attribute. This is so that clients can deploy against older versions of the library, which may have non-public cases in the enum. (In this case the client must manipulate the enum as if the </span><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);" class="">@closed</code><span style="color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);" class=""> attribute were absent.) All cases that are not versioned become implicitly versioned with this number.</span></div><div><br class=""></div><div>I would prefer to see `closed` be an access modifier so it isn’t penalized with verbosity, particularly for enums. I think the best approach is that `closed` with no version specifier is allowed if it is included in the initial release of a module. `public` enums may be changed to `closed(n.m.x)` in future versions of a module. There is already precedent for parameterized access modifiers: `private(set)`.</div><br class=""><blockquote type="cite" class=""><div class=""><div class="bloop_markdown" style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254);"><ul style="margin: 15px 0px;" class=""><li style="margin: 15px 0px;" class=""><p style="margin: 15px 0px; -webkit-margin-before: 0px;" class="">The latter implies in my head that each type needs an explicit version annotation like<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;" class="">@available(1.0.0, *)</code>!?</p></li></ul></div></div></blockquote>No, I don’t think so.<br class=""><blockquote type="cite" class=""><div class=""><div class="bloop_markdown" style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254);"><ul style="margin: 15px 0px;" class=""><li style="margin: 15px 0px;" class="">How do we handle bug fixes on closed types? Assume all current enums would get an annotation like<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;" class="">@closed(*) public</code>. After<span class="Apple-converted-space"> </span><a href="https://github.com/dduan/swift-evolution/blob/185b12711bfe1e3b7982d255b538f8dad9ae242c/proposals/NNNN-Normalize-Enum-Case-Representation.md" style="color: rgb(65, 131, 196); background-color: inherit; text-decoration: none;" class="">normalize enum case representation proposal</a><span class="Apple-converted-space"> </span>you might also want to clean up the names of your cases. That means you have to perform a breaking API change.</li></ul></div></div></blockquote><div>Both proposals would be part of Swift 4. No module would be able to publish a production-ready version until Swift 4 is released. Also, `closed` wouldn’t have ABI implications until ABI is locked down, which won’t happen until Swift 4 is released (or later). So you would have the chance to clean up case names at the same time as you introduce `closed`.</div><div><br class=""></div><div>It’s also worth pointing out that changing a case name is going to be a breaking change regardless of whether an enum is `closed` or not. It might be possible to minimize the impact of these changes if there was a way to specify the prior, deprecated name for the case, but this issue is orthogonal to `closed`.</div></div><div><blockquote type="cite" class=""><div class=""><div class="bloop_markdown" style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254);"><ul style="margin: 15px 0px;" class=""><li style="margin: 15px 0px;" class=""><ul style="margin: 15px 0px;" class=""><li style="margin: 15px 0px; -webkit-margin-before: 0px;" class=""><p style="margin: 15px 0px; -webkit-margin-before: 0px;" class="">For example in one of my ‘just for fun’ projects I have two enum cases that look as follows:</p><pre style="margin: 15px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;" class=""><code class="swift" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;">case javaScript(String)
case scopedJavaScript(String, scope: Document)
</code></pre></li><li style="margin: 15px 0px;" class=""><p style="margin: 15px 0px; -webkit-margin-before: 0px;" class="">If the mentioned proposal will be accepted I’d like to make these cases shiny.</p><pre style="margin: 15px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;" class=""><code class="swift" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;">// v1:
case javaScript(String)
case javaScript(String, scope: Document)
// or v2:
case javaScript(String, scope: Document? = nil)
</code></pre></li></ul></li></ul><div style="margin: 15px 0px;" class=""><br class="webkit-block-placeholder"></div></div><div class="bloop_original_html" style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254);"><div id="bloop_customfont" style="font-family: Helvetica, Arial; font-size: 13px; margin: 0px;" class=""><br class=""></div><br class=""><div id="bloop_sign_1486656193680076032" class="bloop_sign"><div style="font-family: helvetica, arial; font-size: 13px;" class="">-- <br class="">Adrian Zubarev<br class="">Sent with Airmail</div></div><br class=""><p class="airmail_on" style="margin: 15px 0px;">Am 9. Februar 2017 um 16:57:40, Matthew Johnson via swift-evolution (<a href="mailto:swift-evolution@swift.org" style="color: rgb(65, 131, 196); background-color: inherit; text-decoration: none;" class="">swift-evolution@swift.org</a>) schrieb:</p><blockquote type="cite" class="clean_bq" style="margin: 15px 0px;"><span style="margin-top: 0px; margin-bottom: 0px;" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""></div><div class=""><br class=""><div class=""><blockquote type="cite" class="" style="margin: 15px 0px;"><div class="" style="margin-top: 0px;">On Feb 8, 2017, at 5:48 PM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" class="" style="color: rgb(65, 131, 196); background-color: inherit; text-decoration: none;">xiaodi.wu@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class="" style="margin-bottom: 0px;">I agree very much with rationalizing access levels, but I'm not sure I like this proposal for public vs. closed. How would the compiler stop me from editing my own code if something is closed? The answer must be that it can't, so I can't see it as a co-equal to open but rather simply a statement of intention. Therefore I think use cases for the proposed behavior of closed would be better served by annotations and proper semantic versioning.<br class=""></div></blockquote><div class=""><br class=""></div><div class="">The most important point IMO is that they *are* co-equal in the sense that they define a contract between library authors, library users and the compiler. As you note, there are some differences in how the `closed` contract is supported. But that is far less important than the meaning of the contract itself.</div><div class=""><br class=""></div><div class="">Dave's comment about tools to assist with contract-compatible API evolution is the right way to think about this. Of course you *can* make breaking changes, but we want to make it clear when you *are* making a breaking change, both for source and for ABI compatibility. This will help library authors, but it also helps users as well as the compiler reason about code when we are able to offer stronger guarantees.</div><div class=""><br class=""></div><div class="">Most notably, the behavior of public enums *already* has the API contract of `closed` and we do not want to remove that capability. This proposal only formalizes how that contract is specified and makes it consistent across all kinds of types. It *does not* introduce the idea of a closed semantic contract for a type.</div><br class=""><blockquote type="cite" class="" style="margin: 15px 0px;"><div class="" style="margin-top: 0px; margin-bottom: 0px;">As this change didn't seem in scope for Swift 4 phase 1, I've held off on discussing my own thoughts on access levels. The idea I was going to propose in phase 2 was to have simply open and public enums (and protocols). I really think that completes access levels in a rational way without introducing another keyword.<br class=""></div></blockquote><div class=""><br class=""></div><div class="">The reason I posted now is because formalizing this API contract for enums must happen before ABI is locked down, and also because there is at least one protocol in the standard library (`MirrorPath`) which is documented with the intent that it be `closed`.</div><div class=""><br class=""></div><div class="">I understand the reluctance to introduce another keyword. It isn’t clear to me what semantics you assign to `open` and `public` enums.</div><div class=""><br class=""></div><div class="">Are you suggesting that they match the semantics defined in my proposal and suggesting closed enums (i.e. matching the current behavior of `public` enums) would require an `@closed` annotation as suggested in the Library Evolution document? I am opposed to this approach because it penalizes the API contract that I think is often the most appropriate for enums. I strongly prefer that we adopt the same neutral stance that we when we introduced `open`. </div><div class=""><br class=""></div><div class="">On the other hand, you might be suggesting that `public` enums maintain their current behavior and we simply introduce `open` as a modifier that reserves the right for the *library* to introduce new cases while continuing to prohibit *users* from introducing new cases. This approach has inconsistent semantics for both `public` and `open`. These keywords would indicate a different API contract for enums than they do for classes and protocols. In fact, `open` for enums would have a contract analagous with `public` for classes and protocols. This feels like a recipe for confusion. IMO, having consistent semantics for each keyword is pretty important. We already have, and desire to continue to have, three distinct semantic contracts. If we want keywords with consistent semantics we are going to have to introduce a new keyword for the third meaning.</div><div class=""><br class=""></div><br class=""><blockquote type="cite" class="" style="margin: 15px 0px;"><div class="" style="margin-top: 0px; margin-bottom: 0px;"><div class="gmail_quote"><div dir="ltr" class="">On Wed, Feb 8, 2017 at 17:05 Matthew Johnson via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="" style="color: rgb(65, 131, 196); background-color: inherit; text-decoration: none;">swift-evolution@swift.org</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div class="gmail_msg" style="margin-top: 0px; word-wrap: break-word;"><div class="gmail_msg">I’ve been thinking a lot about our public access modifier story lately in the context of both protocols and enums. I believe we should move further in the direction we took when introducing the `open` keyword. I have identified what I think is a promising direction and am interested in feedback from the community. If community feedback is positive I will flesh this out into a more complete proposal draft.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Background and Motivation:</div><div class="gmail_msg"><br class="gmail_msg"></div>In Swift 3 we had an extended debate regarding whether or not to allow inheritance of public classes by default or to require an annotation for classes that could be subclassed outside the module. The decision we reached was to avoid having a default at all, and instead make `open` an access modifier. The result is library authors are required to consider the behavior they wish for each class. Both behaviors are equally convenient (neither is penalized by requiring an additional boilerplate-y annotation).<div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">A recent thread (<a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html" class="gmail_msg" target="_blank" style="color: rgb(65, 131, 196); background-color: inherit; text-decoration: none;">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html</a>) discussed a similar tradeoff regarding whether public enums should commit to a fixed set of cases by default or not. The current behavior is that they *do* commit to a fixed set of cases and there is no option (afaik) to modify that behavior. The Library Evolution document (<a href="https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums" class="gmail_msg" target="_blank" style="color: rgb(65, 131, 196); background-color: inherit; text-decoration: none;">https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums</a>) suggests a desire to change this before locking down ABI such that public enums *do not* make this commitment by default, and are required to opt-in to this behavior using an `@closed` annotation.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">In the previous discussion I stated a strong preference that closed enums *not* be penalized with an additional annotation. This is because I feel pretty strongly that it is a design smell to: 1) expose cases publicly if consumers of the API are not expected to switch on them and 2) require users to handle unknown future cases if they are likely to switch over the cases in correct use of the API.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">The conclusion I came to in that thread is that we should adopt the same strategy as we did with classes: there should not be a default.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">There have also been several discussions both on the list and via Twitter regarding whether or not we should allow closed protocols. In a recent Twitter discussion Joe Groff suggested that we don’t need them because we should use an enum when there is a fixed set of conforming types. There are at least two reasons why I still think we *should* add support for closed protocols.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">As noted above (and in the previous thread in more detail), if the set of types (cases) isn’t intended to be fixed (i.e. the library may add new types in the future) an enum is likely not a good choice. Using a closed protocol discourages the user from switching and prevents the user from adding conformances that are not desired.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Another use case supported by closed protocols is a design where users are not allowed to conform directly to a protocol, but instead are required to conform to one of several protocols which refine the closed protocol. Enums are not a substitute for this use case. The only option is to resort to documentation and runtime checks.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Proposal:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">This proposal introduces the new access modifier `closed` as well as clarifying the meaning of `public` and expanding the use of `open`. This provides consistent capabilities and semantics across enums, classes and protocols.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">`open` is the most permissive modifier. The symbol is visible outside the module and both users and future versions of the library are allowed to add new cases, subclasses or conformances. (Note: this proposal does not introduce user-extensible `open` enums, but provides the syntax that would be used if they are added to the language)</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">`public` makes the symbol visible without allowing the user to add new cases, subclasses or conformances. The library reserves the right to add new cases, subclasses or conformances in a future version.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">`closed` is the most restrictive modifier. The symbol is visible publicly with the commitment that future versions of the library are *also* prohibited from adding new cases, subclasses or conformances. Additionally, all cases, subclasses or conformances must be visible outside the module.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Note: the `closed` modifier only applies to *direct* subclasses or conformances. A subclass of a `closed` class need not be `closed`, in fact it may be `open` if the design of the library requires that. A class that conforms to a `closed` protocol also need not be `closed`. It may also be `open`. Finally, a protocol that refines a `closed` protocol need not be `closed`. It may also be `open`.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">This proposal is consistent with the principle that libraries should opt-in to all public API contracts without taking a position on what that contract should be. It does this in a way that offers semantically consistent choices for API contract across classes, enums and protocols. The result is that the language allows us to choose the best tool for the job without restricting the designs we might consider because some kinds of types are limited with respect to the `open`, `public` and `closed` semantics a design might require.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Source compatibility:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">This proposal affects both public enums and public protocols. The current behavior of enums is equivalent to a `closed` enum under this proposal and the current behavior of protocols is equivalent to an `open` protocol under this proposal. Both changes allow for a simple mechanical migration, but that may not be sufficient given the source compatibility promise made for Swift 4. We may need to identify a multi-release strategy for adopting this proposal.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Brent Royal-Gordon suggested such a strategy in a discussion regarding closed protocols on Twitter:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">* In Swift 4: all unannotated public protocols receive a warning, possibly with a fix-it to change the annotation to `open`.</div><div class="gmail_msg">* Also in Swift 4: an annotation is introduced to opt-in to the new `public` behavior. Brent suggested `@closed`, but as this proposal distinguishes `public` and `closed` we would need to identify something else. I will use `@annotation` as a placeholder.</div><div class="gmail_msg">* Also In Swift 4: the `closed` modifier is introduced.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">* In Swift 5 the warning becomes a compiler error. `public protocol` is not allowed. Users must use `@annotation public protocol`.</div><div class="gmail_msg">* In Swift 6 `public protocol` is allowed again, now with the new semantics. `@annotation public protocol` is also allowed, now with a warning and a fix-it to remove the warning.</div><div class="gmail_msg">* In Swift 7 `@annotation public protocol` is no longer allowed.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">A similar mult-release strategy would work for migrating public enums.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div></div>_______________________________________________<br class="gmail_msg">swift-evolution mailing list<br class="gmail_msg"><a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank" style="color: rgb(65, 131, 196); background-color: inherit; text-decoration: none;">swift-evolution@swift.org</a><br class="gmail_msg"><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" class="gmail_msg" target="_blank" style="color: rgb(65, 131, 196); background-color: inherit; text-decoration: none;">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg" style="margin-bottom: 0px;"></blockquote></div></div></blockquote></div><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></div></span></blockquote></div><div class="bloop_markdown" style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254);"></div></div></blockquote></div><br class=""></body></html>