<html><head><style>
body {
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        padding:1em;
        margin:auto;
        background:#fefefe;
}

h1, h2, h3, h4, h5, h6 {
        font-weight: bold;
}

h1 {
        color: #000000;
        font-size: 28pt;
}

h2 {
        border-bottom: 1px solid #CCCCCC;
        color: #000000;
        font-size: 24px;
}

h3 {
        font-size: 18px;
}

h4 {
        font-size: 16px;
}

h5 {
        font-size: 14px;
}

h6 {
        color: #777777;
        background-color: inherit;
        font-size: 14px;
}

hr {
        height: 0.2em;
        border: 0;
        color: #CCCCCC;
        background-color: #CCCCCC;
    display: inherit;
}

p, blockquote, ul, ol, dl, li, table, pre {
        margin: 15px 0;
}

a, a:visited {
        color: #4183C4;
        background-color: inherit;
        text-decoration: none;
}

#message {
        border-radius: 6px;
        border: 1px solid #ccc;
        display:block;
        width:100%;
        height:60px;
        margin:6px 0px;
}

button, #ws {
        font-size: 12 pt;
        padding: 4px 6px;
        border-radius: 5px;
        border: 1px solid #bbb;
        background-color: #eee;
}

code, pre, #ws, #message {
        font-family: Monaco;
        font-size: 10pt;
        border-radius: 3px;
        background-color: #F8F8F8;
        color: inherit;
}

code {
        border: 1px solid #EAEAEA;
        margin: 0 2px;
        padding: 0 5px;
}

pre {
        border: 1px solid #CCCCCC;
        overflow: auto;
        padding: 4px 8px;
}

pre > code {
        border: 0;
        margin: 0;
        padding: 0;
}

#ws { background-color: #f8f8f8; }


.bloop_markdown table {
border-collapse: collapse;  
font-family: Helvetica, arial, freesans, clean, sans-serif;  
color: rgb(51, 51, 51);  
font-size: 15px; line-height: 25px;
padding: 0; }

.bloop_markdown table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0; }
     
.bloop_markdown table tr:nth-child(2n) {
background-color: #f8f8f8; }

.bloop_markdown table tr th {
font-weight: bold;
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }

.bloop_markdown table tr td {
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }

.bloop_markdown table tr th :first-child, table tr td :first-child {
margin-top: 0; }

.bloop_markdown table tr th :last-child, table tr td :last-child {
margin-bottom: 0; }

.bloop_markdown blockquote{
  border-left: 4px solid #dddddd;
  padding: 0 15px;
  color: #777777; }
  blockquote > :first-child {
    margin-top: 0; }
  blockquote > :last-child {
    margin-bottom: 0; }

code, pre, #ws, #message {
    word-break: normal;
    word-wrap: normal;
}

hr {
    display: inherit;
}

.bloop_markdown :first-child {
    -webkit-margin-before: 0;
}

code, pre, #ws, #message {
    font-family: Menlo, Consolas, Liberation Mono, Courier, monospace;
}


.send { color:#77bb77; }
.server { color:#7799bb; }
.error { color:#AA0000; }</style></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="bloop_markdown"><p>The last explanation is great, now I could follow the idea behind the proposed <code>closed</code> keyword/access modifier. I do now understand the contract on enums, but I’m struggling to understand how <code>closed</code> would work in my own codebase. Assume I had a closed (not the <code>public</code> meaning of your proposal) protocol.</p>

<ul>
<li><p>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>
<li><p>What would an access modifier like <code>closed</code> mean on type members (<code>final public</code>)? If it’s only a type scope access modifier, it leans towards being an attribute instead.</p></li>
<li>If it’s not an access modifier, would <code>closed</code> have some versioning paramerters?

<ul>
<li>Bikeshedding: <code>@closed(1.0.0)</code> (The version, the type was closed)</li>
<li>On current enums: <code>@closed(*)</code> (From the start)</li>
</ul></li>
<li><p>The latter implies in my head that each type needs an explicit version annotation like <code>@available(1.0.0, *)</code>!?</p></li>
<li>How do we handle bug fixes on closed types? Assume all current enums would get an annotation like <code>@closed(*) public</code>. After <a href="https://github.com/dduan/swift-evolution/blob/185b12711bfe1e3b7982d255b538f8dad9ae242c/proposals/NNNN-Normalize-Enum-Case-Representation.md">normalize enum case representation proposal</a> you might also want to clean up the names of your cases. That means you have to perform a breaking API change.

<ul>
<li><p>For example in one of my ‘just for fun’ projects I have two enum cases that look as follows:</p>

<pre><code class="swift">case javaScript(String)
case scopedJavaScript(String, scope: Document)
</code></pre></li>
<li><p>If the mentioned proposal will be accepted I’d like to make these cases shiny.</p>

<pre><code class="swift">// v1:
case javaScript(String)
case javaScript(String, scope: Document)
     
// or v2:
case javaScript(String, scope: Document? = nil)
</code></pre></li>
</ul></li>
</ul>

<p></p></div><div class="bloop_original_html"><style>body{font-family:Helvetica,Arial;font-size:13px}</style><div id="bloop_customfont" style="font-family:Helvetica,Arial;font-size:13px; color: rgba(0,0,0,1.0); margin: 0px; line-height: auto;"><br></div> <br> <div id="bloop_sign_1486656193680076032" class="bloop_sign"><div style="font-family:helvetica,arial;font-size:13px">--&nbsp;<br>Adrian Zubarev<br>Sent with Airmail</div></div> <br><p class="airmail_on">Am 9. Februar 2017 um 16:57:40, Matthew Johnson via swift-evolution (<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>) schrieb:</p> <blockquote type="cite" class="clean_bq"><span><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div></div><div>



<title></title>


<br class="">
<div>
<blockquote type="cite" class="">
<div class="">On Feb 8, 2017, at 5:48 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>&gt;
wrote:</div>
<br class="Apple-interchange-newline">
<div class="">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><br class=""></div>
<div>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. &nbsp;As you note, there are some
differences in how the `closed` contract is supported. &nbsp;But
that is far less important than the meaning of the contract
itself.</div>
<div><br class=""></div>
<div>Dave's comment about tools to assist with contract-compatible
API evolution is the right way to think about this. &nbsp;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. &nbsp;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><br class=""></div>
<div>Most notably, the behavior of public enums *already* has the
API contract of `closed` and we do not want to remove that
capability. &nbsp;This proposal only formalizes how that contract
is specified and makes it consistent across all kinds of types.
&nbsp;It *does not* introduce the idea of a closed semantic
contract for a type.</div>
<br class="">
<blockquote type="cite" class="">
<div class="">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><br class=""></div>
<div>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><br class=""></div>
<div>I understand the reluctance to introduce another keyword.
&nbsp;It isn’t clear to me what semantics you assign to `open` and
`public` enums.</div>
<div><br class=""></div>
<div>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? &nbsp;I am opposed
to this approach because it penalizes the API contract that I think
is often the most appropriate for enums. &nbsp;I strongly prefer
that we adopt the same neutral stance that we when we introduced
`open`. &nbsp;</div>
<div><br class=""></div>
<div>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. &nbsp;This approach has inconsistent semantics for both
`public` and `open`. &nbsp;These keywords would indicate a
different API contract for enums than they do for classes and
protocols. &nbsp;In fact, `open` for enums would have a contract
analagous with `public` for classes and protocols. &nbsp;This feels
like a recipe for confusion. &nbsp;IMO, having consistent semantics
for each keyword is pretty important. &nbsp;We already have, and
desire to continue to have, three distinct semantic contracts.
&nbsp;If we want keywords with consistent semantics we are going to
have to introduce a new keyword for the third meaning.</div>
<div><br class=""></div>
<br class="">
<blockquote type="cite" class="">
<div class="">
<div class="gmail_quote">
<div dir="ltr" class="">On Wed, Feb 8, 2017 at 17:05 Matthew
Johnson via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""></div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word" class="gmail_msg">
<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.&nbsp; I believe we should move further in the direction we
took when introducing the `open` keyword.&nbsp; I have identified
what I think is a promising direction and am interested in feedback
from the community.&nbsp; 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.&nbsp; The decision we reached was to avoid having a default
at all, and instead make `open` an access modifier.&nbsp; The
result is library authors are required to consider the behavior
they wish for each class.&nbsp; 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">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.&nbsp; The current
behavior is that they *do* commit to a fixed set of cases and there
is no option (afaik) to modify that behavior.&nbsp; The Library
Evolution document (<a href="https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums" class="gmail_msg" target="_blank">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.&nbsp; 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.&nbsp; 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.&nbsp; There are
at least two &nbsp;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.&nbsp; 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.&nbsp; Enums
are not a substitute for this use case.&nbsp; 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`.&nbsp; 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.&nbsp; 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. &nbsp;(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.&nbsp; 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.&nbsp; The symbol is visible publicly with the commitment
that future versions of the library are *also* prohibited from
adding new cases, subclasses or conformances.&nbsp; 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.&nbsp; A subclass of a `closed`
class need not be `closed`, in fact it may be `open` if the design
of the library requires that.&nbsp; A class that conforms to a
`closed` protocol also need not be `closed`.&nbsp; It may also be
`open`.&nbsp; Finally, a protocol that refines a `closed` protocol
need not be `closed`.&nbsp; 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.&nbsp; It
does this in a way that offers semantically consistent choices for
API contract across classes, enums and protocols.&nbsp; 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.&nbsp; 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.&nbsp; Both changes allow for a simple mechanical
migration, but that may not be sufficient given the source
compatibility promise made for Swift 4.&nbsp; 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.&nbsp; Brent
suggested `@closed`, but as this proposal distinguishes `public`
and `closed` we would need to identify something else.&nbsp; 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. &nbsp;`public protocol` is not allowed.&nbsp; Users must use
`@annotation public protocol`.</div>
<div class="gmail_msg">* In Swift 6 `public protocol` is allowed
again, now with the new semantics. &nbsp;`@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">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">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg">
</blockquote>
</div>
</div>
</blockquote>
</div>
<br class="">


_______________________________________________<br>swift-evolution mailing list<br>swift-evolution@swift.org<br>https://lists.swift.org/mailman/listinfo/swift-evolution<br></div></div></span></blockquote></div><div class="bloop_markdown"><p></p></div></body></html>