Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-09 Thread Jordan Rose via swift-evolution
I'm not sure how this solves the problem. We need to know whether an enum may 
grow new cases or not, a concept that doesn't exist in Swift today. This is 
most interesting for enums in "libraries with binary compatibility concerns", 
but is also interesting for libraries that don't have such concerns, like 
source packages. Source packages don't use availability annotations.

We definitely need to be able to mark when enum cases were introduced, but the 
language already supports that, at least for libraries that are shipped with an 
Apple OS.

As for the name, I agree that 'exhaustive' isn't great. The best suggestion we 
got from the initial review was 'frozen', and that's what I'm putting in the 
next revision of the proposal.

Jordan

P.S. I'm not sure where you got "versioned" from. The attribute currently 
spelled '_versioned' in the Swift compiler is equivalent to what SE-0193 

 calls 'abiPublic', at least in this revision. (I'm sorry to say I haven't 
caught up on all the discussion there, so I don't know if that's going to be 
spelled some other way.)



> On Jan 9, 2018, at 08:52, Jon Gilbert  wrote:
> 
> Having reviewed much of the commentary on this proposal, I keep coming back 
> to the same thought: why not use @versioned and @available keywords for this 
> instead of some concept related to “exhaustive”?
> 
> The issue here is not whether a given enum is “exhaustive” over the 
> enumerated problem space; it’s whether the developer wants to alter the enum 
> in the future without breaking ABI compatibility.
> 
> If you call it “exhaustive” then it’s misleading, because all enums at a 
> given moment in time can be switched over exhaustively. This will just 
> confuse folks.
> 
> Since versioning is really the main goal, why not use the same annotations 
> for versioning enums as are used for versioning everything else?
> 
> @versioned
> enum MyError: Error {
> @available(OSX, deprecated:10.11, message: "this error case is going away in 
> 10.12")
> case BadThingHappened
> 
> @available(forever)
> case ReallyBadThingHappened
> }
> 
> etc.
> 
> That way you could have some cases get removed in the future as well as 
> added, and you won’t confuse people by talking about “complete” or 
> “exhaustive”, which are terms that are too closely coupled with the meaning 
> and application of a given enum to which they refer. 
> 
> It would be best to use terms that just say what they mean. We are talking 
> about versioning APIs to keep ABI stability? Use @versioned and @available 
> like everywhere else. 
> 
> Or is there a compelling reason this cannot be done? I read much of the 
> arguments here but didn’t see any mention of @versioned... maybe it’s iOS 
> Mail app thinking I was looking for an email address that contains 
> @versioned? ;D
> 
> Jonathan

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-09 Thread Jon Gilbert via swift-evolution
Having reviewed much of the commentary on this proposal, I keep coming back to 
the same thought: why not use @versioned and @available keywords for this 
instead of some concept related to “exhaustive”?

The issue here is not whether a given enum is “exhaustive” over the enumerated 
problem space; it’s whether the developer wants to alter the enum in the future 
without breaking ABI compatibility.

If you call it “exhaustive” then it’s misleading, because all enums at a given 
moment in time can be switched over exhaustively. This will just confuse folks.

Since versioning is really the main goal, why not use the same annotations for 
versioning enums as are used for versioning everything else?

@versioned
enum MyError: Error {
@available(OSX, deprecated:10.11, message: "this error case is going away in 
10.12")
case BadThingHappened

@available(forever)
case ReallyBadThingHappened
}

etc.

That way you could have some cases get removed in the future as well as added, 
and you won’t confuse people by talking about “complete” or “exhaustive”, which 
are terms that are too closely coupled with the meaning and application of a 
given enum to which they refer. 

It would be best to use terms that just say what they mean. We are talking 
about versioning APIs to keep ABI stability? Use @versioned and @available like 
everywhere else. 

Or is there a compelling reason this cannot be done? I read much of the 
arguments here but didn’t see any mention of @versioned... maybe it’s iOS Mail 
app thinking I was looking for an email address that contains @versioned? ;D

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-08 Thread Jordan Rose via swift-evolution
It's true that Apple framework authors have this capability, known as a 
"linked-on-or-after check", but it has several caveats:

- It can only check what SDK the application was linked against. Any prebuilt 
libraries that the application uses might have been built against an older or 
newer SDK. (Yes, Apple discourages linking against libraries you didn't build 
yourself; at the same time we all know people do it.)

- The check is "what SDK was the application linked against". That means that a 
developer is opting into all new behavior when they update to a new SDK, 
instead of just one API's.

- The whole system still has to work together, so it's not always possible to 
preserve the old behavior.

- This means that it's not true that "every library actually keeps old 
implementations around". What happens is that individual frameworks may choose 
to do a "linked-on-or-after" check for a particular feature, and modify their 
behavior based on that. They may also choose not to, which might make sense 
for, e.g., a new UIView animation kind, or a new property list serialization 
kind.

I haven't looked at all, but I suspect the vast majority of changes between 
Apple OS releases, including new cases added to enums, are not guarded by 
linked-on-or-after checks. (I probably can't look, or at least can't tell you, 
because anything not release-noted might be left that way for a reason.) You 
may have been thinking of, say, the .NET approach to compatibility 
,
 where Microsoft actually does ship several copies of the standard library and 
runtimes when they make major breaking changes, but even then they don't do 
this for every single OS update.


I think Jon's original point has been answered by now: this is an issue in 
Objective-C, but not one that leads to undefined behavior, because in effect 
the compiler treats all C enums as "non-exhaustive" except in warnings. (You 
can imagine a `default: break;` inserted at the end of any switch that doesn't 
otherwise have one in C.)

Jordan


> On Jan 8, 2018, at 11:02, Saagar Jha via swift-evolution 
>  wrote:
> 
> (Disclaimer: I’m no expert in this, and I know there are people in this list 
> that are, so if there’s anything wrong please feel free to step in and 
> correct me)
> 
> As far as I’m aware, Apple’s frameworks check which version of the framework 
> you linked with at runtime (for UIKit, I believe this function is 
> UIApplicationLinkedOnOrAfter) and modify their behavior to match. For 
> example, if this function shows your application was linked with the iOS 6 
> SDK you’d get the old skeuomorphic UI instead of the “flatter”, newer iOS 
> 7-style controls. What this means is every library actually keeps old 
> implementations around in addition to the newer ones and picks the necessary 
> one at runtime, so binary compatibility boils down to things like “don't 
> change the memory layout of classes” rather than “don’t change the behavior 
> of your program”.
> 
> Saagar Jha
> 
>> On Jan 5, 2018, at 19:11, Jon Shier via swift-evolution 
>> > wrote:
>> 
>> At this point I think it might be useful to outline how binary compatibility 
>> works for Objective-C on Apple platforms right now. As an app developer I’m 
>> not intimately familiar with what happens when you run an app compiled with 
>> the iOS 10 SDK on iOS 11. Are there just runtime checks to call old code 
>> paths or something else? The more this thread goes on the more confused I 
>> get about why Swift would have this issue while it doesn’t appear to be one 
>> for Obj-C. If an enum adds a case now, I don’t have to care until I 
>> recompile using the new SDK. Is the intention for Swift to be different in 
>> this regard?
>> 
>> 
>> 
>> Jon Shier
>> 
>> On Jan 5, 2018, at 6:41 PM, Jordan Rose via swift-evolution 
>> > wrote:
>> 
>>> 
>>> 
 On Jan 3, 2018, at 00:54, Jason Merchant via swift-evolution 
 > wrote:
 
 Is it hard to imagine that most everyone can get what they want and keep 
 the syntax clean and streamlined at the same time? Without any "@" signs 
 or other compiler hints?
>>> 
>>> For what it's worth, the original version of the proposal started with a 
>>> modifier (a context-sensitive keyword, like 'final'), but the core team 
>>> felt that there were a lot of modifiers in the language already, and this 
>>> didn't meet the bar.
>>> 
>>> 
 "Rather, we are how to enable the vendor of a nonexhaustive enum to add 
 new cases without breaking binaries compiled against previous versions"
 
 When an enum changes, and the change causes the code to break, the user 
 can be presented with migration options from an automated IDE tool. In 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-08 Thread Goffredo Marocchi via swift-evolution
Add -Weverything and you can ensure you are switching exhaustively ;).

Sent from my iPhone

> On 8 Jan 2018, at 19:02, Javier Soto via swift-evolution 
>  wrote:
> 
> This is very much an issue in Obj-C today. If you have an NS_ENUM defined 
> with cases A, B, and C, this switch is correct:
> 
> int foo;
> swith (e) { 
> case A: foo = 0; break;
> case B: foo = 1; break;
> case C: foo = 2; break;
> }
> 
> (Note the lack of a default case)
> 
> If that enum is defined in a framework and it changes after the app is 
> compiled (like it's the case with Apple frameworks), then that code produces 
> no warning, yet the foo variable will have a garbage value (undefined 
> behavior, but as far as the compiler can tell at compile time your code is 
> fine)
> 
> Adding a default clause to that switch has the downside of not getting 
> warnings for new added cases, like has been discussed before, which is very 
> useful.
>> On Fri, Jan 5, 2018 at 7:11 PM Jon Shier via swift-evolution 
>>  wrote:
>> At this point I think it might be useful to outline how binary compatibility 
>> works for Objective-C on Apple platforms right now. As an app developer I’m 
>> not intimately familiar with what happens when you run an app compiled with 
>> the iOS 10 SDK on iOS 11. Are there just runtime checks to call old code 
>> paths or something else? The more this thread goes on the more confused I 
>> get about why Swift would have this issue while it doesn’t appear to be one 
>> for Obj-C. If an enum adds a case now, I don’t have to care until I 
>> recompile using the new SDK. Is the intention for Swift to be different in 
>> this regard?
>> 
>> 
>> 
>> Jon Shier
>> 
>>> On Jan 5, 2018, at 6:41 PM, Jordan Rose via swift-evolution 
>>>  wrote:
>>> 
>>> 
>>> 
 On Jan 3, 2018, at 00:54, Jason Merchant via swift-evolution 
  wrote:
 
 Is it hard to imagine that most everyone can get what they want and keep 
 the syntax clean and streamlined at the same time? Without any "@" signs 
 or other compiler hints?
>>> 
>>> For what it's worth, the original version of the proposal started with a 
>>> modifier (a context-sensitive keyword, like 'final'), but the core team 
>>> felt that there were a lot of modifiers in the language already, and this 
>>> didn't meet the bar.
>>> 
>>> 
> "Rather, we are how to enable the vendor of a nonexhaustive enum to add 
> new cases without breaking binaries compiled against previous versions"
 
 When an enum changes, and the change causes the code to break, the user 
 can be presented with migration options from an automated IDE tool. In 
 what specific way does this not solve the issue about having to upgrade 
 your code when using someone else's code library? This very notion implies 
 your disgruntled about doing work when things are upgraded, is that really 
 what this fuss is all about?
 
 A well written language interpreter and auto-tooling IDE would not need 
 hints embedded in the code syntax itself. Migration hints from version to 
 version should not be a part of either the past or future version of the 
 code library.
>>> 
>>> Thanks for bringing this up! Unfortunately, it falls down in practice, 
>>> because if there's a new enum case, it's unclear what you want to do with 
>>> it. If you're handling errors, it's not obvious that the way you've handled 
>>> any of the other errors is appropriate. In the (admittedly controversial) 
>>> SKPaymentTransactionState case, none of the existing code would be 
>>> appropriate to handle the newly-introduced "deferred" case, and nor could 
>>> StoreKit provide "template" code that would be appropriate to the client 
>>> app.
>>> 
>>> 
>>> In any case, though, the key point on this particular quoted sentence is 
>>> "without breaking binaries". Any such change must be valid without 
>>> recompilation, and indeed without any intervention from the developer or an 
>>> IDE, because that's what happens when the user updates their OS.
>>> 
>>> Jordan
>>> 
>>> 
>>> 
 
 ...
 
 I don't expect the community to agree on language grammar, but the common 
 sense here on how to achieve the intended goals seems to be out of wack.
 
 If someone can present a clear logical statement as to how an automated 
 migration tool behind the scenes in the IDE to handle all your versioning 
 worries, does not make this whole discussion about adding more convoluted 
 syntax additions irrelevant, I'd love to hear it.
 
 ___
 
 Sincerely,
 Jason
 
 
 
 
 
 
> On Tue, Jan 2, 2018 at 12:36 PM, Xiaodi Wu  wrote:
>> On Tue, Jan 2, 2018 at 12:11 PM, Jason Merchant via swift-evolution 
>>  wrote:
> 
>> I think this whole thing has been 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-08 Thread Dominik Pich via swift-evolution
hello,
im not sure I like this. I think new cases to switches should always break an 
app. :)

> Am 19.12.2017 um 14:58 schrieb Ted Kremenek via swift-evolution 
> :
> 
> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs through 
> January 3, 2018.
> 
> The proposal is available here:
> 
> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>  
> 
> Reviews are an important part of the Swift evolution process. All review 
> feedback should be sent to the swift-evolution mailing list at:
> 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 
> or, if you would like to keep your feedback private, directly to the review 
> manager.
> 
> When replying, please try to keep the proposal link at the top of the message:
> 
> Proposal link: 
> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>  
> 
> ...
> Reply text
> ...
> Other replies
> What goes into a review of a proposal?
> 
> The goal of the review process is to improve the proposal under review 
> through constructive criticism and, eventually, determine the direction of 
> Swift.
> 
> When reviewing a proposal, here are some questions to consider:
> 
> What is your evaluation of the proposal?
> 
> Is the problem being addressed significant enough to warrant a change to 
> Swift?
> 
> Does this proposal fit well with the feel and direction of Swift?
> 
> If you have used other languages or libraries with a similar feature, how do 
> you feel that this proposal compares to those?
> 
> How much effort did you put into your review? A glance, a quick reading, or 
> an in-depth study?
> 
> Thanks,
> Ted Kremenek
> Review Manager
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



signature.asc
Description: Message signed with OpenPGP
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-08 Thread Jon Shier via swift-evolution
Which isn’t a problem right now, AFAICT. Apps compiled under older SDKs 
continue to work fine (sometimes better than when compiled under the new SDK, 
as the older one avoids new bugs). My question is about how that compatibility 
is accomplished today and how and why the Obj-C and Swift cases are apparently 
different here. 



Jon

> On Jan 6, 2018, at 6:12 PM, Javier Soto  wrote:
> 
> What doesn't happen today? The issue is not when they ship a new SDK: When 
> rebuilding your app against it, you'll get a warning for a missing case. The 
> problem is when running the app against a newer iOS version with a newer 
> version of the SDK where the enum has a new case.
>> On Sat, Jan 6, 2018 at 3:10 PM Jon Shier  wrote:
>> Except it clearly doesn’t happen today when Apple ships new SDKs. Obviously 
>> there’s an alternate mechanism used in that case. I’m just curious what it 
>> is and why Swift so desperately needs an alternative.  
>> 
>> 
>> Jon
>> 
>>> On Jan 6, 2018, at 5:49 PM, Javier Soto  wrote:
>>> 
>>> This is very much an issue in Obj-C today. If you have an NS_ENUM defined 
>>> with cases A, B, and C, this switch is correct:
>>> 
>>> int foo;
>>> swith (e) { 
>>> case A: foo = 0; break;
>>> case B: foo = 1; break;
>>> case C: foo = 2; break;
>>> }
>>> 
>>> (Note the lack of a default case)
>>> 
>>> If that enum is defined in a framework and it changes after the app is 
>>> compiled (like it's the case with Apple frameworks), then that code 
>>> produces no warning, yet the foo variable will have a garbage value 
>>> (undefined behavior, but as far as the compiler can tell at compile time 
>>> your code is fine)
>>> 
>>> Adding a default clause to that switch has the downside of not getting 
>>> warnings for new added cases, like has been discussed before, which is very 
>>> useful.
 On Fri, Jan 5, 2018 at 7:11 PM Jon Shier via swift-evolution 
  wrote:
 At this point I think it might be useful to outline how binary 
 compatibility works for Objective-C on Apple platforms right now. As an 
 app developer I’m not intimately familiar with what happens when you run 
 an app compiled with the iOS 10 SDK on iOS 11. Are there just runtime 
 checks to call old code paths or something else? The more this thread goes 
 on the more confused I get about why Swift would have this issue while it 
 doesn’t appear to be one for Obj-C. If an enum adds a case now, I don’t 
 have to care until I recompile using the new SDK. Is the intention for 
 Swift to be different in this regard?
 
 
 
 Jon Shier
 
> On Jan 5, 2018, at 6:41 PM, Jordan Rose via swift-evolution 
>  wrote:
> 
> 
> 
>> On Jan 3, 2018, at 00:54, Jason Merchant via swift-evolution 
>>  wrote:
>> 
>> Is it hard to imagine that most everyone can get what they want and keep 
>> the syntax clean and streamlined at the same time? Without any "@" signs 
>> or other compiler hints?
> 
> For what it's worth, the original version of the proposal started with a 
> modifier (a context-sensitive keyword, like 'final'), but the core team 
> felt that there were a lot of modifiers in the language already, and this 
> didn't meet the bar.
> 
> 
>>> "Rather, we are how to enable the vendor of a nonexhaustive enum to add 
>>> new cases without breaking binaries compiled against previous versions"
>> 
>> When an enum changes, and the change causes the code to break, the user 
>> can be presented with migration options from an automated IDE tool. In 
>> what specific way does this not solve the issue about having to upgrade 
>> your code when using someone else's code library? This very notion 
>> implies your disgruntled about doing work when things are upgraded, is 
>> that really what this fuss is all about?
>> 
>> A well written language interpreter and auto-tooling IDE would not need 
>> hints embedded in the code syntax itself. Migration hints from version 
>> to version should not be a part of either the past or future version of 
>> the code library.
> 
> Thanks for bringing this up! Unfortunately, it falls down in practice, 
> because if there's a new enum case, it's unclear what you want to do with 
> it. If you're handling errors, it's not obvious that the way you've 
> handled any of the other errors is appropriate. In the (admittedly 
> controversial) SKPaymentTransactionState case, none of the existing code 
> would be appropriate to handle the newly-introduced "deferred" case, and 
> nor could StoreKit provide "template" code that would be appropriate to 
> the client app.
> 
> 
> In any case, though, the key point on this particular quoted sentence is 
> "without breaking 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-08 Thread Javier Soto via swift-evolution
What doesn't happen today? The issue is not when they ship a new SDK: When
rebuilding your app against it, you'll get a warning for a missing case.
The problem is when running the app against a newer iOS version with a
newer version of the SDK where the enum has a new case.
On Sat, Jan 6, 2018 at 3:10 PM Jon Shier  wrote:

> Except it clearly doesn’t happen today when Apple ships new SDKs.
> Obviously there’s an alternate mechanism used in that case. I’m just
> curious what it is and why Swift so desperately needs an alternative.
>
>
> Jon
>
> On Jan 6, 2018, at 5:49 PM, Javier Soto  wrote:
>
> This is very much an issue in Obj-C today. If you have an NS_ENUM defined
> with cases A, B, and C, this switch is correct:
>
> int foo;
> swith (e) {
> case A: foo = 0; break;
> case B: foo = 1; break;
> case C: foo = 2; break;
> }
>
> (Note the lack of a default case)
>
> If that enum is defined in a framework and it changes after the app is
> compiled (like it's the case with Apple frameworks), then that code
> produces no warning, yet the foo variable will have a garbage value
> (undefined behavior, but as far as the compiler can tell at compile time
> your code is fine)
>
> Adding a default clause to that switch has the downside of not getting
> warnings for new added cases, like has been discussed before, which is very
> useful.
> On Fri, Jan 5, 2018 at 7:11 PM Jon Shier via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> At this point I think it might be useful to outline how binary
>> compatibility works for Objective-C on Apple platforms right now. As an app
>> developer I’m not intimately familiar with what happens when you run an app
>> compiled with the iOS 10 SDK on iOS 11. Are there just runtime checks to
>> call old code paths or something else? The more this thread goes on the
>> more confused I get about why Swift would have this issue while it doesn’t
>> appear to be one for Obj-C. If an enum adds a case now, I don’t have to
>> care until I recompile using the new SDK. Is the intention for Swift to be
>> different in this regard?
>>
>>
>>
>> Jon Shier
>>
>> On Jan 5, 2018, at 6:41 PM, Jordan Rose via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>
>>
>> On Jan 3, 2018, at 00:54, Jason Merchant via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> Is it hard to imagine that most everyone can get what they want and keep
>> the syntax clean and streamlined at the same time? Without any "@" signs or
>> other compiler hints?
>>
>>
>> For what it's worth, the original version of the proposal started with a
>> modifier (a context-sensitive keyword, like 'final'), but the core team
>> felt that there were a lot of modifiers in the language already, and this
>> didn't meet the bar.
>>
>>
>> "Rather, we are how to enable the vendor of a nonexhaustive enum to add
>>> new cases without breaking binaries compiled against previous versions"
>>
>>
>> When an enum changes, and the change causes the code to break, the user
>> can be presented with migration options from an automated IDE tool. In what
>> specific way does this not solve the issue about having to upgrade your
>> code when using someone else's code library? This very notion implies your
>> disgruntled about doing work when things are upgraded, is that really what
>> this fuss is all about?
>>
>> A well written language interpreter and auto-tooling IDE would not need
>> hints embedded in the code syntax itself. Migration hints from version to
>> version should not be a part of either the past or future version of the
>> code library.
>>
>>
>> Thanks for bringing this up! Unfortunately, it falls down in practice,
>> because if there's a new enum case, *it's unclear what you want to do
>> with it.* If you're handling errors, it's not obvious that the way
>> you've handled any of the *other* errors is appropriate. In the
>> (admittedly controversial) SKPaymentTransactionState case, none of the
>> existing code would be appropriate to handle the newly-introduced
>> "deferred" case, and nor could StoreKit provide "template" code that would
>> be appropriate to the client app.
>>
>>
>> In any case, though, the key point on this particular quoted sentence is
>> "without breaking *binaries"*. Any such change must be valid *without* 
>> recompilation,
>> and indeed without any intervention from the developer or an IDE, because
>> that's what happens when the user updates their OS.
>>
>> Jordan
>>
>>
>>
>>
>> ...
>>
>> I don't expect the community to agree on language grammar, but the common
>> sense here on how to achieve the intended goals seems to be out of wack.
>>
>> If someone can present a clear logical statement as to how an automated
>> migration tool behind the scenes in the IDE to handle all your versioning
>> worries, does not make this whole discussion about adding more convoluted
>> syntax additions irrelevant, I'd love to hear it.
>>
>> ___
>>
>> 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-08 Thread Jon Shier via swift-evolution
Except it clearly doesn’t happen today when Apple ships new SDKs. Obviously 
there’s an alternate mechanism used in that case. I’m just curious what it is 
and why Swift so desperately needs an alternative.  


Jon

> On Jan 6, 2018, at 5:49 PM, Javier Soto  wrote:
> 
> This is very much an issue in Obj-C today. If you have an NS_ENUM defined 
> with cases A, B, and C, this switch is correct:
> 
> int foo;
> swith (e) { 
> case A: foo = 0; break;
> case B: foo = 1; break;
> case C: foo = 2; break;
> }
> 
> (Note the lack of a default case)
> 
> If that enum is defined in a framework and it changes after the app is 
> compiled (like it's the case with Apple frameworks), then that code produces 
> no warning, yet the foo variable will have a garbage value (undefined 
> behavior, but as far as the compiler can tell at compile time your code is 
> fine)
> 
> Adding a default clause to that switch has the downside of not getting 
> warnings for new added cases, like has been discussed before, which is very 
> useful.
>> On Fri, Jan 5, 2018 at 7:11 PM Jon Shier via swift-evolution 
>>  wrote:
>> At this point I think it might be useful to outline how binary compatibility 
>> works for Objective-C on Apple platforms right now. As an app developer I’m 
>> not intimately familiar with what happens when you run an app compiled with 
>> the iOS 10 SDK on iOS 11. Are there just runtime checks to call old code 
>> paths or something else? The more this thread goes on the more confused I 
>> get about why Swift would have this issue while it doesn’t appear to be one 
>> for Obj-C. If an enum adds a case now, I don’t have to care until I 
>> recompile using the new SDK. Is the intention for Swift to be different in 
>> this regard?
>> 
>> 
>> 
>> Jon Shier
>> 
>>> On Jan 5, 2018, at 6:41 PM, Jordan Rose via swift-evolution 
>>>  wrote:
>>> 
>>> 
>>> 
 On Jan 3, 2018, at 00:54, Jason Merchant via swift-evolution 
  wrote:
 
 Is it hard to imagine that most everyone can get what they want and keep 
 the syntax clean and streamlined at the same time? Without any "@" signs 
 or other compiler hints?
>>> 
>>> For what it's worth, the original version of the proposal started with a 
>>> modifier (a context-sensitive keyword, like 'final'), but the core team 
>>> felt that there were a lot of modifiers in the language already, and this 
>>> didn't meet the bar.
>>> 
>>> 
> "Rather, we are how to enable the vendor of a nonexhaustive enum to add 
> new cases without breaking binaries compiled against previous versions"
 
 When an enum changes, and the change causes the code to break, the user 
 can be presented with migration options from an automated IDE tool. In 
 what specific way does this not solve the issue about having to upgrade 
 your code when using someone else's code library? This very notion implies 
 your disgruntled about doing work when things are upgraded, is that really 
 what this fuss is all about?
 
 A well written language interpreter and auto-tooling IDE would not need 
 hints embedded in the code syntax itself. Migration hints from version to 
 version should not be a part of either the past or future version of the 
 code library.
>>> 
>>> Thanks for bringing this up! Unfortunately, it falls down in practice, 
>>> because if there's a new enum case, it's unclear what you want to do with 
>>> it. If you're handling errors, it's not obvious that the way you've handled 
>>> any of the other errors is appropriate. In the (admittedly controversial) 
>>> SKPaymentTransactionState case, none of the existing code would be 
>>> appropriate to handle the newly-introduced "deferred" case, and nor could 
>>> StoreKit provide "template" code that would be appropriate to the client 
>>> app.
>>> 
>>> 
>>> In any case, though, the key point on this particular quoted sentence is 
>>> "without breaking binaries". Any such change must be valid without 
>>> recompilation, and indeed without any intervention from the developer or an 
>>> IDE, because that's what happens when the user updates their OS.
>>> 
>>> Jordan
>>> 
>>> 
>>> 
 
 ...
 
 I don't expect the community to agree on language grammar, but the common 
 sense here on how to achieve the intended goals seems to be out of wack.
 
 If someone can present a clear logical statement as to how an automated 
 migration tool behind the scenes in the IDE to handle all your versioning 
 worries, does not make this whole discussion about adding more convoluted 
 syntax additions irrelevant, I'd love to hear it.
 
 ___
 
 Sincerely,
 Jason
 
 
 
 
 
 
> On Tue, Jan 2, 2018 at 12:36 PM, Xiaodi Wu  wrote:
>> On Tue, Jan 2, 2018 at 12:11 PM, Jason Merchant via 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-08 Thread Javier Soto via swift-evolution
This is very much an issue in Obj-C today. If you have an NS_ENUM defined
with cases A, B, and C, this switch is correct:

int foo;
swith (e) {
case A: foo = 0; break;
case B: foo = 1; break;
case C: foo = 2; break;
}

(Note the lack of a default case)

If that enum is defined in a framework and it changes after the app is
compiled (like it's the case with Apple frameworks), then that code
produces no warning, yet the foo variable will have a garbage value
(undefined behavior, but as far as the compiler can tell at compile time
your code is fine)

Adding a default clause to that switch has the downside of not getting
warnings for new added cases, like has been discussed before, which is very
useful.
On Fri, Jan 5, 2018 at 7:11 PM Jon Shier via swift-evolution <
swift-evolution@swift.org> wrote:

> At this point I think it might be useful to outline how binary
> compatibility works for Objective-C on Apple platforms right now. As an app
> developer I’m not intimately familiar with what happens when you run an app
> compiled with the iOS 10 SDK on iOS 11. Are there just runtime checks to
> call old code paths or something else? The more this thread goes on the
> more confused I get about why Swift would have this issue while it doesn’t
> appear to be one for Obj-C. If an enum adds a case now, I don’t have to
> care until I recompile using the new SDK. Is the intention for Swift to be
> different in this regard?
>
>
>
> Jon Shier
>
> On Jan 5, 2018, at 6:41 PM, Jordan Rose via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
>
> On Jan 3, 2018, at 00:54, Jason Merchant via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Is it hard to imagine that most everyone can get what they want and keep
> the syntax clean and streamlined at the same time? Without any "@" signs or
> other compiler hints?
>
>
> For what it's worth, the original version of the proposal started with a
> modifier (a context-sensitive keyword, like 'final'), but the core team
> felt that there were a lot of modifiers in the language already, and this
> didn't meet the bar.
>
>
> "Rather, we are how to enable the vendor of a nonexhaustive enum to add
>> new cases without breaking binaries compiled against previous versions"
>
>
> When an enum changes, and the change causes the code to break, the user
> can be presented with migration options from an automated IDE tool. In what
> specific way does this not solve the issue about having to upgrade your
> code when using someone else's code library? This very notion implies your
> disgruntled about doing work when things are upgraded, is that really what
> this fuss is all about?
>
> A well written language interpreter and auto-tooling IDE would not need
> hints embedded in the code syntax itself. Migration hints from version to
> version should not be a part of either the past or future version of the
> code library.
>
>
> Thanks for bringing this up! Unfortunately, it falls down in practice,
> because if there's a new enum case, *it's unclear what you want to do
> with it.* If you're handling errors, it's not obvious that the way you've
> handled any of the *other* errors is appropriate. In the (admittedly
> controversial) SKPaymentTransactionState case, none of the existing code
> would be appropriate to handle the newly-introduced "deferred" case, and
> nor could StoreKit provide "template" code that would be appropriate to the
> client app.
>
>
> In any case, though, the key point on this particular quoted sentence is
> "without breaking *binaries"*. Any such change must be valid *without* 
> recompilation,
> and indeed without any intervention from the developer or an IDE, because
> that's what happens when the user updates their OS.
>
> Jordan
>
>
>
>
> ...
>
> I don't expect the community to agree on language grammar, but the common
> sense here on how to achieve the intended goals seems to be out of wack.
>
> If someone can present a clear logical statement as to how an automated
> migration tool behind the scenes in the IDE to handle all your versioning
> worries, does not make this whole discussion about adding more convoluted
> syntax additions irrelevant, I'd love to hear it.
>
> ___
>
> Sincerely,
> Jason
>
>
>
>
>
>
> On Tue, Jan 2, 2018 at 12:36 PM, Xiaodi Wu  wrote:
>
>> On Tue, Jan 2, 2018 at 12:11 PM, Jason Merchant via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> I think this whole thing has been unnecessarily convoluted. As a result,
>>> the majority of the replies are rabbit holes.
>>>
>>> In my opinion, the true root of the concept in question is as follows:
>>>
>>> *A list of something is desired:*
>>> 1 - Pancake
>>> 2 - Waffle
>>> 3 - Juice
>>>
>>> *Developer wishes to be able to:*
>>> *A)* Add new things to the list of choices in the future as they come
>>> up with new ideas
>>> *B)* Sometimes select one of the choices to be chosen as the normal
>>> choice if no choice is made by the user
>>>
>>> A 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-08 Thread Saagar Jha via swift-evolution
(Disclaimer: I’m no expert in this, and I know there are people in this list 
that are, so if there’s anything wrong please feel free to step in and correct 
me)

As far as I’m aware, Apple’s frameworks check which version of the framework 
you linked with at runtime (for UIKit, I believe this function is 
UIApplicationLinkedOnOrAfter) and modify their behavior to match. For example, 
if this function shows your application was linked with the iOS 6 SDK you’d get 
the old skeuomorphic UI instead of the “flatter”, newer iOS 7-style controls. 
What this means is every library actually keeps old implementations around in 
addition to the newer ones and picks the necessary one at runtime, so binary 
compatibility boils down to things like “don't change the memory layout of 
classes” rather than “don’t change the behavior of your program”.

Saagar Jha

> On Jan 5, 2018, at 19:11, Jon Shier via swift-evolution 
>  wrote:
> 
> At this point I think it might be useful to outline how binary compatibility 
> works for Objective-C on Apple platforms right now. As an app developer I’m 
> not intimately familiar with what happens when you run an app compiled with 
> the iOS 10 SDK on iOS 11. Are there just runtime checks to call old code 
> paths or something else? The more this thread goes on the more confused I get 
> about why Swift would have this issue while it doesn’t appear to be one for 
> Obj-C. If an enum adds a case now, I don’t have to care until I recompile 
> using the new SDK. Is the intention for Swift to be different in this regard?
> 
> 
> 
> Jon Shier
> 
> On Jan 5, 2018, at 6:41 PM, Jordan Rose via swift-evolution 
> > wrote:
> 
>> 
>> 
>>> On Jan 3, 2018, at 00:54, Jason Merchant via swift-evolution 
>>> > wrote:
>>> 
>>> Is it hard to imagine that most everyone can get what they want and keep 
>>> the syntax clean and streamlined at the same time? Without any "@" signs or 
>>> other compiler hints?
>> 
>> For what it's worth, the original version of the proposal started with a 
>> modifier (a context-sensitive keyword, like 'final'), but the core team felt 
>> that there were a lot of modifiers in the language already, and this didn't 
>> meet the bar.
>> 
>> 
>>> "Rather, we are how to enable the vendor of a nonexhaustive enum to add new 
>>> cases without breaking binaries compiled against previous versions"
>>> 
>>> When an enum changes, and the change causes the code to break, the user can 
>>> be presented with migration options from an automated IDE tool. In what 
>>> specific way does this not solve the issue about having to upgrade your 
>>> code when using someone else's code library? This very notion implies your 
>>> disgruntled about doing work when things are upgraded, is that really what 
>>> this fuss is all about?
>>> 
>>> A well written language interpreter and auto-tooling IDE would not need 
>>> hints embedded in the code syntax itself. Migration hints from version to 
>>> version should not be a part of either the past or future version of the 
>>> code library.
>> 
>> Thanks for bringing this up! Unfortunately, it falls down in practice, 
>> because if there's a new enum case, it's unclear what you want to do with 
>> it. If you're handling errors, it's not obvious that the way you've handled 
>> any of the other errors is appropriate. In the (admittedly controversial) 
>> SKPaymentTransactionState case, none of the existing code would be 
>> appropriate to handle the newly-introduced "deferred" case, and nor could 
>> StoreKit provide "template" code that would be appropriate to the client app.
>> 
>> 
>> In any case, though, the key point on this particular quoted sentence is 
>> "without breaking binaries". Any such change must be valid without 
>> recompilation, and indeed without any intervention from the developer or an 
>> IDE, because that's what happens when the user updates their OS.
>> 
>> Jordan
>> 
>> 
>> 
>>> 
>>> ...
>>> 
>>> I don't expect the community to agree on language grammar, but the common 
>>> sense here on how to achieve the intended goals seems to be out of wack.
>>> 
>>> If someone can present a clear logical statement as to how an automated 
>>> migration tool behind the scenes in the IDE to handle all your versioning 
>>> worries, does not make this whole discussion about adding more convoluted 
>>> syntax additions irrelevant, I'd love to hear it.
>>> 
>>> ___
>>> 
>>> Sincerely,
>>> Jason
>>> 
>>> 
>>> 
>>> 
>>> 
>>> 
>>> On Tue, Jan 2, 2018 at 12:36 PM, Xiaodi Wu >> > wrote:
>>> On Tue, Jan 2, 2018 at 12:11 PM, Jason Merchant via swift-evolution 
>>> > wrote:
>>> I think this whole thing has been unnecessarily convoluted. As a result, 
>>> the majority of the replies are 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-08 Thread Jason Merchant via swift-evolution
There are a number of things being talked about in this thread, all of
which are solved by proper automated IDE tooling.

Javier, In my opinion the situation you've described is based on how
overall nil is handled by the language parser before it generates LLVM IR.

A smart compiler would know what to do here without any changes to the
language syntax. (Having implemented a similar language parser for LLVM IR,
I can say for certain there is no excuse for the ugly syntax choices that
Swift has been making, and it appears to me the result of laziness and bad
design choices)

I solved this without setting a value before the switch/case statements and
without forcing a default clause to be written. No doubt, it has been clear
that these things appear troubling because of the incorrect design choices
and approach to the underlying problem.

I will present another situation outside of the realm of enums in which
Swift syntax has been made incorrect syntax choices in the handling of nil.

The most obvious is optionals. There are several things wrong with the
swift implementation of optionals:

A: When an object is nil, swift syntax itself changes to try to protect the
user. This results in extra code the developer has to type, even if they
program in genres in which optional situations are irrelevant. (Forcing the
user to unwrap optionals with things like "if let" and "guard" is ugly,
bloated, and unnecessary) In my implementation I have seen that there is no
need for optionals to be written like this in the syntax.

B: The symbols "?" and "!" are littered throughout code needlessly as *compiler
hints*. Meaning the swift parser programmer team was essentially too lazy
to implement what I'm describing and sacrificed the syntax of the language
to avoid writing a parser that would be able to know if something was set
or nil without adding extra garbage to the syntax. Again in my
implementation, I have verified that this can be done and in fact if done
correctly, the resulting* compile time is faster* than the swift compiler,
and the code is cleaner.

What is happening in this thread is that there are core underlying
philosophies that the swift design has adopted which are incorrect
approaches to big picture problems. As a result of swift making these big
picture mistakes, there arise a plethora of these other troubles that come
as domino effects in circumstances here and there. This is why there is a
lot of talk about patching the syntax here or there, and forcing things to
be written, and then down wind of this trail of derailed logic, there arise
a number of people debating what grammar to use for something that
shouldn't be written in the first place. If the big picture problem is
solved, the majority of these discussions are mute.

If Swift can accept that these choices were incorrect, we can cleanup the
syntax and rewrite the parser within an impressively short time as I've
seen myself. However, this requires the agreement of those involved, and
based on this thread and the fact that this line of derailed logic has gone
on for several years, means that the likely response to what I'm suggesting
is one of "That sounds like a lot of work to change, and I already spent a
lot of time and effort making it like this" - Laziness is no excuse for
sticking to bad choices made in the past and causing more bad syntax
choices to be made in the present. If we are truly going to make swift the
dominant language for the future, then we have to adopt a different
attitude toward rewriting design flaws as a community.

We can't always see into the future and know if a choice will be good or
bad, but when we are far enough along the trail to see that the choices
swift made in the past and are a core part of the language, are in fact the
root of the problem, rather than clinging to backward compatibility of a
clearly misguided architecture, *we should do the wise thing and rewrite
the foundation of the language to be built on solid concepts of what we
have learned from the mistakes.*


___

Sincerely,
Jason




On Sat, Jan 6, 2018 at 8:07 PM, Javier Soto  wrote:

> Why isn't that a problem today? Like I showed in that example, that's
> undefined behavior and will potentially result in a bug (or even a crash if
> instead of an int you end up with an unexpected nil pointer)
>
> On Sat, Jan 6, 2018 at 4:47 PM Jon Shier  wrote:
>
>> Which isn’t a problem right now, AFAICT. Apps compiled under older SDKs
>> continue to work fine (sometimes better than when compiled under the new
>> SDK, as the older one avoids new bugs). My question is about how that
>> compatibility is accomplished today and how and why the Obj-C and Swift
>> cases are apparently different here.
>>
>>
>>
>> Jon
>>
>> On Jan 6, 2018, at 6:12 PM, Javier Soto  wrote:
>>
>> What doesn't happen today? The issue is not when they ship a new SDK:
>> When rebuilding your app against it, you'll get a 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-08 Thread Jean-Daniel via swift-evolution


> Le 6 janv. 2018 à 04:11, Jon Shier via swift-evolution 
>  a écrit :
> 
> At this point I think it might be useful to outline how binary compatibility 
> works for Objective-C on Apple platforms right now. As an app developer I’m 
> not intimately familiar with what happens when you run an app compiled with 
> the iOS 10 SDK on iOS 11. Are there just runtime checks to call old code 
> paths or something else? The more this thread goes on the more confused I get 
> about why Swift would have this issue while it doesn’t appear to be one for 
> Obj-C. If an enum adds a case now, I don’t have to care until I recompile 
> using the new SDK. Is the intention for Swift to be different in this regard?
> 

Obj-C does not mandate that you have to handle all cases in an enum. Swift 
does. In Obj-C, when you switch over an unhandled value, the code just flow 
after the switch and continue executing. Your code may be silently buggy (as it 
misses a case), but it does not crash.

In Swift, if you swift over an unhandled case, the program abort execution. 
This is part of the Swift safety model where the language prefers to crash soon 
than continuing with potentially broken assumptions and crashing later at a 
completely unrelated point (which make it very hard to find the root cause of 
the crash).



> 
> 
> Jon Shier
> 
> On Jan 5, 2018, at 6:41 PM, Jordan Rose via swift-evolution 
> > wrote:
> 
>> 
>> 
>>> On Jan 3, 2018, at 00:54, Jason Merchant via swift-evolution 
>>> > wrote:
>>> 
>>> Is it hard to imagine that most everyone can get what they want and keep 
>>> the syntax clean and streamlined at the same time? Without any "@" signs or 
>>> other compiler hints?
>> 
>> For what it's worth, the original version of the proposal started with a 
>> modifier (a context-sensitive keyword, like 'final'), but the core team felt 
>> that there were a lot of modifiers in the language already, and this didn't 
>> meet the bar.
>> 
>> 
>>> "Rather, we are how to enable the vendor of a nonexhaustive enum to add new 
>>> cases without breaking binaries compiled against previous versions"
>>> 
>>> When an enum changes, and the change causes the code to break, the user can 
>>> be presented with migration options from an automated IDE tool. In what 
>>> specific way does this not solve the issue about having to upgrade your 
>>> code when using someone else's code library? This very notion implies your 
>>> disgruntled about doing work when things are upgraded, is that really what 
>>> this fuss is all about?
>>> 
>>> A well written language interpreter and auto-tooling IDE would not need 
>>> hints embedded in the code syntax itself. Migration hints from version to 
>>> version should not be a part of either the past or future version of the 
>>> code library.
>> 
>> Thanks for bringing this up! Unfortunately, it falls down in practice, 
>> because if there's a new enum case, it's unclear what you want to do with 
>> it. If you're handling errors, it's not obvious that the way you've handled 
>> any of the other errors is appropriate. In the (admittedly controversial) 
>> SKPaymentTransactionState case, none of the existing code would be 
>> appropriate to handle the newly-introduced "deferred" case, and nor could 
>> StoreKit provide "template" code that would be appropriate to the client app.
>> 
>> 
>> In any case, though, the key point on this particular quoted sentence is 
>> "without breaking binaries". Any such change must be valid without 
>> recompilation, and indeed without any intervention from the developer or an 
>> IDE, because that's what happens when the user updates their OS.
>> 
>> Jordan
>> 
>> 
>> 
>>> 
>>> ...
>>> 
>>> I don't expect the community to agree on language grammar, but the common 
>>> sense here on how to achieve the intended goals seems to be out of wack.
>>> 
>>> If someone can present a clear logical statement as to how an automated 
>>> migration tool behind the scenes in the IDE to handle all your versioning 
>>> worries, does not make this whole discussion about adding more convoluted 
>>> syntax additions irrelevant, I'd love to hear it.
>>> 
>>> ___
>>> 
>>> Sincerely,
>>> Jason
>>> 
>>> 
>>> 
>>> 
>>> 
>>> 
>>> On Tue, Jan 2, 2018 at 12:36 PM, Xiaodi Wu >> > wrote:
>>> On Tue, Jan 2, 2018 at 12:11 PM, Jason Merchant via swift-evolution 
>>> > wrote:
>>> I think this whole thing has been unnecessarily convoluted. As a result, 
>>> the majority of the replies are rabbit holes.
>>> 
>>> In my opinion, the true root of the concept in question is as follows:
>>> 
>>> A list of something is desired:
>>> 1 - Pancake
>>> 2 - Waffle
>>> 3 - Juice
>>> 
>>> Developer wishes to be able to:
>>> A) Add new things to the 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-05 Thread Jon Shier via swift-evolution
At this point I think it might be useful to outline how binary compatibility 
works for Objective-C on Apple platforms right now. As an app developer I’m not 
intimately familiar with what happens when you run an app compiled with the iOS 
10 SDK on iOS 11. Are there just runtime checks to call old code paths or 
something else? The more this thread goes on the more confused I get about why 
Swift would have this issue while it doesn’t appear to be one for Obj-C. If an 
enum adds a case now, I don’t have to care until I recompile using the new SDK. 
Is the intention for Swift to be different in this regard?



Jon Shier

> On Jan 5, 2018, at 6:41 PM, Jordan Rose via swift-evolution 
>  wrote:
> 
> 
> 
>> On Jan 3, 2018, at 00:54, Jason Merchant via swift-evolution 
>>  wrote:
>> 
>> Is it hard to imagine that most everyone can get what they want and keep the 
>> syntax clean and streamlined at the same time? Without any "@" signs or 
>> other compiler hints?
> 
> For what it's worth, the original version of the proposal started with a 
> modifier (a context-sensitive keyword, like 'final'), but the core team felt 
> that there were a lot of modifiers in the language already, and this didn't 
> meet the bar.
> 
> 
>>> "Rather, we are how to enable the vendor of a nonexhaustive enum to add new 
>>> cases without breaking binaries compiled against previous versions"
>> 
>> When an enum changes, and the change causes the code to break, the user can 
>> be presented with migration options from an automated IDE tool. In what 
>> specific way does this not solve the issue about having to upgrade your code 
>> when using someone else's code library? This very notion implies your 
>> disgruntled about doing work when things are upgraded, is that really what 
>> this fuss is all about?
>> 
>> A well written language interpreter and auto-tooling IDE would not need 
>> hints embedded in the code syntax itself. Migration hints from version to 
>> version should not be a part of either the past or future version of the 
>> code library.
> 
> Thanks for bringing this up! Unfortunately, it falls down in practice, 
> because if there's a new enum case, it's unclear what you want to do with it. 
> If you're handling errors, it's not obvious that the way you've handled any 
> of the other errors is appropriate. In the (admittedly controversial) 
> SKPaymentTransactionState case, none of the existing code would be 
> appropriate to handle the newly-introduced "deferred" case, and nor could 
> StoreKit provide "template" code that would be appropriate to the client app.
> 
> 
> In any case, though, the key point on this particular quoted sentence is 
> "without breaking binaries". Any such change must be valid without 
> recompilation, and indeed without any intervention from the developer or an 
> IDE, because that's what happens when the user updates their OS.
> 
> Jordan
> 
> 
> 
>> 
>> ...
>> 
>> I don't expect the community to agree on language grammar, but the common 
>> sense here on how to achieve the intended goals seems to be out of wack.
>> 
>> If someone can present a clear logical statement as to how an automated 
>> migration tool behind the scenes in the IDE to handle all your versioning 
>> worries, does not make this whole discussion about adding more convoluted 
>> syntax additions irrelevant, I'd love to hear it.
>> 
>> ___
>> 
>> Sincerely,
>> Jason
>> 
>> 
>> 
>> 
>> 
>> 
>>> On Tue, Jan 2, 2018 at 12:36 PM, Xiaodi Wu  wrote:
 On Tue, Jan 2, 2018 at 12:11 PM, Jason Merchant via swift-evolution 
  wrote:
>>> 
 I think this whole thing has been unnecessarily convoluted. As a result, 
 the majority of the replies are rabbit holes.
 
 In my opinion, the true root of the concept in question is as follows:
 
 A list of something is desired:
 1 - Pancake
 2 - Waffle
 3 - Juice
 
 Developer wishes to be able to:
 A) Add new things to the list of choices in the future as they come up 
 with new ideas
 B) Sometimes select one of the choices to be chosen as the normal choice 
 if no choice is made by the user
 
 A and B are separate desires. In some circumstances a developer may want 
 to add a new choice and make it the normal choice when there was no normal 
 choice was clarified before.
>>> 
>>> I don't think this is an accurate summary of the problem being tackled 
>>> here. Rather, we are how to enable the vendor of a nonexhaustive enum to 
>>> add new cases without breaking binaries compiled against previous versions. 
>>> There is little here to do with what a "default" should be. Indeed, it is 
>>> an explicit design decision of Swift not to support types having an 
>>> implicit default value.
>>>  
 
 
 Part 2:
 
 After this simple desire is clear, there should be two 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-05 Thread Jordan Rose via swift-evolution


> On Jan 3, 2018, at 00:54, Jason Merchant via swift-evolution 
>  wrote:
> 
> Is it hard to imagine that most everyone can get what they want and keep the 
> syntax clean and streamlined at the same time? Without any "@" signs or other 
> compiler hints?

For what it's worth, the original version of the proposal started with a 
modifier (a context-sensitive keyword, like 'final'), but the core team felt 
that there were a lot of modifiers in the language already, and this didn't 
meet the bar.


> "Rather, we are how to enable the vendor of a nonexhaustive enum to add new 
> cases without breaking binaries compiled against previous versions"
> 
> When an enum changes, and the change causes the code to break, the user can 
> be presented with migration options from an automated IDE tool. In what 
> specific way does this not solve the issue about having to upgrade your code 
> when using someone else's code library? This very notion implies your 
> disgruntled about doing work when things are upgraded, is that really what 
> this fuss is all about?
> 
> A well written language interpreter and auto-tooling IDE would not need hints 
> embedded in the code syntax itself. Migration hints from version to version 
> should not be a part of either the past or future version of the code library.

Thanks for bringing this up! Unfortunately, it falls down in practice, because 
if there's a new enum case, it's unclear what you want to do with it. If you're 
handling errors, it's not obvious that the way you've handled any of the other 
errors is appropriate. In the (admittedly controversial) 
SKPaymentTransactionState case, none of the existing code would be appropriate 
to handle the newly-introduced "deferred" case, and nor could StoreKit provide 
"template" code that would be appropriate to the client app.


In any case, though, the key point on this particular quoted sentence is 
"without breaking binaries". Any such change must be valid without 
recompilation, and indeed without any intervention from the developer or an 
IDE, because that's what happens when the user updates their OS.

Jordan



> 
> ...
> 
> I don't expect the community to agree on language grammar, but the common 
> sense here on how to achieve the intended goals seems to be out of wack.
> 
> If someone can present a clear logical statement as to how an automated 
> migration tool behind the scenes in the IDE to handle all your versioning 
> worries, does not make this whole discussion about adding more convoluted 
> syntax additions irrelevant, I'd love to hear it.
> 
> ___
> 
> Sincerely,
> Jason
> 
> 
> 
> 
> 
> 
> On Tue, Jan 2, 2018 at 12:36 PM, Xiaodi Wu  > wrote:
> On Tue, Jan 2, 2018 at 12:11 PM, Jason Merchant via swift-evolution 
> > wrote:
> I think this whole thing has been unnecessarily convoluted. As a result, the 
> majority of the replies are rabbit holes.
> 
> In my opinion, the true root of the concept in question is as follows:
> 
> A list of something is desired:
> 1 - Pancake
> 2 - Waffle
> 3 - Juice
> 
> Developer wishes to be able to:
> A) Add new things to the list of choices in the future as they come up with 
> new ideas
> B) Sometimes select one of the choices to be chosen as the normal choice if 
> no choice is made by the user
> 
> A and B are separate desires. In some circumstances a developer may want to 
> add a new choice and make it the normal choice when there was no normal 
> choice was clarified before.
> 
> I don't think this is an accurate summary of the problem being tackled here. 
> Rather, we are how to enable the vendor of a nonexhaustive enum to add new 
> cases without breaking binaries compiled against previous versions. There is 
> little here to do with what a "default" should be. Indeed, it is an explicit 
> design decision of Swift not to support types having an implicit default 
> value.
>  
> 
> 
> Part 2:
> 
> After this simple desire is clear, there should be two discussions:
> A) In a text only coding language, what would we like the syntax to look 
> like? (Without regard to past-bias. What should it really be, forget what 
> mistaken design choices were made in Swift in the past)
> B) How do we approach making this happen behind the scenes?
> 
> Bonus: Given that some of us have changed our approach to programming 
> significantly beyond text based coding, and into more dynamic mediums of 
> programming in other niches, and even here and there in Xcode - I would 
> recommend considering how the IDE would show a modern version of this 
> concept. I feel too often that Swift design syntax has a lack of awareness 
> between the distinctions of what the IDE should do, as opposed to what the 
> syntax of the language should be, and what should be handled behind the 
> scenes by automated tooling.
> 
> 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-05 Thread Jonathan Hull via swift-evolution
Oh, I see… the case would silently change from unexpected to default if they 
were both included.  Hmm.  I will have to think on this more.

Thanks,
Jon

> On Jan 5, 2018, at 3:17 PM, Jordan Rose  wrote:
> 
> 
> 
>> On Jan 5, 2018, at 00:11, Jonathan Hull via swift-evolution 
>> > wrote:
>> 
>>> 
>>> On Jan 4, 2018, at 11:02 PM, Xiaodi Wu >> > wrote:
>>> 
>>> 
>>> On Fri, Jan 5, 2018 at 01:56 Jonathan Hull >> > wrote:
 On Jan 4, 2018, at 10:31 PM, Xiaodi Wu via swift-evolution 
 > wrote:
>>> 
 
 On Fri, Jan 5, 2018 at 00:21 Cheyo Jimenez > wrote:
>>> 
 
 On Jan 4, 2018, at 4:37 PM, Xiaodi Wu > wrote:
 
>>> 
> On Thu, Jan 4, 2018 at 19:29 Cheyo J. Jimenez  > wrote:
> 
> We seem to agree that, by virtue of not supporting use in a pattern and 
> being placed at the end, the feature is a flavor of default. I’m still 
> not sure I understand why you believe it should not be a flavor of 
> default going forward.
> 
>> 
>> You still haven’t answered my question, though—what’s the use case for 
>> the feature you propose?
> 
> My use case would be distinguishing between compile time known cases vs 
> “future only” cases (or unknown cases).
> 
> I understand that the feature you propose would allow you to make such a 
> distinction, but again, what is your use case for doing so?
>>> 
 Breaking out early by checking unknown cases first. I admit this is not 
 deal breaker, just a different style I’d like to see supported in the 
 future. 
>>> 
 
 I'm still not sure I understand. How can the machine know that it's 
 dealing with an unknown case without first checking if it matches any 
 known case?
>>> 
>>> 
>>> I had the same thought as Cheyo.  It isn’t a deal breaker… I like the 
>>> compromise, but I would prefer it trigger only on an actual unknown case 
>>> (as opposed to acting like default). I like to break failure cases out at 
>>> the top when possible. I don’t see any good reason not to support that 
>>> style.
>>> 
>>> To answer your question, in the naive sense, it basically is the same 
>>> question as asking if it is a known case (and then taking the inverse). 
>>> That doesn’t mean actually checking each case separately though. For 
>>> example, if the enum cases are internally represented as an unsigned 
>>> integer, and they are all together in a block, the compiler could simply 
>>> check that it is greater than the max known value. You could probably even 
>>> do a bit mask comparison in some cases...
>>> 
>>> These are obvious optimizations, but why does this require new syntax?
>> 
>> I am not sure I understand what you are asking. There isn’t additional 
>> syntax.  We are just arguing over the name + behavior of ‘unexpected:’.  You 
>> want it to behave like ‘default’ and I am saying that stops the use case I 
>> mention above.
>> 
>> 
>>> What do you gain from writing the unknown case first?
>> I know where to look for the failure cases.  I also tend put a bunch of 
>> guard statements near the beginning of a function.  It is just a programming 
>> style.
>> 
>> With my behavior of ‘unexpected:’ you can put it wherever you want.  Why 
>> limit that by forcing it to go at the end?
>> 
>>> Isn't this basically the same thing as asking for the ability to write the 
>>> default case first, a frequently suggested and rejected syntax addition?
>> 
>> No.  I don’t think I have ever heard that asked for, but putting default in 
>> a different place has a different meaning.  The way I read a switch 
>> statement anyway is that it tries each case until it find one that matches.  
>> Default matches everything, so it has to go at the end (since it will always 
>> match and nothing afterwards will be tried).
>> 
>> Having ‘unexpected:’ also match known/expected cases is problematic as a 
>> mental model.  I think that is just an artifact of the original proposal 
>> using default.  There is no reason 'unexpected:’ should have to handle known 
>> cases as well… let’s just have it trigger on unexpected ones.
> 
> I'm going to repeat this from my reply to Cheyo earlier: I really, really 
> don't want recompiling code against a different version of the library to 
> pick a different case than it did before.
> 
> (This might be a weak argument since overload resolution, protocol 
> conformance checking, etc can end up picking a different declaration than it 
> did before. But I would hope that the overloads or alternate protocol 
> witnesses at least "do the same thing" in normal situations, if 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-05 Thread Jordan Rose via swift-evolution


> On Jan 5, 2018, at 00:11, Jonathan Hull via swift-evolution 
>  wrote:
> 
>> 
>> On Jan 4, 2018, at 11:02 PM, Xiaodi Wu > > wrote:
>> 
>> 
>> On Fri, Jan 5, 2018 at 01:56 Jonathan Hull > > wrote:
>>> On Jan 4, 2018, at 10:31 PM, Xiaodi Wu via swift-evolution 
>>> > wrote:
>> 
>>> 
>>> On Fri, Jan 5, 2018 at 00:21 Cheyo Jimenez >> > wrote:
>> 
>>> 
>>> On Jan 4, 2018, at 4:37 PM, Xiaodi Wu >> > wrote:
>>> 
>> 
 On Thu, Jan 4, 2018 at 19:29 Cheyo J. Jimenez > wrote:
 
 We seem to agree that, by virtue of not supporting use in a pattern and 
 being placed at the end, the feature is a flavor of default. I’m still not 
 sure I understand why you believe it should not be a flavor of default 
 going forward.
 
> 
> You still haven’t answered my question, though—what’s the use case for 
> the feature you propose?
 
 My use case would be distinguishing between compile time known cases vs 
 “future only” cases (or unknown cases).
 
 I understand that the feature you propose would allow you to make such a 
 distinction, but again, what is your use case for doing so?
>> 
>>> Breaking out early by checking unknown cases first. I admit this is not 
>>> deal breaker, just a different style I’d like to see supported in the 
>>> future. 
>> 
>>> 
>>> I'm still not sure I understand. How can the machine know that it's dealing 
>>> with an unknown case without first checking if it matches any known case?
>> 
>> 
>> I had the same thought as Cheyo.  It isn’t a deal breaker… I like the 
>> compromise, but I would prefer it trigger only on an actual unknown case (as 
>> opposed to acting like default). I like to break failure cases out at the 
>> top when possible. I don’t see any good reason not to support that style.
>> 
>> To answer your question, in the naive sense, it basically is the same 
>> question as asking if it is a known case (and then taking the inverse). That 
>> doesn’t mean actually checking each case separately though. For example, if 
>> the enum cases are internally represented as an unsigned integer, and they 
>> are all together in a block, the compiler could simply check that it is 
>> greater than the max known value. You could probably even do a bit mask 
>> comparison in some cases...
>> 
>> These are obvious optimizations, but why does this require new syntax?
> 
> I am not sure I understand what you are asking. There isn’t additional 
> syntax.  We are just arguing over the name + behavior of ‘unexpected:’.  You 
> want it to behave like ‘default’ and I am saying that stops the use case I 
> mention above.
> 
> 
>> What do you gain from writing the unknown case first?
> I know where to look for the failure cases.  I also tend put a bunch of guard 
> statements near the beginning of a function.  It is just a programming style.
> 
> With my behavior of ‘unexpected:’ you can put it wherever you want.  Why 
> limit that by forcing it to go at the end?
> 
>> Isn't this basically the same thing as asking for the ability to write the 
>> default case first, a frequently suggested and rejected syntax addition?
> 
> No.  I don’t think I have ever heard that asked for, but putting default in a 
> different place has a different meaning.  The way I read a switch statement 
> anyway is that it tries each case until it find one that matches.  Default 
> matches everything, so it has to go at the end (since it will always match 
> and nothing afterwards will be tried).
> 
> Having ‘unexpected:’ also match known/expected cases is problematic as a 
> mental model.  I think that is just an artifact of the original proposal 
> using default.  There is no reason 'unexpected:’ should have to handle known 
> cases as well… let’s just have it trigger on unexpected ones.

I'm going to repeat this from my reply to Cheyo earlier: I really, really don't 
want recompiling code against a different version of the library to pick a 
different case than it did before.

(This might be a weak argument since overload resolution, protocol conformance 
checking, etc can end up picking a different declaration than it did before. 
But I would hope that the overloads or alternate protocol witnesses at least 
"do the same thing" in normal situations, if possibly more efficiently. I 
wouldn't expect that for `unknown case` vs. `default` if you actually had both 
of them.)


The reason `unknown case` has to match known cases is, again, for source 
compatibility. If the compiler only produces a warning, rather than an error, 
when you're missing a case, it has to do something if that case comes up. The 
most reasonable thing for it to do (in 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-05 Thread Cheyo J. Jimenez via swift-evolution

> On Jan 5, 2018, at 4:42 AM, Xiaodi Wu  wrote:
> 
> 
> On Fri, Jan 5, 2018 at 03:11 Jonathan Hull  > wrote:
>> On Jan 4, 2018, at 11:02 PM, Xiaodi Wu > > wrote:
>> 
>> 
>> On Fri, Jan 5, 2018 at 01:56 Jonathan Hull > > wrote:
>>> On Jan 4, 2018, at 10:31 PM, Xiaodi Wu via swift-evolution 
>>> > wrote:
>> 
>>> 
>>> On Fri, Jan 5, 2018 at 00:21 Cheyo Jimenez >> > wrote:
>> 
>>> 
>>> On Jan 4, 2018, at 4:37 PM, Xiaodi Wu >> > wrote:
>>> 
>> 
 On Thu, Jan 4, 2018 at 19:29 Cheyo J. Jimenez > wrote:
 
 We seem to agree that, by virtue of not supporting use in a pattern and 
 being placed at the end, the feature is a flavor of default. I’m still not 
 sure I understand why you believe it should not be a flavor of default 
 going forward.
 
> 
> You still haven’t answered my question, though—what’s the use case for 
> the feature you propose?
 
 My use case would be distinguishing between compile time known cases vs 
 “future only” cases (or unknown cases).
 
 I understand that the feature you propose would allow you to make such a 
 distinction, but again, what is your use case for doing so?
>> 
>>> Breaking out early by checking unknown cases first. I admit this is not 
>>> deal breaker, just a different style I’d like to see supported in the 
>>> future. 
>> 
>>> 
>>> I'm still not sure I understand. How can the machine know that it's dealing 
>>> with an unknown case without first checking if it matches any known case?
>> 
>> 
>> I had the same thought as Cheyo.  It isn’t a deal breaker… I like the 
>> compromise, but I would prefer it trigger only on an actual unknown case (as 
>> opposed to acting like default). I like to break failure cases out at the 
>> top when possible. I don’t see any good reason not to support that style.
>> 
>> To answer your question, in the naive sense, it basically is the same 
>> question as asking if it is a known case (and then taking the inverse). That 
>> doesn’t mean actually checking each case separately though. For example, if 
>> the enum cases are internally represented as an unsigned integer, and they 
>> are all together in a block, the compiler could simply check that it is 
>> greater than the max known value. You could probably even do a bit mask 
>> comparison in some cases...
>> 
>> These are obvious optimizations, but why does this require new syntax?
> 
> I am not sure I understand what you are asking. There isn’t additional 
> syntax.  We are just arguing over the name + behavior of ‘unexpected:’.  You 
> want it to behave like ‘default’ and I am saying that stops the use case I 
> mention above.
> 
> Cheyo said he wants “unexpected case” to work in pattern matching, as well as 
> a new “case *” that is distinct from “case _”. This is additional syntax. 
> When asked what the use case was for these suggestions, he said he wants to 
> distinguish between known and unknown cases at the beginning of the switch.
> 
> 
> 
>> What do you gain from writing the unknown case first?
> 
> I know where to look for the failure cases.  I also tend put a bunch of guard 
> statements near the beginning of a function.  It is just a programming style.
> 
> With my behavior of ‘unexpected:’ you can put it wherever you want.  Why 
> limit that by forcing it to go at the end?
> 
> As pointed out earlier (by one of the core team members, I think), meaningful 
> resilience would mean that the unexpected or unknown case should have useful 
> work executed at runtime; the intention is that the user *shouldn’t* be 
> treating it as a runtime “failure case,” as it effectively makes adding an 
> enum case a change that is incompatible with existing binaries (i.e., not 
> terribly resilient).
> 
> As you and I seem to agree, reaching an unexpected case requires at least 
> notionally considering which cases are expected in the first place. This is 
> the dictionary definition of a default, and Swift usage is to put the default 
> case at the end of a switch statement. Adding new syntax as Cheyo suggests to 
> enable putting it elsewhere, merely for “style,” doesn’t seem to pass the bar 
> for new syntax, nor is it consistent with existing Swift usage.

I agree with the new syntax suggestion is premature. I would hope that the 
proposed runtime "Deriving collections of enum cases” 
 function also has a 
compile time version which we can then use to match all the known cases at 
compile time. I am happy with SE 0192 as it stands now. 


> 
>> Isn't this basically the same thing as asking for the ability 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-05 Thread Xiaodi Wu via swift-evolution
On Fri, Jan 5, 2018 at 03:11 Jonathan Hull  wrote:

> On Jan 4, 2018, at 11:02 PM, Xiaodi Wu  wrote:
>
>
> On Fri, Jan 5, 2018 at 01:56 Jonathan Hull  wrote:
>
>> On Jan 4, 2018, at 10:31 PM, Xiaodi Wu via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>
>> On Fri, Jan 5, 2018 at 00:21 Cheyo Jimenez  wrote:
>>
>>
>>> On Jan 4, 2018, at 4:37 PM, Xiaodi Wu  wrote:
>>>
>>> On Thu, Jan 4, 2018 at 19:29 Cheyo J. Jimenez 
>>> wrote:
>>>
>>> We seem to agree that, by virtue of not supporting use in a pattern and
>>> being placed at the end, the feature is a flavor of default. I’m still not
>>> sure I understand why you believe it should not be a flavor of default
>>> going forward.
>>>
>>>
 You still haven’t answered my question, though—what’s the use case for
 the feature you propose?


 My use case would be distinguishing between compile time known cases vs
 “future only” cases (or unknown cases).

>>>
>>> I understand that the feature you propose would allow you to make such a
>>> distinction, but again, what is your use case for doing so?
>>>
>>> Breaking out early by checking unknown cases first. I admit this is not
>>> deal breaker, just a different style I’d like to see supported in the
>>> future.
>>>
>>
>> I'm still not sure I understand. How can the machine know that it's
>> dealing with an unknown case without first checking if it matches any known
>> case?
>>
>>
>> I had the same thought as Cheyo.  It isn’t a deal breaker… I like the
>> compromise, but I would prefer it trigger only on an actual unknown case
>> (as opposed to acting like default). I like to break failure cases out at
>> the top when possible. I don’t see any good reason not to support that
>> style.
>>
>> To answer your question, in the naive sense, it basically is the same
>> question as asking if it is a known case (and then taking the inverse).
>> That doesn’t mean actually checking each case separately though. For
>> example, if the enum cases are internally represented as an unsigned
>> integer, and they are all together in a block, the compiler could simply
>> check that it is greater than the max known value. You could probably even
>> do a bit mask comparison in some cases...
>>
>
> These are obvious optimizations, but why does this require new syntax?
>
>
> I am not sure I understand what you are asking. There isn’t additional
> syntax.  We are just arguing over the name + behavior of ‘unexpected:’.
> You want it to behave like ‘default’ and I am saying that stops the use
> case I mention above.
>

Cheyo said he wants “unexpected case” to work in pattern matching, as well
as a new “case *” that is distinct from “case _”. This is additional
syntax. When asked what the use case was for these suggestions, he said he
wants to distinguish between known and unknown cases at the beginning of
the switch.


>
> What do you gain from writing the unknown case first?
>
> I know where to look for the failure cases.  I also tend put a bunch of
> guard statements near the beginning of a function.  It is just a
> programming style.
>
> With my behavior of ‘unexpected:’ you can put it wherever you want.  Why
> limit that by forcing it to go at the end?
>

As pointed out earlier (by one of the core team members, I think),
meaningful resilience would mean that the unexpected or unknown case should
have useful work executed at runtime; the intention is that the user
*shouldn’t* be treating it as a runtime “failure case,” as it effectively
makes adding an enum case a change that is incompatible with existing
binaries (i.e., not terribly resilient).

As you and I seem to agree, reaching an unexpected case requires at least
notionally considering which cases are expected in the first place. This is
the dictionary definition of a default, and Swift usage is to put the
default case at the end of a switch statement. Adding new syntax as Cheyo
suggests to enable putting it elsewhere, merely for “style,” doesn’t seem
to pass the bar for new syntax, nor is it consistent with existing Swift
usage.

Isn't this basically the same thing as asking for the ability to write the
> default case first, a frequently suggested and rejected syntax addition?
>
>
> No.  I don’t think I have ever heard that asked for,
>

It has been asked for more than once on this list.

but putting default in a different place has a different meaning.  The way
> I read a switch statement anyway is that it tries each case until it find
> one that matches.  Default matches everything, so it has to go at the end
> (since it will always match and nothing afterwards will be tried).
>
> Having ‘unexpected:’ also match known/expected cases is problematic as a
> mental model.  I think that is just an artifact of the original proposal
> using default.  There is no reason 'unexpected:’ should have to handle
> known cases as well… let’s just 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-05 Thread Jonathan Hull via swift-evolution

> On Jan 4, 2018, at 11:02 PM, Xiaodi Wu  wrote:
> 
> 
> On Fri, Jan 5, 2018 at 01:56 Jonathan Hull  > wrote:
>> On Jan 4, 2018, at 10:31 PM, Xiaodi Wu via swift-evolution 
>> > wrote:
> 
>> 
>> On Fri, Jan 5, 2018 at 00:21 Cheyo Jimenez > > wrote:
> 
>> 
>> On Jan 4, 2018, at 4:37 PM, Xiaodi Wu > > wrote:
>> 
> 
>>> On Thu, Jan 4, 2018 at 19:29 Cheyo J. Jimenez >> > wrote:
>>> 
>>> We seem to agree that, by virtue of not supporting use in a pattern and 
>>> being placed at the end, the feature is a flavor of default. I’m still not 
>>> sure I understand why you believe it should not be a flavor of default 
>>> going forward.
>>> 
 
 You still haven’t answered my question, though—what’s the use case for the 
 feature you propose?
>>> 
>>> My use case would be distinguishing between compile time known cases vs 
>>> “future only” cases (or unknown cases).
>>> 
>>> I understand that the feature you propose would allow you to make such a 
>>> distinction, but again, what is your use case for doing so?
> 
>> Breaking out early by checking unknown cases first. I admit this is not deal 
>> breaker, just a different style I’d like to see supported in the future. 
> 
>> 
>> I'm still not sure I understand. How can the machine know that it's dealing 
>> with an unknown case without first checking if it matches any known case?
> 
> 
> I had the same thought as Cheyo.  It isn’t a deal breaker… I like the 
> compromise, but I would prefer it trigger only on an actual unknown case (as 
> opposed to acting like default). I like to break failure cases out at the top 
> when possible. I don’t see any good reason not to support that style.
> 
> To answer your question, in the naive sense, it basically is the same 
> question as asking if it is a known case (and then taking the inverse). That 
> doesn’t mean actually checking each case separately though. For example, if 
> the enum cases are internally represented as an unsigned integer, and they 
> are all together in a block, the compiler could simply check that it is 
> greater than the max known value. You could probably even do a bit mask 
> comparison in some cases...
> 
> These are obvious optimizations, but why does this require new syntax?

I am not sure I understand what you are asking. There isn’t additional syntax.  
We are just arguing over the name + behavior of ‘unexpected:’.  You want it to 
behave like ‘default’ and I am saying that stops the use case I mention above.


> What do you gain from writing the unknown case first?
I know where to look for the failure cases.  I also tend put a bunch of guard 
statements near the beginning of a function.  It is just a programming style.

With my behavior of ‘unexpected:’ you can put it wherever you want.  Why limit 
that by forcing it to go at the end?

> Isn't this basically the same thing as asking for the ability to write the 
> default case first, a frequently suggested and rejected syntax addition?

No.  I don’t think I have ever heard that asked for, but putting default in a 
different place has a different meaning.  The way I read a switch statement 
anyway is that it tries each case until it find one that matches.  Default 
matches everything, so it has to go at the end (since it will always match and 
nothing afterwards will be tried).

Having ‘unexpected:’ also match known/expected cases is problematic as a mental 
model.  I think that is just an artifact of the original proposal using 
default.  There is no reason 'unexpected:’ should have to handle known cases as 
well… let’s just have it trigger on unexpected ones.

Thanks,
Jon


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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-04 Thread Xiaodi Wu via swift-evolution
On Fri, Jan 5, 2018 at 01:56 Jonathan Hull  wrote:

> On Jan 4, 2018, at 10:31 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> On Fri, Jan 5, 2018 at 00:21 Cheyo Jimenez  wrote:
>
>
>> On Jan 4, 2018, at 4:37 PM, Xiaodi Wu  wrote:
>>
>> On Thu, Jan 4, 2018 at 19:29 Cheyo J. Jimenez 
>> wrote:
>>
>> We seem to agree that, by virtue of not supporting use in a pattern and
>> being placed at the end, the feature is a flavor of default. I’m still not
>> sure I understand why you believe it should not be a flavor of default
>> going forward.
>>
>>
>>> You still haven’t answered my question, though—what’s the use case for
>>> the feature you propose?
>>>
>>>
>>> My use case would be distinguishing between compile time known cases vs
>>> “future only” cases (or unknown cases).
>>>
>>
>> I understand that the feature you propose would allow you to make such a
>> distinction, but again, what is your use case for doing so?
>>
>> Breaking out early by checking unknown cases first. I admit this is not
>> deal breaker, just a different style I’d like to see supported in the
>> future.
>>
>
> I'm still not sure I understand. How can the machine know that it's
> dealing with an unknown case without first checking if it matches any known
> case?
>
>
> I had the same thought as Cheyo.  It isn’t a deal breaker… I like the
> compromise, but I would prefer it trigger only on an actual unknown case
> (as opposed to acting like default). I like to break failure cases out at
> the top when possible. I don’t see any good reason not to support that
> style.
>
> To answer your question, in the naive sense, it basically is the same
> question as asking if it is a known case (and then taking the inverse).
> That doesn’t mean actually checking each case separately though. For
> example, if the enum cases are internally represented as an unsigned
> integer, and they are all together in a block, the compiler could simply
> check that it is greater than the max known value. You could probably even
> do a bit mask comparison in some cases...
>

These are obvious optimizations, but why does this require new syntax? What
do you gain from writing the unknown case first? Isn't this basically the
same thing as asking for the ability to write the default case first, a
frequently suggested and rejected syntax addition?

If it is inefficient for some reason, the compiler should be free to
> rearrange the order of things, as long as it doesn’t change the outcome.
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-04 Thread Jonathan Hull via swift-evolution

> On Jan 4, 2018, at 10:31 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Fri, Jan 5, 2018 at 00:21 Cheyo Jimenez  > wrote:
> 
> On Jan 4, 2018, at 4:37 PM, Xiaodi Wu  > wrote:
> 
>> On Thu, Jan 4, 2018 at 19:29 Cheyo J. Jimenez > > wrote:
>> 
>> We seem to agree that, by virtue of not supporting use in a pattern and 
>> being placed at the end, the feature is a flavor of default. I’m still not 
>> sure I understand why you believe it should not be a flavor of default going 
>> forward.
>> 
>>> 
>>> You still haven’t answered my question, though—what’s the use case for the 
>>> feature you propose?
>> 
>> My use case would be distinguishing between compile time known cases vs 
>> “future only” cases (or unknown cases).
>> 
>> I understand that the feature you propose would allow you to make such a 
>> distinction, but again, what is your use case for doing so?
> 
> Breaking out early by checking unknown cases first. I admit this is not deal 
> breaker, just a different style I’d like to see supported in the future. 
> 
> I'm still not sure I understand. How can the machine know that it's dealing 
> with an unknown case without first checking if it matches any known case?

I had the same thought as Cheyo.  It isn’t a deal breaker… I like the 
compromise, but I would prefer it trigger only on an actual unknown case (as 
opposed to acting like default). I like to break failure cases out at the top 
when possible. I don’t see any good reason not to support that style.

To answer your question, in the naive sense, it basically is the same question 
as asking if it is a known case (and then taking the inverse). That doesn’t 
mean actually checking each case separately though. For example, if the enum 
cases are internally represented as an unsigned integer, and they are all 
together in a block, the compiler could simply check that it is greater than 
the max known value. You could probably even do a bit mask comparison in some 
cases...

If it is inefficient for some reason, the compiler should be free to rearrange 
the order of things, as long as it doesn’t change the outcome.

Thanks,
Jon ___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-04 Thread Xiaodi Wu via swift-evolution
On Fri, Jan 5, 2018 at 00:21 Cheyo Jimenez  wrote:

>
>
> On Jan 4, 2018, at 4:37 PM, Xiaodi Wu  wrote:
>
>
> On Thu, Jan 4, 2018 at 19:29 Cheyo J. Jimenez  wrote:
>
>> On Jan 4, 2018, at 3:50 PM, Xiaodi Wu  wrote:
>>
>>
>> On Thu, Jan 4, 2018 at 18:39 Cheyo J. Jimenez 
>> wrote:
>>
>>>
>>> On Jan 4, 2018, at 2:55 PM, Xiaodi Wu  wrote:
>>>
>>>
>>> On Thu, Jan 4, 2018 at 17:15 Cheyo J. Jimenez 
>>> wrote:
>>>
 On Jan 4, 2018, at 11:53 AM, Xiaodi Wu  wrote:


 On Thu, Jan 4, 2018 at 13:46 Cheyo Jimenez  wrote:

>
>
> On Jan 4, 2018, at 10:49 AM, Jordan Rose 
> wrote:
>
> I'll admit I hadn't thought of using "unknown default" (or "default
> unknown"). I don't think that's terrible, but I mildly prefer `unknown
> case` because it builds on the "pun" that enum elements are also defined
> using 'case'. If anything hits this part of the switch, it really will be
> an "unknown case", i.e. a statically-unknown enum element.
>
> To Cheyo's point, if this *were* to be a single token I'd probably
> spell it #unknown, like #available. Then we'd have `case #unknown:` and
> something that naturally expands to other pattern positions. I found that
> less aesthetically pleasing, though, and so a context-sensitive keyword
> seemed like the way to go.
>
> (For the record, though, I wouldn't describe `case _` as a special
> case of `default`. They do exactly the same thing, and `_` is a useful
> pattern in other contexts, so if anything the current `default` should be
> thought of as syntactic sugar for `case _`.)
>
>
> Can case _ be mixed with unknown case? How can we match all compile
> time known cases but exclude future cases?
>

 What’s your use case for that? That eliminates the possibility of
 “unknown case” giving you compile-time warnings for subsequently added
 cases, which was the entire purpose of adding the syntax in the first 
 place.


 I was thinking of a generalized `unknown case` pattern but that is out
 of scope for this proposal.
 


 switch excuse {
  case .eatenByPet :
//…
  unknown case:
// …
  case _:
// …
  }


 Should there be something like `case *` that would capture all
> currently known cases during compile time? case * and case _ would be the
> same in exhaustive enums.
>

 This is why I was suggesting another pattern that only captures known
 cases at compile time:

 switch excuse {
  case .eatenByPet :
//…
  case * : //  All cases captured at compile time.
// …
  unknown case:
// …
  }

>>>
>>> Sorry, I don’t understand. However you spell it, what is your use case
>>> for this? The stated purpose of “unknown case” is to gain compile-time
>>> exhaustiveness testing, but this would not allow for that.
>>>
>>>
>>>
>>>
>>>
>>> switch (excuse, notifiedTeacherBeforeDeadline) {case (.eatenByPet, true):
>>>   // …case (.thoughtItWasDueNextWeek, true):
>>>   // …case (unknown case, true):
>>>   // …case (_, false):
>>>   // …}
>>>
>>>
>>> Im referring to the future direction section in the new PR
>>> .
>>> The above example if from there.
>>>
>>> I am fine with `unknown case` being required to be at the end of the
>>> switch for now.
>>>
>>> I think of `unknown case` as a pattern that only matches unknown cases
>>> no matter where on the switch it is.
>>>
>>> This is why I do not think that `default unknown` would work well once
>>> `unknown case` can be used a pattern.
>>>
>>> We can start a new thread on this if you’d like.
>>>
>>
>> The reason I put forward “default unknown” is precisely because the
>> proposed feature *cannot* be used in a pattern and therefore seems more apt
>> as not a case.
>>
>> It can not be used in a pattern now but you could in the future if left
>> as `case`.
>>
>>
>> It actually makes it more natural to use in the given example above
>> because “default unknown” could actually be used to provide compile-time
>> exhaustiveness checking for such a tuple pattern, whereas without being
>> able to use “unknown case” in a pattern you can’t write “case (unknown
>> case, _)”.
>>
>>
>> The way `unknown case` enforces  compile-time exhaustiveness is by only
>> matching unknown cases. The implementation may be more close to default by
>> the virtue of being forced to go at the end of the switch statement now but
>> that should not 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-04 Thread Cheyo Jimenez via swift-evolution


> On Jan 4, 2018, at 4:37 PM, Xiaodi Wu  wrote:
> 
> 
> On Thu, Jan 4, 2018 at 19:29 Cheyo J. Jimenez  wrote:
>>> On Jan 4, 2018, at 3:50 PM, Xiaodi Wu  wrote:
>>> 
>>> 
>>> On Thu, Jan 4, 2018 at 18:39 Cheyo J. Jimenez  wrote:
 
> On Jan 4, 2018, at 2:55 PM, Xiaodi Wu  wrote:
> 
> 
> On Thu, Jan 4, 2018 at 17:15 Cheyo J. Jimenez  wrote:
>>> On Jan 4, 2018, at 11:53 AM, Xiaodi Wu  wrote:
>>> 
>>> 
 On Thu, Jan 4, 2018 at 13:46 Cheyo Jimenez  wrote:
 
 
> On Jan 4, 2018, at 10:49 AM, Jordan Rose  
> wrote:
> 
> I'll admit I hadn't thought of using "unknown default" (or "default 
> unknown"). I don't think that's terrible, but I mildly prefer 
> `unknown case` because it builds on the "pun" that enum elements are 
> also defined using 'case'. If anything hits this part of the switch, 
> it really will be an "unknown case", i.e. a statically-unknown enum 
> element.
> 
> To Cheyo's point, if this were to be a single token I'd probably 
> spell it #unknown, like #available. Then we'd have `case #unknown:` 
> and something that naturally expands to other pattern positions. I 
> found that less aesthetically pleasing, though, and so a 
> context-sensitive keyword seemed like the way to go.
> 
> (For the record, though, I wouldn't describe `case _` as a special 
> case of `default`. They do exactly the same thing, and `_` is a 
> useful pattern in other contexts, so if anything the current 
> `default` should be thought of as syntactic sugar for `case _`.)
 
 Can case _ be mixed with unknown case? How can we match all compile 
 time known cases but exclude future cases?
>>> 
>>> What’s your use case for that? That eliminates the possibility of 
>>> “unknown case” giving you compile-time warnings for subsequently added 
>>> cases, which was the entire purpose of adding the syntax in the first 
>>> place.
>> 
>> I was thinking of a generalized `unknown case` pattern but that is out 
>> of scope for this proposal. 
>> 
>> switch excuse {
>>  case .eatenByPet :
>>//…
>>  unknown case:
>>// …
>>  case _:
>>// …
>>  }
>> 
>>> 
 Should there be something like `case *` that would capture all 
 currently known cases during compile time? case * and case _ would be 
 the same in exhaustive enums. 
>> 
>> This is why I was suggesting another pattern that only captures known 
>> cases at compile time:
>> 
>> switch excuse {
>>  case .eatenByPet :
>>//…
>>  case * : //  All cases captured at compile time. 
>>// …
>>  unknown case:
>>// …
>>  }
> 
> Sorry, I don’t understand. However you spell it, what is your use case 
> for this? The stated purpose of “unknown case” is to gain compile-time 
> exhaustiveness testing, but this would not allow for that.
 
 
 
 
 switch (excuse, notifiedTeacherBeforeDeadline) {
 case (.eatenByPet, true):
   // …
 case (.thoughtItWasDueNextWeek, true):
   // …
 case (unknown case, true):
   // …
 case (_, false):
   // …
 }
 
 Im referring to the future direction section in the new PR. The above 
 example if from there. 
 
 I am fine with `unknown case` being required to be at the end of the 
 switch for now. 
 
 I think of `unknown case` as a pattern that only matches unknown cases no 
 matter where on the switch it is.
 
 This is why I do not think that `default unknown` would work well once 
 `unknown case` can be used a pattern.
 
 We can start a new thread on this if you’d like. 
>>> 
>>> The reason I put forward “default unknown” is precisely because the 
>>> proposed feature *cannot* be used in a pattern and therefore seems more apt 
>>> as not a case.
>>> 
>> 
>> It can not be used in a pattern now but you could in the future if left as 
>> `case`. 
>> 
>> 
>>> It actually makes it more natural to use in the given example above because 
>>> “default unknown” could actually be used to provide compile-time 
>>> exhaustiveness checking for such a tuple pattern, whereas without being 
>>> able to use “unknown case” in a pattern you can’t write “case (unknown 
>>> case, _)”.
>> 
>> The way `unknown case` enforces  compile-time exhaustiveness is by only 
>> matching unknown cases. The implementation may be more close to default by 
>> the virtue of being forced to go at the end of the switch statement now but 
>> that should not dictate the user experience. 
> 
> We seem to 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-04 Thread Xiaodi Wu via swift-evolution
On Thu, Jan 4, 2018 at 19:29 Cheyo J. Jimenez  wrote:

> On Jan 4, 2018, at 3:50 PM, Xiaodi Wu  wrote:
>
>
> On Thu, Jan 4, 2018 at 18:39 Cheyo J. Jimenez  wrote:
>
>>
>> On Jan 4, 2018, at 2:55 PM, Xiaodi Wu  wrote:
>>
>>
>> On Thu, Jan 4, 2018 at 17:15 Cheyo J. Jimenez 
>> wrote:
>>
>>> On Jan 4, 2018, at 11:53 AM, Xiaodi Wu  wrote:
>>>
>>>
>>> On Thu, Jan 4, 2018 at 13:46 Cheyo Jimenez  wrote:
>>>


 On Jan 4, 2018, at 10:49 AM, Jordan Rose  wrote:

 I'll admit I hadn't thought of using "unknown default" (or "default
 unknown"). I don't think that's terrible, but I mildly prefer `unknown
 case` because it builds on the "pun" that enum elements are also defined
 using 'case'. If anything hits this part of the switch, it really will be
 an "unknown case", i.e. a statically-unknown enum element.

 To Cheyo's point, if this *were* to be a single token I'd probably
 spell it #unknown, like #available. Then we'd have `case #unknown:` and
 something that naturally expands to other pattern positions. I found that
 less aesthetically pleasing, though, and so a context-sensitive keyword
 seemed like the way to go.

 (For the record, though, I wouldn't describe `case _` as a special case
 of `default`. They do exactly the same thing, and `_` is a useful pattern
 in other contexts, so if anything the current `default` should be thought
 of as syntactic sugar for `case _`.)


 Can case _ be mixed with unknown case? How can we match all compile
 time known cases but exclude future cases?

>>>
>>> What’s your use case for that? That eliminates the possibility of
>>> “unknown case” giving you compile-time warnings for subsequently added
>>> cases, which was the entire purpose of adding the syntax in the first place.
>>>
>>>
>>> I was thinking of a generalized `unknown case` pattern but that is out
>>> of scope for this proposal.
>>> 
>>>
>>>
>>> switch excuse {
>>>  case .eatenByPet :
>>>//…
>>>  unknown case:
>>>// …
>>>  case _:
>>>// …
>>>  }
>>>
>>>
>>> Should there be something like `case *` that would capture all currently
 known cases during compile time? case * and case _ would be the same in
 exhaustive enums.

>>>
>>> This is why I was suggesting another pattern that only captures known
>>> cases at compile time:
>>>
>>> switch excuse {
>>>  case .eatenByPet :
>>>//…
>>>  case * : //  All cases captured at compile time.
>>>// …
>>>  unknown case:
>>>// …
>>>  }
>>>
>>
>> Sorry, I don’t understand. However you spell it, what is your use case
>> for this? The stated purpose of “unknown case” is to gain compile-time
>> exhaustiveness testing, but this would not allow for that.
>>
>>
>>
>>
>>
>> switch (excuse, notifiedTeacherBeforeDeadline) {case (.eatenByPet, true):
>>   // …case (.thoughtItWasDueNextWeek, true):
>>   // …case (unknown case, true):
>>   // …case (_, false):
>>   // …}
>>
>>
>> Im referring to the future direction section in the new PR
>> .
>> The above example if from there.
>>
>> I am fine with `unknown case` being required to be at the end of the
>> switch for now.
>>
>> I think of `unknown case` as a pattern that only matches unknown cases no
>> matter where on the switch it is.
>>
>> This is why I do not think that `default unknown` would work well once
>> `unknown case` can be used a pattern.
>>
>> We can start a new thread on this if you’d like.
>>
>
> The reason I put forward “default unknown” is precisely because the
> proposed feature *cannot* be used in a pattern and therefore seems more apt
> as not a case.
>
> It can not be used in a pattern now but you could in the future if left as
> `case`.
>
>
> It actually makes it more natural to use in the given example above
> because “default unknown” could actually be used to provide compile-time
> exhaustiveness checking for such a tuple pattern, whereas without being
> able to use “unknown case” in a pattern you can’t write “case (unknown
> case, _)”.
>
>
> The way `unknown case` enforces  compile-time exhaustiveness is by only
> matching unknown cases. The implementation may be more close to default by
> the virtue of being forced to go at the end of the switch statement now but
> that should not dictate the user experience.
>

We seem to agree that, by virtue of not supporting use in a pattern and
being placed at the end, the feature is a flavor of default. I’m still not
sure I understand why you believe it should not be a flavor of default
going forward.


> You still haven’t answered my 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-04 Thread Cheyo J. Jimenez via swift-evolution

> On Jan 4, 2018, at 3:50 PM, Xiaodi Wu  wrote:
> 
> 
> On Thu, Jan 4, 2018 at 18:39 Cheyo J. Jimenez  > wrote:
> 
>> On Jan 4, 2018, at 2:55 PM, Xiaodi Wu > > wrote:
>> 
>> 
>> On Thu, Jan 4, 2018 at 17:15 Cheyo J. Jimenez > > wrote:
>>> On Jan 4, 2018, at 11:53 AM, Xiaodi Wu >> > wrote:
>>> 
>>> 
>>> On Thu, Jan 4, 2018 at 13:46 Cheyo Jimenez >> > wrote:
>>> 
>>> 
>>> On Jan 4, 2018, at 10:49 AM, Jordan Rose >> > wrote:
>>> 
 I'll admit I hadn't thought of using "unknown default" (or "default 
 unknown"). I don't think that's terrible, but I mildly prefer `unknown 
 case` because it builds on the "pun" that enum elements are also defined 
 using 'case'. If anything hits this part of the switch, it really will be 
 an "unknown case", i.e. a statically-unknown enum element.
 
 To Cheyo's point, if this were to be a single token I'd probably spell it 
 #unknown, like #available. Then we'd have `case #unknown:` and something 
 that naturally expands to other pattern positions. I found that less 
 aesthetically pleasing, though, and so a context-sensitive keyword seemed 
 like the way to go.
 
 (For the record, though, I wouldn't describe `case _` as a special case of 
 `default`. They do exactly the same thing, and `_` is a useful pattern in 
 other contexts, so if anything the current `default` should be thought of 
 as syntactic sugar for `case _`.)
>>> 
>>> Can case _ be mixed with unknown case? How can we match all compile time 
>>> known cases but exclude future cases?
>>> 
>>> What’s your use case for that? That eliminates the possibility of “unknown 
>>> case” giving you compile-time warnings for subsequently added cases, which 
>>> was the entire purpose of adding the syntax in the first place.
>> 
>> I was thinking of a generalized `unknown case` pattern but that is out of 
>> scope for this proposal. 
>> 
>>  
>> 
>> switch excuse {
>>  case .eatenByPet :
>>//…
>>  unknown case:
>>// …
>>  case _:
>>// …
>>  }
>> 
>>> 
>>> Should there be something like `case *` that would capture all currently 
>>> known cases during compile time? case * and case _ would be the same in 
>>> exhaustive enums. 
>> 
>> This is why I was suggesting another pattern that only captures known cases 
>> at compile time:
>> 
>> switch excuse {
>>  case .eatenByPet :
>>//…
>>  case * : //  All cases captured at compile time. 
>>// …
>>  unknown case:
>>// …
>>  }
>> 
>> Sorry, I don’t understand. However you spell it, what is your use case for 
>> this? The stated purpose of “unknown case” is to gain compile-time 
>> exhaustiveness testing, but this would not allow for that.
> 
> 
> 
> 
> switch (excuse, notifiedTeacherBeforeDeadline) {
> case (.eatenByPet, true):
>   // …
> case (.thoughtItWasDueNextWeek, true):
>   // …
> case (unknown case, true):
>   // …
> case (_, false):
>   // …
> }
> 
> Im referring to the future direction section in the new PR 
> .
>  The above example if from there. 
> 
> I am fine with `unknown case` being required to be at the end of the switch 
> for now. 
> 
> I think of `unknown case` as a pattern that only matches unknown cases no 
> matter where on the switch it is.
> 
> This is why I do not think that `default unknown` would work well once 
> `unknown case` can be used a pattern.
> 
> We can start a new thread on this if you’d like. 
> 
> The reason I put forward “default unknown” is precisely because the proposed 
> feature *cannot* be used in a pattern and therefore seems more apt as not a 
> case.
> 
It can not be used in a pattern now but you could in the future if left as 
`case`. 

> It actually makes it more natural to use in the given example above because 
> “default unknown” could actually be used to provide compile-time 
> exhaustiveness checking for such a tuple pattern, whereas without being able 
> to use “unknown case” in a pattern you can’t write “case (unknown case, _)”.

The way `unknown case` enforces  compile-time exhaustiveness is by only 
matching unknown cases. The implementation may be more close to default by the 
virtue of being forced to go at the end of the switch statement now but that 
should not dictate the user experience. 

> 
> You still haven’t answered my question, though—what’s the use case for the 
> feature you propose?

My use case would be distinguishing between compile time known cases vs 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-04 Thread Xiaodi Wu via swift-evolution
On Thu, Jan 4, 2018 at 18:39 Cheyo J. Jimenez  wrote:

>
> On Jan 4, 2018, at 2:55 PM, Xiaodi Wu  wrote:
>
>
> On Thu, Jan 4, 2018 at 17:15 Cheyo J. Jimenez  wrote:
>
>> On Jan 4, 2018, at 11:53 AM, Xiaodi Wu  wrote:
>>
>>
>> On Thu, Jan 4, 2018 at 13:46 Cheyo Jimenez  wrote:
>>
>>>
>>>
>>> On Jan 4, 2018, at 10:49 AM, Jordan Rose  wrote:
>>>
>>> I'll admit I hadn't thought of using "unknown default" (or "default
>>> unknown"). I don't think that's terrible, but I mildly prefer `unknown
>>> case` because it builds on the "pun" that enum elements are also defined
>>> using 'case'. If anything hits this part of the switch, it really will be
>>> an "unknown case", i.e. a statically-unknown enum element.
>>>
>>> To Cheyo's point, if this *were* to be a single token I'd probably
>>> spell it #unknown, like #available. Then we'd have `case #unknown:` and
>>> something that naturally expands to other pattern positions. I found that
>>> less aesthetically pleasing, though, and so a context-sensitive keyword
>>> seemed like the way to go.
>>>
>>> (For the record, though, I wouldn't describe `case _` as a special case
>>> of `default`. They do exactly the same thing, and `_` is a useful pattern
>>> in other contexts, so if anything the current `default` should be thought
>>> of as syntactic sugar for `case _`.)
>>>
>>>
>>> Can case _ be mixed with unknown case? How can we match all compile time
>>> known cases but exclude future cases?
>>>
>>
>> What’s your use case for that? That eliminates the possibility of
>> “unknown case” giving you compile-time warnings for subsequently added
>> cases, which was the entire purpose of adding the syntax in the first place.
>>
>>
>> I was thinking of a generalized `unknown case` pattern but that is out
>> of scope for this proposal.
>> 
>>
>>
>> switch excuse {
>>  case .eatenByPet :
>>//…
>>  unknown case:
>>// …
>>  case _:
>>// …
>>  }
>>
>>
>> Should there be something like `case *` that would capture all currently
>>> known cases during compile time? case * and case _ would be the same in
>>> exhaustive enums.
>>>
>>
>> This is why I was suggesting another pattern that only captures known
>> cases at compile time:
>>
>> switch excuse {
>>  case .eatenByPet :
>>//…
>>  case * : //  All cases captured at compile time.
>>// …
>>  unknown case:
>>// …
>>  }
>>
>
> Sorry, I don’t understand. However you spell it, what is your use case for
> this? The stated purpose of “unknown case” is to gain compile-time
> exhaustiveness testing, but this would not allow for that.
>
>
>
>
>
> switch (excuse, notifiedTeacherBeforeDeadline) {case (.eatenByPet, true):
>   // …case (.thoughtItWasDueNextWeek, true):
>   // …case (unknown case, true):
>   // …case (_, false):
>   // …}
>
>
> Im referring to the future direction section in the new PR
> .
> The above example if from there.
>
> I am fine with `unknown case` being required to be at the end of the
> switch for now.
>
> I think of `unknown case` as a pattern that only matches unknown cases no
> matter where on the switch it is.
>
> This is why I do not think that `default unknown` would work well once
> `unknown case` can be used a pattern.
>
> We can start a new thread on this if you’d like.
>

The reason I put forward “default unknown” is precisely because the
proposed feature *cannot* be used in a pattern and therefore seems more apt
as not a case.

It actually makes it more natural to use in the given example above because
“default unknown” could actually be used to provide compile-time
exhaustiveness checking for such a tuple pattern, whereas without being
able to use “unknown case” in a pattern you can’t write “case (unknown
case, _)”.

You still haven’t answered my question, though—what’s the use case for the
feature you propose?


>
>
>
>
>
>>
>>>
>>>
>>> I'll add these points to the "Alternatives Considered" section in the PR
>>> later today.
>>>
>>> Jordan
>>>
>>>
>>> On Jan 3, 2018, at 22:56, Xiaodi Wu  wrote:
>>>
>>> As has already been said, “case unknown” is source-breaking because it
>>> conflicts with any real cases named “unknown”; “\unknown” looks like a key
>>> path but isn’t, and I wonder if it would potentially conflict with existing
>>> key paths.
>>>
>>> In any case, my point was not to bikeshed the “unknown” part, but to ask
>>> whether any consideration had been made to have the feature presented as a
>>> flavor of default instead of a flavor of case.
>>>
>>> On Wed, Jan 3, 2018 at 23:57 Cheyo Jimenez  wrote:
>>>


 On Jan 3, 2018, at 6:52 PM, Xiaodi Wu via 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-04 Thread Cheyo J. Jimenez via swift-evolution

> On Jan 4, 2018, at 2:55 PM, Xiaodi Wu  wrote:
> 
> 
> On Thu, Jan 4, 2018 at 17:15 Cheyo J. Jimenez  > wrote:
>> On Jan 4, 2018, at 11:53 AM, Xiaodi Wu > > wrote:
>> 
>> 
>> On Thu, Jan 4, 2018 at 13:46 Cheyo Jimenez > > wrote:
>> 
>> 
>> On Jan 4, 2018, at 10:49 AM, Jordan Rose > > wrote:
>> 
>>> I'll admit I hadn't thought of using "unknown default" (or "default 
>>> unknown"). I don't think that's terrible, but I mildly prefer `unknown 
>>> case` because it builds on the "pun" that enum elements are also defined 
>>> using 'case'. If anything hits this part of the switch, it really will be 
>>> an "unknown case", i.e. a statically-unknown enum element.
>>> 
>>> To Cheyo's point, if this were to be a single token I'd probably spell it 
>>> #unknown, like #available. Then we'd have `case #unknown:` and something 
>>> that naturally expands to other pattern positions. I found that less 
>>> aesthetically pleasing, though, and so a context-sensitive keyword seemed 
>>> like the way to go.
>>> 
>>> (For the record, though, I wouldn't describe `case _` as a special case of 
>>> `default`. They do exactly the same thing, and `_` is a useful pattern in 
>>> other contexts, so if anything the current `default` should be thought of 
>>> as syntactic sugar for `case _`.)
>> 
>> Can case _ be mixed with unknown case? How can we match all compile time 
>> known cases but exclude future cases?
>> 
>> What’s your use case for that? That eliminates the possibility of “unknown 
>> case” giving you compile-time warnings for subsequently added cases, which 
>> was the entire purpose of adding the syntax in the first place.
> 
> I was thinking of a generalized `unknown case` pattern but that is out of 
> scope for this proposal. 
> 
>  
> 
> switch excuse {
>  case .eatenByPet :
>//…
>  unknown case:
>// …
>  case _:
>// …
>  }
> 
>> 
>> Should there be something like `case *` that would capture all currently 
>> known cases during compile time? case * and case _ would be the same in 
>> exhaustive enums. 
> 
> This is why I was suggesting another pattern that only captures known cases 
> at compile time:
> 
> switch excuse {
>  case .eatenByPet :
>//…
>  case * : //  All cases captured at compile time. 
>// …
>  unknown case:
>// …
>  }
> 
> Sorry, I don’t understand. However you spell it, what is your use case for 
> this? The stated purpose of “unknown case” is to gain compile-time 
> exhaustiveness testing, but this would not allow for that.




switch (excuse, notifiedTeacherBeforeDeadline) {
case (.eatenByPet, true):
  // …
case (.thoughtItWasDueNextWeek, true):
  // …
case (unknown case, true):
  // …
case (_, false):
  // …
}

Im referring to the future direction section in the new PR 
.
 The above example if from there. 

I am fine with `unknown case` being required to be at the end of the switch for 
now. 

I think of `unknown case` as a pattern that only matches unknown cases no 
matter where on the switch it is.

This is why I do not think that `default unknown` would work well once `unknown 
case` can be used a pattern.

We can start a new thread on this if you’d like. 

 

> 
> 
> 
>> 
>> 
>>> 
>>> I'll add these points to the "Alternatives Considered" section in the PR 
>>> later today.
>>> 
>>> Jordan
>>> 
>>> 
 On Jan 3, 2018, at 22:56, Xiaodi Wu > wrote:
 
 As has already been said, “case unknown” is source-breaking because it 
 conflicts with any real cases named “unknown”; “\unknown” looks like a key 
 path but isn’t, and I wonder if it would potentially conflict with 
 existing key paths.
 
 In any case, my point was not to bikeshed the “unknown” part, but to ask 
 whether any consideration had been made to have the feature presented as a 
 flavor of default instead of a flavor of case.
 
 On Wed, Jan 3, 2018 at 23:57 Cheyo Jimenez > wrote:
 
 
 On Jan 3, 2018, at 6:52 PM, Xiaodi Wu via swift-evolution 
 > wrote:
 
> This is a very nice revision. One bikeshedding thought:
> 
> Since "unknown case" is presented as a special kind of "default", can't 
> be mixed with "default", and can't be used in case patterns, why not 
> "default unknown" (or "unknown default") instead of "unknown case"?
 
 `case _ :` is already a special case of default. 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-04 Thread Xiaodi Wu via swift-evolution
On Thu, Jan 4, 2018 at 17:15 Cheyo J. Jimenez  wrote:

> On Jan 4, 2018, at 11:53 AM, Xiaodi Wu  wrote:
>
>
> On Thu, Jan 4, 2018 at 13:46 Cheyo Jimenez  wrote:
>
>>
>>
>> On Jan 4, 2018, at 10:49 AM, Jordan Rose  wrote:
>>
>> I'll admit I hadn't thought of using "unknown default" (or "default
>> unknown"). I don't think that's terrible, but I mildly prefer `unknown
>> case` because it builds on the "pun" that enum elements are also defined
>> using 'case'. If anything hits this part of the switch, it really will be
>> an "unknown case", i.e. a statically-unknown enum element.
>>
>> To Cheyo's point, if this *were* to be a single token I'd probably spell
>> it #unknown, like #available. Then we'd have `case #unknown:` and something
>> that naturally expands to other pattern positions. I found that less
>> aesthetically pleasing, though, and so a context-sensitive keyword seemed
>> like the way to go.
>>
>> (For the record, though, I wouldn't describe `case _` as a special case
>> of `default`. They do exactly the same thing, and `_` is a useful pattern
>> in other contexts, so if anything the current `default` should be thought
>> of as syntactic sugar for `case _`.)
>>
>>
>> Can case _ be mixed with unknown case? How can we match all compile time
>> known cases but exclude future cases?
>>
>
> What’s your use case for that? That eliminates the possibility of “unknown
> case” giving you compile-time warnings for subsequently added cases, which
> was the entire purpose of adding the syntax in the first place.
>
>
> I was thinking of a generalized `unknown case` pattern but that is out of
> scope for this proposal.
> 
>
>
> switch excuse {
>  case .eatenByPet :
>//…
>  unknown case:
>// …
>  case _:
>// …
>  }
>
>
> Should there be something like `case *` that would capture all currently
>> known cases during compile time? case * and case _ would be the same in
>> exhaustive enums.
>>
>
> This is why I was suggesting another pattern that only captures known
> cases at compile time:
>
> switch excuse {
>  case .eatenByPet :
>//…
>  case * : //  All cases captured at compile time.
>// …
>  unknown case:
>// …
>  }
>

Sorry, I don’t understand. However you spell it, what is your use case for
this? The stated purpose of “unknown case” is to gain compile-time
exhaustiveness testing, but this would not allow for that.



>
>>
>>
>> I'll add these points to the "Alternatives Considered" section in the PR
>> later today.
>>
>> Jordan
>>
>>
>> On Jan 3, 2018, at 22:56, Xiaodi Wu  wrote:
>>
>> As has already been said, “case unknown” is source-breaking because it
>> conflicts with any real cases named “unknown”; “\unknown” looks like a key
>> path but isn’t, and I wonder if it would potentially conflict with existing
>> key paths.
>>
>> In any case, my point was not to bikeshed the “unknown” part, but to ask
>> whether any consideration had been made to have the feature presented as a
>> flavor of default instead of a flavor of case.
>>
>> On Wed, Jan 3, 2018 at 23:57 Cheyo Jimenez  wrote:
>>
>>>
>>>
>>> On Jan 3, 2018, at 6:52 PM, Xiaodi Wu via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>> This is a very nice revision. One bikeshedding thought:
>>>
>>> Since "unknown case" is presented as a special kind of "default", can't
>>> be mixed with "default", and can't be used in case patterns, why not
>>> "default unknown" (or "unknown default") instead of "unknown case"?
>>>
>>>
>>> `case _ :` is already a special case of default.
>>> I’d rather have `case unknown :`
>>> `unknown case :` is weird because of the order of `case`.
>>>
>>> Another alternative is `case \unknown :`
>>> `\unknown` would also allow pattern matching.
>>>
>>>
>>>
>>>
>>>
>>> On Wed, Jan 3, 2018 at 8:05 PM, Jordan Rose via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
 On Jan 2, 2018, at 18:07, Jordan Rose  wrote:

 [Proposal:
 https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
 ]

 Whew! Thanks for your feedback, everyone. On the lighter side of
 feedback—naming things—it seems that most people seem to like '
 *@frozen*', and that does in fact have the connotations we want it to
 have. I like it too.

 More seriously, this discussion has convinced me that it's worth
 including what the proposal discusses as a *'future' case*. The key
 point that swayed me is that this can produce a *warning* when the
 switch is missing a case rather than an *error,* which both provides
 the necessary compiler feedback to update your code and allows your
 dependencies to continue compiling when you update to a newer SDK. I know
 people on both sides won't 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-04 Thread Cheyo J. Jimenez via swift-evolution

> On Jan 4, 2018, at 11:53 AM, Xiaodi Wu  wrote:
> 
> 
> On Thu, Jan 4, 2018 at 13:46 Cheyo Jimenez  > wrote:
> 
> 
> On Jan 4, 2018, at 10:49 AM, Jordan Rose  > wrote:
> 
>> I'll admit I hadn't thought of using "unknown default" (or "default 
>> unknown"). I don't think that's terrible, but I mildly prefer `unknown case` 
>> because it builds on the "pun" that enum elements are also defined using 
>> 'case'. If anything hits this part of the switch, it really will be an 
>> "unknown case", i.e. a statically-unknown enum element.
>> 
>> To Cheyo's point, if this were to be a single token I'd probably spell it 
>> #unknown, like #available. Then we'd have `case #unknown:` and something 
>> that naturally expands to other pattern positions. I found that less 
>> aesthetically pleasing, though, and so a context-sensitive keyword seemed 
>> like the way to go.
>> 
>> (For the record, though, I wouldn't describe `case _` as a special case of 
>> `default`. They do exactly the same thing, and `_` is a useful pattern in 
>> other contexts, so if anything the current `default` should be thought of as 
>> syntactic sugar for `case _`.)
> 
> Can case _ be mixed with unknown case? How can we match all compile time 
> known cases but exclude future cases?
> 
> What’s your use case for that? That eliminates the possibility of “unknown 
> case” giving you compile-time warnings for subsequently added cases, which 
> was the entire purpose of adding the syntax in the first place.

I was thinking of a generalized `unknown case` pattern but that is out of scope 
for this proposal. 

 

switch excuse {
 case .eatenByPet :
   //…
 unknown case:
   // …
 case _:
   // …
 }

> 
> Should there be something like `case *` that would capture all currently 
> known cases during compile time? case * and case _ would be the same in 
> exhaustive enums. 

This is why I was suggesting another pattern that only captures known cases at 
compile time:

switch excuse {
 case .eatenByPet :
   //…
 case * : //  All cases captured at compile time. 
   // …
 unknown case:
   // …
 }

> 
> 
>> 
>> I'll add these points to the "Alternatives Considered" section in the PR 
>> later today.
>> 
>> Jordan
>> 
>> 
>>> On Jan 3, 2018, at 22:56, Xiaodi Wu >> > wrote:
>>> 
>>> As has already been said, “case unknown” is source-breaking because it 
>>> conflicts with any real cases named “unknown”; “\unknown” looks like a key 
>>> path but isn’t, and I wonder if it would potentially conflict with existing 
>>> key paths.
>>> 
>>> In any case, my point was not to bikeshed the “unknown” part, but to ask 
>>> whether any consideration had been made to have the feature presented as a 
>>> flavor of default instead of a flavor of case.
>>> 
>>> On Wed, Jan 3, 2018 at 23:57 Cheyo Jimenez >> > wrote:
>>> 
>>> 
>>> On Jan 3, 2018, at 6:52 PM, Xiaodi Wu via swift-evolution 
>>> > wrote:
>>> 
 This is a very nice revision. One bikeshedding thought:
 
 Since "unknown case" is presented as a special kind of "default", can't be 
 mixed with "default", and can't be used in case patterns, why not "default 
 unknown" (or "unknown default") instead of "unknown case"?
>>> 
>>> `case _ :` is already a special case of default. 
>>> I’d rather have `case unknown :`
>>> `unknown case :` is weird because of the order of `case`. 
>>> 
>>> Another alternative is `case \unknown :`
>>> `\unknown` would also allow pattern matching. 
>>> 
>>> 
>>> 
 
 
 On Wed, Jan 3, 2018 at 8:05 PM, Jordan Rose via swift-evolution 
 > wrote:
> On Jan 2, 2018, at 18:07, Jordan Rose  > wrote:
> 
> [Proposal: 
> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>  
> ]
> 
> Whew! Thanks for your feedback, everyone. On the lighter side of 
> feedback—naming things—it seems that most people seem to like '@frozen', 
> and that does in fact have the connotations we want it to have. I like it 
> too.
> 
> More seriously, this discussion has convinced me that it's worth 
> including what the proposal discusses as a 'future' case. The key point 
> that swayed me is that this can produce a warning when the switch is 
> missing a case rather than an error, which both provides the necessary 
> compiler feedback to update your code and allows your dependencies to 
> 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-04 Thread Xiaodi Wu via swift-evolution
On Thu, Jan 4, 2018 at 13:46 Cheyo Jimenez  wrote:

>
>
> On Jan 4, 2018, at 10:49 AM, Jordan Rose  wrote:
>
> I'll admit I hadn't thought of using "unknown default" (or "default
> unknown"). I don't think that's terrible, but I mildly prefer `unknown
> case` because it builds on the "pun" that enum elements are also defined
> using 'case'. If anything hits this part of the switch, it really will be
> an "unknown case", i.e. a statically-unknown enum element.
>
> To Cheyo's point, if this *were* to be a single token I'd probably spell
> it #unknown, like #available. Then we'd have `case #unknown:` and something
> that naturally expands to other pattern positions. I found that less
> aesthetically pleasing, though, and so a context-sensitive keyword seemed
> like the way to go.
>
> (For the record, though, I wouldn't describe `case _` as a special case of
> `default`. They do exactly the same thing, and `_` is a useful pattern in
> other contexts, so if anything the current `default` should be thought of
> as syntactic sugar for `case _`.)
>
>
> Can case _ be mixed with unknown case? How can we match all compile time
> known cases but exclude future cases?
>

What’s your use case for that? That eliminates the possibility of “unknown
case” giving you compile-time warnings for subsequently added cases, which
was the entire purpose of adding the syntax in the first place.

Should be something like `case *` that would capture all currently known
> cases during compile time? case * and case _ would be the same in
> exhaustive enums.
>
>
>
> I'll add these points to the "Alternatives Considered" section in the PR
> later today.
>
> Jordan
>
>
> On Jan 3, 2018, at 22:56, Xiaodi Wu  wrote:
>
> As has already been said, “case unknown” is source-breaking because it
> conflicts with any real cases named “unknown”; “\unknown” looks like a key
> path but isn’t, and I wonder if it would potentially conflict with existing
> key paths.
>
> In any case, my point was not to bikeshed the “unknown” part, but to ask
> whether any consideration had been made to have the feature presented as a
> flavor of default instead of a flavor of case.
>
> On Wed, Jan 3, 2018 at 23:57 Cheyo Jimenez  wrote:
>
>>
>>
>> On Jan 3, 2018, at 6:52 PM, Xiaodi Wu via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> This is a very nice revision. One bikeshedding thought:
>>
>> Since "unknown case" is presented as a special kind of "default", can't
>> be mixed with "default", and can't be used in case patterns, why not
>> "default unknown" (or "unknown default") instead of "unknown case"?
>>
>>
>> `case _ :` is already a special case of default.
>> I’d rather have `case unknown :`
>> `unknown case :` is weird because of the order of `case`.
>>
>> Another alternative is `case \unknown :`
>> `\unknown` would also allow pattern matching.
>>
>>
>>
>>
>>
>> On Wed, Jan 3, 2018 at 8:05 PM, Jordan Rose via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> On Jan 2, 2018, at 18:07, Jordan Rose  wrote:
>>>
>>> [Proposal:
>>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>>> ]
>>>
>>> Whew! Thanks for your feedback, everyone. On the lighter side of
>>> feedback—naming things—it seems that most people seem to like '*@frozen*',
>>> and that does in fact have the connotations we want it to have. I like it
>>> too.
>>>
>>> More seriously, this discussion has convinced me that it's worth
>>> including what the proposal discusses as a *'future' case*. The key
>>> point that swayed me is that this can produce a *warning* when the
>>> switch is missing a case rather than an *error,* which both provides
>>> the necessary compiler feedback to update your code and allows your
>>> dependencies to continue compiling when you update to a newer SDK. I know
>>> people on both sides won't be 100% satisfied with this, but does it seem
>>> like a reasonable compromise?
>>>
>>> The next question is how to spell it. I'm leaning towards `unexpected
>>> case:`, which (a) is backwards-compatible, and (b) also handles "private
>>> cases", either the fake kind that you can do in C (as described in the
>>> proposal), or some real feature we might add to Swift some day. `unknown
>>> case:` isn't bad either.
>>>
>>> I too would like to just do `unknown:` or `unexpected:` but that's
>>> technically a source-breaking change:
>>>
>>> switch foo {
>>> case bar:
>>>   unknown:
>>>   while baz() {
>>> while garply() {
>>>   if quux() {
>>> break unknown
>>>   }
>>> }
>>>   }
>>> }
>>>
>>>
>>> Another downside of the `unexpected case:` spelling is that it doesn't
>>> work as part of a larger pattern. I don't have a good answer for that one,
>>> but perhaps it's acceptable for now.
>>>
>>> I'll write up a revision of the proposal soon and make sure the core
>>> team gets my recommendation when 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-04 Thread Jordan Rose via swift-evolution


> On Jan 4, 2018, at 11:45, Cheyo Jimenez  wrote:
> 
> 
> 
> On Jan 4, 2018, at 10:49 AM, Jordan Rose  > wrote:
> 
>> I'll admit I hadn't thought of using "unknown default" (or "default 
>> unknown"). I don't think that's terrible, but I mildly prefer `unknown case` 
>> because it builds on the "pun" that enum elements are also defined using 
>> 'case'. If anything hits this part of the switch, it really will be an 
>> "unknown case", i.e. a statically-unknown enum element.
>> 
>> To Cheyo's point, if this were to be a single token I'd probably spell it 
>> #unknown, like #available. Then we'd have `case #unknown:` and something 
>> that naturally expands to other pattern positions. I found that less 
>> aesthetically pleasing, though, and so a context-sensitive keyword seemed 
>> like the way to go.
>> 
>> (For the record, though, I wouldn't describe `case _` as a special case of 
>> `default`. They do exactly the same thing, and `_` is a useful pattern in 
>> other contexts, so if anything the current `default` should be thought of as 
>> syntactic sugar for `case _`.)
> 
> Can case _ be mixed with unknown case? How can we match all compile time 
> known cases but exclude future cases? Should be something like `case *` that 
> would capture all currently known cases during compile time? case * and case 
> _ would be the same in exhaustive enums. 

I thought about this, but I couldn’t think of a use case for it. You won’t get 
any exhaustivity checks, and if you recompile the app you silently get 
different behavior. That didn’t seem like a good idea to me.

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-04 Thread Cheyo Jimenez via swift-evolution


> On Jan 4, 2018, at 10:49 AM, Jordan Rose  wrote:
> 
> I'll admit I hadn't thought of using "unknown default" (or "default 
> unknown"). I don't think that's terrible, but I mildly prefer `unknown case` 
> because it builds on the "pun" that enum elements are also defined using 
> 'case'. If anything hits this part of the switch, it really will be an 
> "unknown case", i.e. a statically-unknown enum element.
> 
> To Cheyo's point, if this were to be a single token I'd probably spell it 
> #unknown, like #available. Then we'd have `case #unknown:` and something that 
> naturally expands to other pattern positions. I found that less aesthetically 
> pleasing, though, and so a context-sensitive keyword seemed like the way to 
> go.
> 
> (For the record, though, I wouldn't describe `case _` as a special case of 
> `default`. They do exactly the same thing, and `_` is a useful pattern in 
> other contexts, so if anything the current `default` should be thought of as 
> syntactic sugar for `case _`.)

Can case _ be mixed with unknown case? How can we match all compile time known 
cases but exclude future cases? Should be something like `case *` that would 
capture all currently known cases during compile time? case * and case _ would 
be the same in exhaustive enums. 


> 
> I'll add these points to the "Alternatives Considered" section in the PR 
> later today.
> 
> Jordan
> 
> 
>> On Jan 3, 2018, at 22:56, Xiaodi Wu  wrote:
>> 
>> As has already been said, “case unknown” is source-breaking because it 
>> conflicts with any real cases named “unknown”; “\unknown” looks like a key 
>> path but isn’t, and I wonder if it would potentially conflict with existing 
>> key paths.
>> 
>> In any case, my point was not to bikeshed the “unknown” part, but to ask 
>> whether any consideration had been made to have the feature presented as a 
>> flavor of default instead of a flavor of case.
>> 
>>> On Wed, Jan 3, 2018 at 23:57 Cheyo Jimenez  wrote:
>>> 
>>> 
 On Jan 3, 2018, at 6:52 PM, Xiaodi Wu via swift-evolution 
  wrote:
 
 This is a very nice revision. One bikeshedding thought:
 
 Since "unknown case" is presented as a special kind of "default", can't be 
 mixed with "default", and can't be used in case patterns, why not "default 
 unknown" (or "unknown default") instead of "unknown case"?
>>> 
>>> `case _ :` is already a special case of default. 
>>> I’d rather have `case unknown :`
>>> `unknown case :` is weird because of the order of `case`. 
>>> 
>>> Another alternative is `case \unknown :`
>>> `\unknown` would also allow pattern matching. 
>>> 
>>> 
>>> 
 
 
 On Wed, Jan 3, 2018 at 8:05 PM, Jordan Rose via swift-evolution 
  wrote:
>> On Jan 2, 2018, at 18:07, Jordan Rose  wrote:
>> 
>> [Proposal: 
>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md]
>> 
>> Whew! Thanks for your feedback, everyone. On the lighter side of 
>> feedback—naming things—it seems that most people seem to like '@frozen', 
>> and that does in fact have the connotations we want it to have. I like 
>> it too.
>> 
>> More seriously, this discussion has convinced me that it's worth 
>> including what the proposal discusses as a 'future' case. The key point 
>> that swayed me is that this can produce a warning when the switch is 
>> missing a case rather than an error, which both provides the necessary 
>> compiler feedback to update your code and allows your dependencies to 
>> continue compiling when you update to a newer SDK. I know people on both 
>> sides won't be 100% satisfied with this, but does it seem like a 
>> reasonable compromise?
>> 
>> The next question is how to spell it. I'm leaning towards `unexpected 
>> case:`, which (a) is backwards-compatible, and (b) also handles "private 
>> cases", either the fake kind that you can do in C (as described in the 
>> proposal), or some real feature we might add to Swift some day. `unknown 
>> case:` isn't bad either.
>> 
>> I too would like to just do `unknown:` or `unexpected:` but that's 
>> technically a source-breaking change:
>> 
>> switch foo {
>> case bar:
>>   unknown:
>>   while baz() {
>> while garply() {
>>   if quux() {
>> break unknown
>>   }
>> }
>>   }
>> }
>> 
>> Another downside of the `unexpected case:` spelling is that it doesn't 
>> work as part of a larger pattern. I don't have a good answer for that 
>> one, but perhaps it's acceptable for now.
>> 
>> I'll write up a revision of the proposal soon and make sure the core 
>> team gets my recommendation when they discuss the results of the review.
>> 
>> ---
>> 
>> 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-04 Thread Jordan Rose via swift-evolution
I'll admit I hadn't thought of using "unknown default" (or "default unknown"). 
I don't think that's terrible, but I mildly prefer `unknown case` because it 
builds on the "pun" that enum elements are also defined using 'case'. If 
anything hits this part of the switch, it really will be an "unknown case", 
i.e. a statically-unknown enum element.

To Cheyo's point, if this were to be a single token I'd probably spell it 
#unknown, like #available. Then we'd have `case #unknown:` and something that 
naturally expands to other pattern positions. I found that less aesthetically 
pleasing, though, and so a context-sensitive keyword seemed like the way to go.

(For the record, though, I wouldn't describe `case _` as a special case of 
`default`. They do exactly the same thing, and `_` is a useful pattern in other 
contexts, so if anything the current `default` should be thought of as 
syntactic sugar for `case _`.)

I'll add these points to the "Alternatives Considered" section in the PR later 
today.

Jordan


> On Jan 3, 2018, at 22:56, Xiaodi Wu  wrote:
> 
> As has already been said, “case unknown” is source-breaking because it 
> conflicts with any real cases named “unknown”; “\unknown” looks like a key 
> path but isn’t, and I wonder if it would potentially conflict with existing 
> key paths.
> 
> In any case, my point was not to bikeshed the “unknown” part, but to ask 
> whether any consideration had been made to have the feature presented as a 
> flavor of default instead of a flavor of case.
> 
> On Wed, Jan 3, 2018 at 23:57 Cheyo Jimenez  > wrote:
> 
> 
> On Jan 3, 2018, at 6:52 PM, Xiaodi Wu via swift-evolution 
> > wrote:
> 
>> This is a very nice revision. One bikeshedding thought:
>> 
>> Since "unknown case" is presented as a special kind of "default", can't be 
>> mixed with "default", and can't be used in case patterns, why not "default 
>> unknown" (or "unknown default") instead of "unknown case"?
> 
> `case _ :` is already a special case of default. 
> I’d rather have `case unknown :`
> `unknown case :` is weird because of the order of `case`. 
> 
> Another alternative is `case \unknown :`
> `\unknown` would also allow pattern matching. 
> 
> 
> 
>> 
>> 
>> On Wed, Jan 3, 2018 at 8:05 PM, Jordan Rose via swift-evolution 
>> > wrote:
>>> On Jan 2, 2018, at 18:07, Jordan Rose >> > wrote:
>>> 
>>> [Proposal: 
>>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>>>  
>>> ]
>>> 
>>> Whew! Thanks for your feedback, everyone. On the lighter side of 
>>> feedback—naming things—it seems that most people seem to like '@frozen', 
>>> and that does in fact have the connotations we want it to have. I like it 
>>> too.
>>> 
>>> More seriously, this discussion has convinced me that it's worth including 
>>> what the proposal discusses as a 'future' case. The key point that swayed 
>>> me is that this can produce a warning when the switch is missing a case 
>>> rather than an error, which both provides the necessary compiler feedback 
>>> to update your code and allows your dependencies to continue compiling when 
>>> you update to a newer SDK. I know people on both sides won't be 100% 
>>> satisfied with this, but does it seem like a reasonable compromise?
>>> 
>>> The next question is how to spell it. I'm leaning towards `unexpected 
>>> case:`, which (a) is backwards-compatible, and (b) also handles "private 
>>> cases", either the fake kind that you can do in C (as described in the 
>>> proposal), or some real feature we might add to Swift some day. `unknown 
>>> case:` isn't bad either.
>>> 
>>> I too would like to just do `unknown:` or `unexpected:` but that's 
>>> technically a source-breaking change:
>>> 
>>> switch foo {
>>> case bar:
>>>   unknown:
>>>   while baz() {
>>> while garply() {
>>>   if quux() {
>>> break unknown
>>>   }
>>> }
>>>   }
>>> }
>>> 
>>> Another downside of the `unexpected case:` spelling is that it doesn't work 
>>> as part of a larger pattern. I don't have a good answer for that one, but 
>>> perhaps it's acceptable for now.
>>> 
>>> I'll write up a revision of the proposal soon and make sure the core team 
>>> gets my recommendation when they discuss the results of the review.
>>> 
>>> ---
>>> 
>>> I'll respond to a few of the more intricate discussions tomorrow, including 
>>> the syntax of putting a new declaration inside the enum rather than 
>>> outside. Thank you again, everyone, and happy new year!
>> 
>> I ended up doing these in the opposite order, writing up the new proposal 
>> first and not yet responding to the discussion that's further out. You can 
>> read 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-03 Thread Howard Lovatt via swift-evolution
Despite having suggested the @version syntax I do agree with people that have 
said any @annotation is both a burden on the programmer and severely reduces 
readability. 

Therefore a 4th option, carrying on from the numbering in my previous email is:

  4. The compiler issues a description of the public enums in a module. 
Application code that uses the enums knows what version of the enum they were 
compiled against. When the application launches the runtime writes a 
translation between the module enum and the application enum and vice versa. 
When an enum goes into or comes out of the application code to/from the module 
code it goes through the translation functions. EG:

// Module version 1. 
public enum E {
case A, B, C
}
...
switch e {
case A: a()
default: d() // Could alternatively have cases B and C instead of default. 
unknown case: u() // Must have unknown case for a public enum. 
}

// Application code compiled against module version 1. 
// Stored in the code is the description of E having cases A, B, and C. 
switch e {
case A: a()
default: d() // Could alternatively have cases B and C instead of default. 
unknown case: u() // Must have unknown case for a public enum. 
}

The translation functions in each direction are trivial since the two enums 
match and therefore have the same numbering and the same number range. 

Now the module is changed. 

// Module version 2.
public enum E {
case A, C, D // B deleted and D added. 
}
...
// switch as before but now D calls d() and B calls u(). Previously B 
called d() but since B is deleted it is now an unknown case. 

The translation between module 2 code and application compiled against 1 code 
is:

  Module 2 <—> Application 1
  A   <—> A
  U   <—   B
  C   <—> C
  D —> U

IE all the old cases, from the application, are translated into unknown on the 
module side and all the new cases, from the module, are translated to unknown 
on the application side. 

This way neither the module programmer nor the application programmer has to 
version their code since the runtime provides the translation. 

It is source breaking however, since all switches of public enums require an 
unknown case both in the module code and application code. 

-- Howard. 

> On 3 Jan 2018, at 3:54 am, Jason Merchant via swift-evolution 
>  wrote:
> 
> Is it hard to imagine that most everyone can get what they want and keep the 
> syntax clean and streamlined at the same time? Without any "@" signs or other 
> compiler hints?
> 
>> "Rather, we are how to enable the vendor of a nonexhaustive enum to add new 
>> cases without breaking binaries compiled against previous versions"
> 
> When an enum changes, and the change causes the code to break, the user can 
> be presented with migration options from an automated IDE tool. In what 
> specific way does this not solve the issue about having to upgrade your code 
> when using someone else's code library? This very notion implies your 
> disgruntled about doing work when things are upgraded, is that really what 
> this fuss is all about?
> 
> A well written language interpreter and auto-tooling IDE would not need hints 
> embedded in the code syntax itself. Migration hints from version to version 
> should not be a part of either the past or future version of the code library.
> 
> ...
> 
> I don't expect the community to agree on language grammar, but the common 
> sense here on how to achieve the intended goals seems to be out of wack.
> 
> If someone can present a clear logical statement as to how an automated 
> migration tool behind the scenes in the IDE to handle all your versioning 
> worries, does not make this whole discussion about adding more convoluted 
> syntax additions irrelevant, I'd love to hear it.
> 
> ___
> 
> Sincerely,
> Jason
> 
> 
> 
> 
> 
> 
>> On Tue, Jan 2, 2018 at 12:36 PM, Xiaodi Wu  wrote:
>>> On Tue, Jan 2, 2018 at 12:11 PM, Jason Merchant via swift-evolution 
>>>  wrote:
>> 
>>> I think this whole thing has been unnecessarily convoluted. As a result, 
>>> the majority of the replies are rabbit holes.
>>> 
>>> In my opinion, the true root of the concept in question is as follows:
>>> 
>>> A list of something is desired:
>>> 1 - Pancake
>>> 2 - Waffle
>>> 3 - Juice
>>> 
>>> Developer wishes to be able to:
>>> A) Add new things to the list of choices in the future as they come up with 
>>> new ideas
>>> B) Sometimes select one of the choices to be chosen as the normal choice if 
>>> no choice is made by the user
>>> 
>>> A and B are separate desires. In some circumstances a developer may want to 
>>> add a new choice and make it the normal choice when there was no normal 
>>> choice was clarified before.
>> 
>> I don't think this is an accurate summary of the 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-03 Thread Jason Merchant via swift-evolution
Is it hard to imagine that most everyone can get what they want and keep
the syntax clean and streamlined at the same time? Without any "@" signs or
other compiler hints?

"Rather, we are how to enable the vendor of a nonexhaustive enum to add new
> cases without breaking binaries compiled against previous versions"


When an enum changes, and the change causes the code to break, the user can
be presented with migration options from an automated IDE tool. In what
specific way does this not solve the issue about having to upgrade your
code when using someone else's code library? This very notion implies your
disgruntled about doing work when things are upgraded, is that really what
this fuss is all about?

A well written language interpreter and auto-tooling IDE would not need
hints embedded in the code syntax itself. Migration hints from version to
version should not be a part of either the past or future version of the
code library.

...

I don't expect the community to agree on language grammar, but the common
sense here on how to achieve the intended goals seems to be out of wack.

If someone can present a clear logical statement as to how an automated
migration tool behind the scenes in the IDE to handle all your versioning
worries, does not make this whole discussion about adding more convoluted
syntax additions irrelevant, I'd love to hear it.

___

Sincerely,
Jason






On Tue, Jan 2, 2018 at 12:36 PM, Xiaodi Wu  wrote:

> On Tue, Jan 2, 2018 at 12:11 PM, Jason Merchant via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> I think this whole thing has been unnecessarily convoluted. As a result,
>> the majority of the replies are rabbit holes.
>>
>> In my opinion, the true root of the concept in question is as follows:
>>
>> *A list of something is desired:*
>> 1 - Pancake
>> 2 - Waffle
>> 3 - Juice
>>
>> *Developer wishes to be able to:*
>> *A)* Add new things to the list of choices in the future as they come up
>> with new ideas
>> *B)* Sometimes select one of the choices to be chosen as the normal
>> choice if no choice is made by the user
>>
>> A and B are *separate desires*. In some circumstances a developer may
>> want to add a new choice and make it the normal choice when there was no
>> normal choice was clarified before.
>>
>
> I don't think this is an accurate summary of the problem being tackled
> here. Rather, we are how to enable the vendor of a nonexhaustive enum to
> add new cases without breaking binaries compiled against previous versions.
> There is little here to do with what a "default" should be. Indeed, it is
> an explicit design decision of Swift not to support types having an
> implicit default value.
>
>
>> 
>>
>> *Part 2:*
>>
>> After this simple desire is clear, there should be two discussions:
>> *A)* In a text only coding language, what would we like the syntax to
>> look like? (Without regard to past-bias. What should it really be, forget
>> what mistaken design choices were made in Swift in the past)
>> *B)* How do we approach making this happen behind the scenes?
>>
>> *Bonus:* Given that some of us have changed our approach to programming
>> significantly beyond text based coding, and into more dynamic mediums of
>> programming in other niches, and even here and there in Xcode - I would
>> recommend considering how the IDE would show a modern version of this
>> concept. I feel too often that Swift design syntax has a *lack of
>> awareness between the distinctions of what the IDE should do, as opposed to
>> what the syntax of the language should be*, and what should be handled
>> behind the scenes by automated tooling.
>>
>> _
>>
>> *My opinion*, in answering the above questions is in preference to a
>> simple easy to read and write syntax, something like the following:
>>
>> choices Breakfast {
>> Pancake, *Waffle*, Juice
>> }
>>
>> If a "default" choice is desired, it is obvious to me that I would select
>> the choice from the IDE, and it would be visually indicated that it was the
>> default.
>>
>> When changes occur, whether new choices are added, old ones are removed
>> or changed, or a default is added, changed, or removed - a behind the
>> scenes automated tool analyzes the changes and presents migration options
>> through the IDE.
>>
>> _
>>
>> Sincerely,
>> Jason
>>
>>
>>>
>>
>> ___
>> 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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Goffredo Marocchi via swift-evolution
This is not what I am saying.

Change X helps use case A, but unnecessarily removes feature important (and 
like argument labels for everything quite Swift defining, but alas...) for use 
case B.

What I am saying is that before merging change X we should figure out what is 
needed (change Y) to ensure that use case B is not harmed while we do also help 
use case A.

Use case A being binary frameworks shipped by the OS and use case B being 
everything else... :).

Change X being the current proposal.

Change Y being the feature(s) needed to be added to X to ensure X’ helps use 
case A without removing the functionality use case B relies on.

Sent from my iPhone

> On 3 Jan 2018, at 02:01, Xiaodi Wu  wrote:
> 
>> On Tue, Jan 2, 2018 at 7:02 PM, Goffredo Marocchi  wrote:
>> 
>>> On 3 Jan 2018, at 00:38, Xiaodi Wu via swift-evolution 
>>>  wrote:
>>> 
 On Tue, Jan 2, 2018 at 4:31 PM, Jonathan Hull  wrote:
 I think there are a couple of different definitions running around, and 
 that is confusing things.
 
 In my mind, ‘unexpected:’ catches only cases which were unknown at compile 
 time. Adding cases to an enum *should* be a source-breaking change. That 
 is the whole point of this.  We should have to update the switch (either 
 by handling new case explicitly, or by adding default) before successfully 
 compiling.  What ‘unexpected:’ protects against are changes to a linked 
 binary (e.g. iOS) that are now vending cases we didn’t know about when we 
 were compiled.
 
 I’ll say it again… framing this idea as one of exhaustiveness is really 
 confusing.  Enums should just always be exhaustive in swift.  There may be 
 cases where we need to use ‘unexpected:’ to handle unexpected/future cases 
 exhaustively.  If we annotate an enum as @frozen, then we won’t need to do 
 that to be exhaustive because we know it won’t change out from under us.  
 Always exhaustive. Much less confusing…
 
 Thanks,
 Jon
>>> 
>>> I think, then, you fundamentally disagree with the starting premise of the 
>>> proposal, which is specifically the addition of nonexhaustive enums to the 
>>> language, and making them the default sort of enum so that adding cases *is 
>>> not* a source-breaking change. If your whole purpose is to change the 
>>> proposal so that adding cases will _always_ be a source-breaking change and 
>>> enums are _never_ nonexhaustive, then I'm not sure how to proceed in the 
>>> discussion as we're working towards diametrically opposite goals.
>> 
>> The main issue is a resilience issue and it mainly affects binary frameworks 
>> the app links with at runtime and does not package them (read mostly Apple 
>> ones for the moment)... the fact that enum changes are source breaking is 
>> the whole entire point of swift’s enum and a best practice warning to always 
>> have turned on even before with Objective-C. Our goal, and yours goal should 
>> be the one and the same too IMHO, is not to throw the proverbial baby out 
>> with the bath water.
>> 
>> We should look for a solution that allows what Apple and OS framework 
>> authors need and also what is best for app developers and if we need 
>> something to do this we pause this proposal until that something is ready 
>> and merged.
>> 
> 
> Hmm, I think indeed we disagree fundamentally on what this proposal is about, 
> or the desired end goal.
> 
> If I understand correctly, *your* end goal is simply to enable something like 
> `@_fixed_layout` for enums, an optimization hint to allow binary frameworks 
> to add cases without being shipped with apps. You want no semantic changes to 
> how enums work.
> 
> *My* understand of this proposals goal--and I support it--is that it takes 
> this ABI compatibility problem as a starting point and discovers that there 
> are fundamentally two semantic categories of enums, ones that are necessarily 
> exhaustive (there's either something or nothing for an Optional value, there 
> are three possible comparison results for comparable types, there are four 
> sides to a rectangular window, etc.) and ones that are not. It discovers 
> that, empirically, most enums are nonexhaustive, and proposes changes to the 
> grammar so that Swift distinguishes between these two so as to prompt 
> developers to deal with the issue of nonexhaustiveness where the semantics 
> require it. The goal, then, is to introduce new spellings and semantics to 
> distinguish between two different flavors of enum. Like `open` vs. `public` 
> for classes, this has implications for ABI compatibility but isn't just about 
> ABI compatibility.
> 
> I was laboring under the idea that we were working to make such a 
> wide-ranging change as ergonomic as possible, but it seems like you and Jon 
> do not want such a change at all.
> 
>>> 
> On Jan 2, 2018, at 1:41 PM, Xiaodi Wu via swift-evolution 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Xiaodi Wu via swift-evolution
On Tue, Jan 2, 2018 at 8:25 PM, Matthew Johnson 
wrote:

>
> On Jan 2, 2018, at 3:41 PM, Xiaodi Wu  wrote:
>
> On Tue, Jan 2, 2018 at 3:27 PM, Kevin Nattinger 
> wrote:
>
>> [...]
>>
>> in what other circumstances do we insist that the compiler inform the end
>>> user about future additions to the API at compile time?
>>>
>>>
>>> This isn’t a request for the compiler to inform the user about future
>>> additions to an API.  It is a request to validate the compiler’s knowledge
>>> of the *current* state of an API with the *current* state of the source
>>> code.
>>>
>>
>> Well, it's of course impossible to inform the user about future
>> additions, so that's poorly phrased on my part. It's about the compiler
>> informing the end user about *new* additions, part of the *current* state
>> of the API, that have cropped up since the user last revised the code when
>> the API was in a *previous* state (or, indistinguishably, members of which
>> a user is unaware regardless of the temporal sequence of when such members
>> were added). In what other circumstances do we insist that the compiler
>> perform this service?
>>
>>
>> Enums. That's literally how they work today. You are arguing in favor of
>> actively removing compiler-aided correctness.
>>
>> There's also protocol requirements
>>
>
> No, that's now how enums work today, and it's not how protocol
> requirements work today. Enums today are all semantically exhaustive; if a
> case is added in a later version of a library, it's semantically a
> *different* enum type that happens to share the same name. Not considering
> all the cases of an exhaustive enum is an _error_, not a _warning_, because
> there is no basis on which to proceed. This will not change with the
> proposal. Likewise, adding a protocol requirement without a default
> implementation is source-breaking. The result is a compiler _error_.
>
> The question is, what non-source breaking API additions today cause the
> compiler to inform the end user of such additions?
>
>
> Posing the question this way takes it as a given that adding a case to a
> resilient enum is non-source breaking with a full stop.
>

Ah, yes. As I wrote in an earlier email in reply to Jon and others, it
seems we have a fundamental difference here. I take it as a given, full
stop, that this is what we are setting out to do. If it is not, then we are
trying to design with different end goals in mind.

The position of everyone asking for something like `future` / `unknown` as
> an alternative to `default` is exactly that this should not be the case.
> Instead, adding a case should always be binary compatible and should be
> source compatible by default, but authors should have the ability to opt-in
> to making case additions be source-breaking for individual switch
> statements.
>
> When you view it this way we are not asking the compiler to inform us of a
> non-source breaking addition.  We are asking the compiler to treat an
> addition as source breaking in a specific context.
>
> The answer is: none whatsoever. Not new methods or properties on a type,
> not even new protocol requirements that have a default implementation.
>
>
> and, arguably, deprecated methods with a proper message ("use foo
>> instead").
>>
>
>
>
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Matthew Johnson via swift-evolution

> On Jan 2, 2018, at 2:09 PM, Xiaodi Wu  wrote:
> 
> On Tue, Jan 2, 2018 at 1:46 PM, Matthew Johnson  > wrote:
> 
> 
> Sent from my iPad
> 
> On Jan 2, 2018, at 12:48 PM, Xiaodi Wu  > wrote:
> 
>> On Tue, Jan 2, 2018 at 9:38 AM, Matthew Johnson via swift-evolution 
>> > wrote:
>> 
>> 
>> Sent from my iPad
>> 
>> On Jan 1, 2018, at 11:47 PM, Chris Lattner > > wrote:
>> 
 On Dec 31, 2017, at 12:14 PM, Matthew Johnson via swift-evolution 
 > wrote:
 
 I agree that we need a solution to the problem described.  I also agree 
 that non-exhaustive is most in keeping with the overall design of Swift at 
 module boundaries.  However, I believe this proposal should be modified 
 before being accepted
>>> 
>>> Thanks for writing this up - you’ve explained a common concern in an 
>>> interesting way:
>>> 
 This is likely to be a relatively rare need mostly encountered by 3rd 
 party libraries but it will happen.  When it does happen it would be 
 really unfortunate to be forced to use a `default` clause rather than 
 something like a `future` clause which will produce an error when compiled 
 against an SDK where the enum includes cases that are not covered.  I can 
 imagine cases where this catch-all case would need to do something other 
 than abort the program so I do not like the `switch!` suggestion that has 
 been discussed.  The programmer should still be responsible for 
 determining the behavior of unknown cases.
>>> ..
 While library authors have a legitimate need to reserve the right to 
 introduce new cases for some enums this need can be met without taking 
 away a useful tool for generating static compiler errors when code does 
 not align with intent (in this case, the intent being to cover all known 
 cases).  Switch statements working with these kinds of enums should be 
 required to cover unknown cases but should be able to do so while still 
 being statically checked with regards to known cases.  
>>> 
>>> I think that this could be the crux of some major confusion, the root of 
>>> which is the difference between source packages and binary packages that 
>>> are updated outside your control (e.g. the OS, or a dynamic library that is 
>>> updated independently of your app like a 3rd party plugin).  Consider:
>>> 
>>> 1) When dealing with independently updated binary packages, your code *has* 
>>> to implement some behavior for unexpected cases if the enum is 
>>> non-exhaustive.  It isn’t acceptable to not handle that case, and it isn’t 
>>> acceptable to abort because then your app will start crashing when a new OS 
>>> comes out. You have to build some sort of fallback into your app.
>>> 
>>> 2) When dealing with a source package that contributes to your app (e.g. 
>>> through SwiftPM), *YOU* control when you update that package, and therefore 
>>> it is entirely reasonable to exhaustively handle enums even if that package 
>>> owner didn’t “intend” for them to be exhaustive.  When *you* chose to 
>>> update the package, you get the “unhandled case” error, and you have 
>>> maximal “knowability” about the package’s behavior.
>>> 
>>> 
>>> It seems that your concern stems from the fact that the feature as proposed 
>>> is aligned around module boundaries, and therefore overly punishes source 
>>> packages like #2.  I hope you agree that in case #1, that the feature as 
>>> proposed is the right and only thing we can do: you really do have to 
>>> handle unknown future cases somehow.
>>> 
>>> If I’m getting this right, then maybe there is a variant of the proposal 
>>> that ties the error/warning behavior to whether or not a module is a source 
>>> module vs a binary module.  The problem with that right now is that we have 
>>> no infrastructure in the language to know this…
>> 
>> Hi Chris, thanks for your reply.
>> 
>> The concern you describe isn’t exactly what I was describing but it is 
>> related.  John McCall recently posted a sketch of a solution to the concern 
>> you describe which looked great to me.  I don’t have time to look up the 
>> link this morning but I think it was in this review thread.
>> 
>> The actual concern I am describing is where a 3rd party library (or app) 
>> wants to switch over a non-exhaustive enum provided by a module that is a 
>> binary (not source) dependency.  The author of the 3rd party library may 
>> have a legitimate reason to switch over an enum despite the author of the 
>> binary module reserving the right to add additional cases.  
>> 
>> When this circumstance arises they will do it using the tools provided by 
>> the language.  Regardless of the final language 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Matthew Johnson via swift-evolution

> On Jan 2, 2018, at 3:41 PM, Xiaodi Wu  wrote:
> 
> On Tue, Jan 2, 2018 at 3:27 PM, Kevin Nattinger  > wrote:
> [...]
> 
>>> in what other circumstances do we insist that the compiler inform the end 
>>> user about future additions to the API at compile time?
>> 
>> This isn’t a request for the compiler to inform the user about future 
>> additions to an API.  It is a request to validate the compiler’s knowledge 
>> of the current state of an API with the current state of the source code. 
>> 
>> Well, it's of course impossible to inform the user about future additions, 
>> so that's poorly phrased on my part. It's about the compiler informing the 
>> end user about *new* additions, part of the *current* state of the API, that 
>> have cropped up since the user last revised the code when the API was in a 
>> *previous* state (or, indistinguishably, members of which a user is unaware 
>> regardless of the temporal sequence of when such members were added). In 
>> what other circumstances do we insist that the compiler perform this service?
> 
> Enums. That's literally how they work today. You are arguing in favor of 
> actively removing compiler-aided correctness.
> 
> There's also protocol requirements
> 
> No, that's now how enums work today, and it's not how protocol requirements 
> work today. Enums today are all semantically exhaustive; if a case is added 
> in a later version of a library, it's semantically a *different* enum type 
> that happens to share the same name. Not considering all the cases of an 
> exhaustive enum is an _error_, not a _warning_, because there is no basis on 
> which to proceed. This will not change with the proposal. Likewise, adding a 
> protocol requirement without a default implementation is source-breaking. The 
> result is a compiler _error_.
> 
> The question is, what non-source breaking API additions today cause the 
> compiler to inform the end user of such additions?

Posing the question this way takes it as a given that adding a case to a 
resilient enum is non-source breaking with a full stop.  The position of 
everyone asking for something like `future` / `unknown` as an alternative to 
`default` is exactly that this should not be the case.  Instead, adding a case 
should always be binary compatible and should be source compatible by default, 
but authors should have the ability to opt-in to making case additions be 
source-breaking for individual switch statements.  

When you view it this way we are not asking the compiler to inform us of a 
non-source breaking addition.  We are asking the compiler to treat an addition 
as source breaking in a specific context.

> The answer is: none whatsoever. Not new methods or properties on a type, not 
> even new protocol requirements that have a default implementation.
> 
> 
> and, arguably, deprecated methods with a proper message ("use foo instead").
> 
> 



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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Xiaodi Wu via swift-evolution
On Tue, Jan 2, 2018 at 7:02 PM, Goffredo Marocchi  wrote:

>
> On 3 Jan 2018, at 00:38, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Tue, Jan 2, 2018 at 4:31 PM, Jonathan Hull  wrote:
>
>> I think there are a couple of different definitions running around, and
>> that is confusing things.
>>
>> In my mind, ‘unexpected:’ catches only cases which were unknown at
>> compile time. Adding cases to an enum *should* be a source-breaking change.
>> That is the whole point of this.  We should have to update the switch
>> (either by handling new case explicitly, or by adding default) before
>> successfully compiling.  What ‘unexpected:’ protects against are changes to
>> a linked binary (e.g. iOS) that are now vending cases we didn’t know about
>> when we were compiled.
>>
>> I’ll say it again… framing this idea as one of exhaustiveness is really
>> confusing.  Enums should just always be exhaustive in swift.  There may be
>> cases where we need to use ‘unexpected:’ to handle unexpected/future cases
>> exhaustively.  If we annotate an enum as @frozen, then we won’t need to do
>> that to be exhaustive because we know it won’t change out from under us.
>> Always exhaustive. Much less confusing…
>>
>> Thanks,
>> Jon
>>
>
> I think, then, you fundamentally disagree with the starting premise of the
> proposal, which is specifically the addition of nonexhaustive enums to the
> language, and making them the default sort of enum so that adding cases *is
> not* a source-breaking change. If your whole purpose is to change the
> proposal so that adding cases will _always_ be a source-breaking change and
> enums are _never_ nonexhaustive, then I'm not sure how to proceed in the
> discussion as we're working towards diametrically opposite goals.
>
>
> The main issue is a resilience issue and it mainly affects binary
> frameworks the app links with at runtime and does not package them (read
> mostly Apple ones for the moment)... the fact that enum changes are source
> breaking is the whole entire point of swift’s enum and a best practice
> warning to always have turned on even before with Objective-C. Our goal,
> and yours goal should be the one and the same too IMHO, is not to throw the
> proverbial baby out with the bath water.
>
> We should look for a solution that allows what Apple and OS framework
> authors need and also what is best for app developers and if we need
> something to do this we pause this proposal until that something is ready
> and merged.
>
>
Hmm, I think indeed we disagree fundamentally on what this proposal is
about, or the desired end goal.

If I understand correctly, *your* end goal is simply to enable something
like `@_fixed_layout` for enums, an optimization hint to allow binary
frameworks to add cases without being shipped with apps. You want no
semantic changes to how enums work.

*My* understand of this proposals goal--and I support it--is that it takes
this ABI compatibility problem as a starting point and discovers that there
are fundamentally two semantic categories of enums, ones that are
necessarily exhaustive (there's either something or nothing for an Optional
value, there are three possible comparison results for comparable types,
there are four sides to a rectangular window, etc.) and ones that are not.
It discovers that, empirically, most enums are nonexhaustive, and proposes
changes to the grammar so that Swift distinguishes between these two so as
to prompt developers to deal with the issue of nonexhaustiveness where the
semantics require it. The goal, then, is to introduce new spellings and
semantics to distinguish between two different flavors of enum. Like `open`
vs. `public` for classes, this has implications for ABI compatibility but
isn't just about ABI compatibility.

I was laboring under the idea that we were working to make such a
wide-ranging change as ergonomic as possible, but it seems like you and Jon
do not want such a change at all.


> On Jan 2, 2018, at 1:41 PM, Xiaodi Wu via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> On Tue, Jan 2, 2018 at 3:27 PM, Kevin Nattinger 
>> wrote:
>>
>>> [...]
>>>
>>> in what other circumstances do we insist that the compiler inform the
 end user about future additions to the API at compile time?


 This isn’t a request for the compiler to inform the user about future
 additions to an API.  It is a request to validate the compiler’s knowledge
 of the *current* state of an API with the *current* state of the
 source code.

>>>
>>> Well, it's of course impossible to inform the user about future
>>> additions, so that's poorly phrased on my part. It's about the compiler
>>> informing the end user about *new* additions, part of the *current* state
>>> of the API, that have cropped up since the user last revised the code when
>>> the API was in a *previous* state (or, indistinguishably, members of which
>>> a 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Goffredo Marocchi via swift-evolution

> On 3 Jan 2018, at 00:38, Xiaodi Wu via swift-evolution 
>  wrote:
> 
>> On Tue, Jan 2, 2018 at 4:31 PM, Jonathan Hull  wrote:
>> I think there are a couple of different definitions running around, and that 
>> is confusing things.
>> 
>> In my mind, ‘unexpected:’ catches only cases which were unknown at compile 
>> time. Adding cases to an enum *should* be a source-breaking change. That is 
>> the whole point of this.  We should have to update the switch (either by 
>> handling new case explicitly, or by adding default) before successfully 
>> compiling.  What ‘unexpected:’ protects against are changes to a linked 
>> binary (e.g. iOS) that are now vending cases we didn’t know about when we 
>> were compiled.
>> 
>> I’ll say it again… framing this idea as one of exhaustiveness is really 
>> confusing.  Enums should just always be exhaustive in swift.  There may be 
>> cases where we need to use ‘unexpected:’ to handle unexpected/future cases 
>> exhaustively.  If we annotate an enum as @frozen, then we won’t need to do 
>> that to be exhaustive because we know it won’t change out from under us.  
>> Always exhaustive. Much less confusing…
>> 
>> Thanks,
>> Jon
> 
> I think, then, you fundamentally disagree with the starting premise of the 
> proposal, which is specifically the addition of nonexhaustive enums to the 
> language, and making them the default sort of enum so that adding cases *is 
> not* a source-breaking change. If your whole purpose is to change the 
> proposal so that adding cases will _always_ be a source-breaking change and 
> enums are _never_ nonexhaustive, then I'm not sure how to proceed in the 
> discussion as we're working towards diametrically opposite goals.

The main issue is a resilience issue and it mainly affects binary frameworks 
the app links with at runtime and does not package them (read mostly Apple ones 
for the moment)... the fact that enum changes are source breaking is the whole 
entire point of swift’s enum and a best practice warning to always have turned 
on even before with Objective-C. Our goal, and yours goal should be the one and 
the same too IMHO, is not to throw the proverbial baby out with the bath water.

We should look for a solution that allows what Apple and OS framework authors 
need and also what is best for app developers and if we need something to do 
this we pause this proposal until that something is ready and merged.

> 
>>> On Jan 2, 2018, at 1:41 PM, Xiaodi Wu via swift-evolution 
>>>  wrote:
>>> 
 On Tue, Jan 2, 2018 at 3:27 PM, Kevin Nattinger  
 wrote:
 [...]
 
>>> in what other circumstances do we insist that the compiler inform the 
>>> end user about future additions to the API at compile time?
>> 
>> This isn’t a request for the compiler to inform the user about future 
>> additions to an API.  It is a request to validate the compiler’s 
>> knowledge of the current state of an API with the current state of the 
>> source code. 
> 
> Well, it's of course impossible to inform the user about future 
> additions, so that's poorly phrased on my part. It's about the compiler 
> informing the end user about *new* additions, part of the *current* state 
> of the API, that have cropped up since the user last revised the code 
> when the API was in a *previous* state (or, indistinguishably, members of 
> which a user is unaware regardless of the temporal sequence of when such 
> members were added). In what other circumstances do we insist that the 
> compiler perform this service?
 
 Enums. That's literally how they work today. You are arguing in favor of 
 actively removing compiler-aided correctness.
 
 There's also protocol requirements
>>> 
>>> No, that's now how enums work today, and it's not how protocol requirements 
>>> work today. Enums today are all semantically exhaustive; if a case is added 
>>> in a later version of a library, it's semantically a *different* enum type 
>>> that happens to share the same name. Not considering all the cases of an 
>>> exhaustive enum is an _error_, not a _warning_, because there is no basis 
>>> on which to proceed. This will not change with the proposal. Likewise, 
>>> adding a protocol requirement without a default implementation is 
>>> source-breaking. The result is a compiler _error_.
>>> 
>>> The question is, what non-source breaking API additions today cause the 
>>> compiler to inform the end user of such additions? The answer is: none 
>>> whatsoever. Not new methods or properties on a type, not even new protocol 
>>> requirements that have a default implementation.
>>> 
>>> 
 and, arguably, deprecated methods with a proper message ("use foo 
 instead").
>>> 
>>> 
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Xiaodi Wu via swift-evolution
On Tue, Jan 2, 2018 at 4:31 PM, Jonathan Hull  wrote:

> I think there are a couple of different definitions running around, and
> that is confusing things.
>
> In my mind, ‘unexpected:’ catches only cases which were unknown at compile
> time. Adding cases to an enum *should* be a source-breaking change. That is
> the whole point of this.  We should have to update the switch (either by
> handling new case explicitly, or by adding default) before successfully
> compiling.  What ‘unexpected:’ protects against are changes to a linked
> binary (e.g. iOS) that are now vending cases we didn’t know about when we
> were compiled.
>
> I’ll say it again… framing this idea as one of exhaustiveness is really
> confusing.  Enums should just always be exhaustive in swift.  There may be
> cases where we need to use ‘unexpected:’ to handle unexpected/future cases
> exhaustively.  If we annotate an enum as @frozen, then we won’t need to do
> that to be exhaustive because we know it won’t change out from under us.
> Always exhaustive. Much less confusing…
>
> Thanks,
> Jon
>

I think, then, you fundamentally disagree with the starting premise of the
proposal, which is specifically the addition of nonexhaustive enums to the
language, and making them the default sort of enum so that adding cases *is
not* a source-breaking change. If your whole purpose is to change the
proposal so that adding cases will _always_ be a source-breaking change and
enums are _never_ nonexhaustive, then I'm not sure how to proceed in the
discussion as we're working towards diametrically opposite goals.

On Jan 2, 2018, at 1:41 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Tue, Jan 2, 2018 at 3:27 PM, Kevin Nattinger 
> wrote:
>
>> [...]
>>
>> in what other circumstances do we insist that the compiler inform the end
>>> user about future additions to the API at compile time?
>>>
>>>
>>> This isn’t a request for the compiler to inform the user about future
>>> additions to an API.  It is a request to validate the compiler’s knowledge
>>> of the *current* state of an API with the *current* state of the source
>>> code.
>>>
>>
>> Well, it's of course impossible to inform the user about future
>> additions, so that's poorly phrased on my part. It's about the compiler
>> informing the end user about *new* additions, part of the *current* state
>> of the API, that have cropped up since the user last revised the code when
>> the API was in a *previous* state (or, indistinguishably, members of which
>> a user is unaware regardless of the temporal sequence of when such members
>> were added). In what other circumstances do we insist that the compiler
>> perform this service?
>>
>>
>> Enums. That's literally how they work today. You are arguing in favor of
>> actively removing compiler-aided correctness.
>>
>> There's also protocol requirements
>>
>
> No, that's now how enums work today, and it's not how protocol
> requirements work today. Enums today are all semantically exhaustive; if a
> case is added in a later version of a library, it's semantically a
> *different* enum type that happens to share the same name. Not considering
> all the cases of an exhaustive enum is an _error_, not a _warning_, because
> there is no basis on which to proceed. This will not change with the
> proposal. Likewise, adding a protocol requirement without a default
> implementation is source-breaking. The result is a compiler _error_.
>
> The question is, what non-source breaking API additions today cause the
> compiler to inform the end user of such additions? The answer is: none
> whatsoever. Not new methods or properties on a type, not even new protocol
> requirements that have a default implementation.
>
>
> and, arguably, deprecated methods with a proper message ("use foo
>> instead").
>>
>
>
> ___
> 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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Eneko Alonso via swift-evolution
In regards of A, doesn’t this code cover al cases?

@incomplete enum {
  case pancake
  case waffle
  case juice
}

When the @incomplete tag is present, the compiler enforces (with an error) that 
all switches handle a default case:

switch breakfast {
  case .pancake:
  case .waffle:
  case .juice:
  default:  // <— default case must be present to compile
break
}

This is also allowed:

switch breakfast {
  case .pancake:
// only like pancakes and nothing else!
  default:  // <— default case must be present to compile
break
}

I think it is safe for the compiler not to warn users when new cases are 
introduced (by the new OS, for instance), in similar way as users are not 
warned when new methods are added to a class, or new classes added to a 
framework. For instance, if a new case is added for UILabel text alignment, I 
don’t _really_ need to know unless I wanted my app to support that case. Users 
would be able to get that information from the documentation.

In regards of B (select one of the choices to be chosen as the normal choice if 
no choice is made by the user), sounds like an edge case and should be left for 
a separate proposal.


Thank you,
Eneko


> On Jan 2, 2018, at 10:11 AM, Jason Merchant via swift-evolution 
>  wrote:
> 
> I think this whole thing has been unnecessarily convoluted. As a result, the 
> majority of the replies are rabbit holes.
> 
> In my opinion, the true root of the concept in question is as follows:
> 
> A list of something is desired:
> 1 - Pancake
> 2 - Waffle
> 3 - Juice
> 
> Developer wishes to be able to:
> A) Add new things to the list of choices in the future as they come up with 
> new ideas
> B) Sometimes select one of the choices to be chosen as the normal choice if 
> no choice is made by the user
> 
> A and B are separate desires. In some circumstances a developer may want to 
> add a new choice and make it the normal choice when there was no normal 
> choice was clarified before.
> 
> 
> 
> Part 2:
> 
> After this simple desire is clear, there should be two discussions:
> A) In a text only coding language, what would we like the syntax to look 
> like? (Without regard to past-bias. What should it really be, forget what 
> mistaken design choices were made in Swift in the past)
> B) How do we approach making this happen behind the scenes?
> 
> Bonus: Given that some of us have changed our approach to programming 
> significantly beyond text based coding, and into more dynamic mediums of 
> programming in other niches, and even here and there in Xcode - I would 
> recommend considering how the IDE would show a modern version of this 
> concept. I feel too often that Swift design syntax has a lack of awareness 
> between the distinctions of what the IDE should do, as opposed to what the 
> syntax of the language should be, and what should be handled behind the 
> scenes by automated tooling.
> 
> _
> 
> My opinion, in answering the above questions is in preference to a simple 
> easy to read and write syntax, something like the following:
> 
> choices Breakfast {
> Pancake, Waffle, Juice
> }
> 
> If a "default" choice is desired, it is obvious to me that I would select the 
> choice from the IDE, and it would be visually indicated that it was the 
> default.
> 
> When changes occur, whether new choices are added, old ones are removed or 
> changed, or a default is added, changed, or removed - a behind the scenes 
> automated tool analyzes the changes and presents migration options through 
> the IDE.
> 
> _
> 
> Sincerely,
> Jason
> 
> 
> 
> ___
> 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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Jonathan Hull via swift-evolution
I think there are a couple of different definitions running around, and that is 
confusing things.

In my mind, ‘unexpected:’ catches only cases which were unknown at compile 
time. Adding cases to an enum *should* be a source-breaking change. That is the 
whole point of this.  We should have to update the switch (either by handling 
new case explicitly, or by adding default) before successfully compiling.  What 
‘unexpected:’ protects against are changes to a linked binary (e.g. iOS) that 
are now vending cases we didn’t know about when we were compiled.

I’ll say it again… framing this idea as one of exhaustiveness is really 
confusing.  Enums should just always be exhaustive in swift.  There may be 
cases where we need to use ‘unexpected:’ to handle unexpected/future cases 
exhaustively.  If we annotate an enum as @frozen, then we won’t need to do that 
to be exhaustive because we know it won’t change out from under us.  Always 
exhaustive. Much less confusing…

Thanks,
Jon



> On Jan 2, 2018, at 1:41 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Tue, Jan 2, 2018 at 3:27 PM, Kevin Nattinger  > wrote:
> [...]
> 
>>> in what other circumstances do we insist that the compiler inform the end 
>>> user about future additions to the API at compile time?
>> 
>> This isn’t a request for the compiler to inform the user about future 
>> additions to an API.  It is a request to validate the compiler’s knowledge 
>> of the current state of an API with the current state of the source code. 
>> 
>> Well, it's of course impossible to inform the user about future additions, 
>> so that's poorly phrased on my part. It's about the compiler informing the 
>> end user about *new* additions, part of the *current* state of the API, that 
>> have cropped up since the user last revised the code when the API was in a 
>> *previous* state (or, indistinguishably, members of which a user is unaware 
>> regardless of the temporal sequence of when such members were added). In 
>> what other circumstances do we insist that the compiler perform this service?
> 
> Enums. That's literally how they work today. You are arguing in favor of 
> actively removing compiler-aided correctness.
> 
> There's also protocol requirements
> 
> No, that's now how enums work today, and it's not how protocol requirements 
> work today. Enums today are all semantically exhaustive; if a case is added 
> in a later version of a library, it's semantically a *different* enum type 
> that happens to share the same name. Not considering all the cases of an 
> exhaustive enum is an _error_, not a _warning_, because there is no basis on 
> which to proceed. This will not change with the proposal. Likewise, adding a 
> protocol requirement without a default implementation is source-breaking. The 
> result is a compiler _error_.
> 
> The question is, what non-source breaking API additions today cause the 
> compiler to inform the end user of such additions? The answer is: none 
> whatsoever. Not new methods or properties on a type, not even new protocol 
> requirements that have a default implementation.
> 
> 
> and, arguably, deprecated methods with a proper message ("use foo instead").
> 
> 
> ___
> 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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Jonathan Hull via swift-evolution
I think this is a good summary.  

I agree that we need to handle unexpected cases from changes to a binary 
somehow.  The main issue is that, when forcing developers to use ‘default’ to 
do it, it also brings along unwanted semantics that prevent warnings in the 
very common use case of a 3rd party library being updated.  The proposal is 
close to what we want, but unacceptable in it’s current form IMHO.

I see two possible solutions to this:

1) A new ‘unexpected:’ construct in switches, which handle cases not known at 
compile time.  This is my favorite option because I think it gives us the most 
freedom to evolve the language in the future.  For example, if we end up adding 
subclassable enums in Swift 12 or something, we will already have a mechanism 
in place to deal with the issues that arise.

2) We version the annotation, and then require any additions to map themselves 
back an existing case for code which doesn’t know about the new case.


I also feel like framing the issue as being about exhaustiveness of enums is 
confusing. It really doesn’t have to be about exhaustiveness at all. I would 
much prefer an annotation like @frozen which can be used for structs as well. 
With @exhaustive you have to start talking about module boundaries, because all 
enums are already exhaustive within the module boundary.  You may find people 
adding @exhaustive for the wrong reasons (i.e. they want their local enum to be 
exhaustive).  Framing the issue as something where we promise not to change the 
API is a much easier mental model to explain to people.

Thanks,
Jon

> On Jan 1, 2018, at 9:48 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
>> On Dec 31, 2017, at 12:14 PM, Matthew Johnson via swift-evolution 
>> > wrote:
>> 
>> I agree that we need a solution to the problem described.  I also agree that 
>> non-exhaustive is most in keeping with the overall design of Swift at module 
>> boundaries.  However, I believe this proposal should be modified before 
>> being accepted
> 
> Thanks for writing this up - you’ve explained a common concern in an 
> interesting way:
> 
>> This is likely to be a relatively rare need mostly encountered by 3rd party 
>> libraries but it will happen.  When it does happen it would be really 
>> unfortunate to be forced to use a `default` clause rather than something 
>> like a `future` clause which will produce an error when compiled against an 
>> SDK where the enum includes cases that are not covered.  I can imagine cases 
>> where this catch-all case would need to do something other than abort the 
>> program so I do not like the `switch!` suggestion that has been discussed.  
>> The programmer should still be responsible for determining the behavior of 
>> unknown cases.
> ..
>> While library authors have a legitimate need to reserve the right to 
>> introduce new cases for some enums this need can be met without taking away 
>> a useful tool for generating static compiler errors when code does not align 
>> with intent (in this case, the intent being to cover all known cases).  
>> Switch statements working with these kinds of enums should be required to 
>> cover unknown cases but should be able to do so while still being statically 
>> checked with regards to known cases.  
> 
> I think that this could be the crux of some major confusion, the root of 
> which is the difference between source packages and binary packages that are 
> updated outside your control (e.g. the OS, or a dynamic library that is 
> updated independently of your app like a 3rd party plugin).  Consider:
> 
> 1) When dealing with independently updated binary packages, your code *has* 
> to implement some behavior for unexpected cases if the enum is 
> non-exhaustive.  It isn’t acceptable to not handle that case, and it isn’t 
> acceptable to abort because then your app will start crashing when a new OS 
> comes out. You have to build some sort of fallback into your app.
> 
> 2) When dealing with a source package that contributes to your app (e.g. 
> through SwiftPM), *YOU* control when you update that package, and therefore 
> it is entirely reasonable to exhaustively handle enums even if that package 
> owner didn’t “intend” for them to be exhaustive.  When *you* chose to update 
> the package, you get the “unhandled case” error, and you have maximal 
> “knowability” about the package’s behavior.
> 
> 
> It seems that your concern stems from the fact that the feature as proposed 
> is aligned around module boundaries, and therefore overly punishes source 
> packages like #2.  I hope you agree that in case #1, that the feature as 
> proposed is the right and only thing we can do: you really do have to handle 
> unknown future cases somehow.
> 
> If I’m getting this right, then maybe there is a variant of the proposal that 
> ties the error/warning behavior to whether or not a module is a source module 
> vs a 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Xiaodi Wu via swift-evolution
On Tue, Jan 2, 2018 at 3:27 PM, Kevin Nattinger  wrote:

> [...]
>
> in what other circumstances do we insist that the compiler inform the end
>> user about future additions to the API at compile time?
>>
>>
>> This isn’t a request for the compiler to inform the user about future
>> additions to an API.  It is a request to validate the compiler’s knowledge
>> of the *current* state of an API with the *current* state of the source
>> code.
>>
>
> Well, it's of course impossible to inform the user about future additions,
> so that's poorly phrased on my part. It's about the compiler informing the
> end user about *new* additions, part of the *current* state of the API,
> that have cropped up since the user last revised the code when the API was
> in a *previous* state (or, indistinguishably, members of which a user is
> unaware regardless of the temporal sequence of when such members were
> added). In what other circumstances do we insist that the compiler perform
> this service?
>
>
> Enums. That's literally how they work today. You are arguing in favor of
> actively removing compiler-aided correctness.
>
> There's also protocol requirements
>

No, that's now how enums work today, and it's not how protocol requirements
work today. Enums today are all semantically exhaustive; if a case is added
in a later version of a library, it's semantically a *different* enum type
that happens to share the same name. Not considering all the cases of an
exhaustive enum is an _error_, not a _warning_, because there is no basis
on which to proceed. This will not change with the proposal. Likewise,
adding a protocol requirement without a default implementation is
source-breaking. The result is a compiler _error_.

The question is, what non-source breaking API additions today cause the
compiler to inform the end user of such additions? The answer is: none
whatsoever. Not new methods or properties on a type, not even new protocol
requirements that have a default implementation.


and, arguably, deprecated methods with a proper message ("use foo instead").
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Kevin Nattinger via swift-evolution
[...]

>> in what other circumstances do we insist that the compiler inform the end 
>> user about future additions to the API at compile time?
> 
> This isn’t a request for the compiler to inform the user about future 
> additions to an API.  It is a request to validate the compiler’s knowledge of 
> the current state of an API with the current state of the source code. 
> 
> Well, it's of course impossible to inform the user about future additions, so 
> that's poorly phrased on my part. It's about the compiler informing the end 
> user about *new* additions, part of the *current* state of the API, that have 
> cropped up since the user last revised the code when the API was in a 
> *previous* state (or, indistinguishably, members of which a user is unaware 
> regardless of the temporal sequence of when such members were added). In what 
> other circumstances do we insist that the compiler perform this service?

Enums. That's literally how they work today. You are arguing in favor of 
actively removing compiler-aided correctness.

There's also protocol requirements and, arguably, deprecated methods with a 
proper message ("use foo instead").

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Karl Wagner via swift-evolution


> On 2. Jan 2018, at 16:38, Matthew Johnson via swift-evolution 
>  wrote:
> 
> 
> 
> Sent from my iPad
> 
> On Jan 1, 2018, at 11:47 PM, Chris Lattner  > wrote:
> 
>>> On Dec 31, 2017, at 12:14 PM, Matthew Johnson via swift-evolution 
>>> > wrote:
>>> 
>>> I agree that we need a solution to the problem described.  I also agree 
>>> that non-exhaustive is most in keeping with the overall design of Swift at 
>>> module boundaries.  However, I believe this proposal should be modified 
>>> before being accepted
>> 
>> Thanks for writing this up - you’ve explained a common concern in an 
>> interesting way:
>> 
>>> This is likely to be a relatively rare need mostly encountered by 3rd party 
>>> libraries but it will happen.  When it does happen it would be really 
>>> unfortunate to be forced to use a `default` clause rather than something 
>>> like a `future` clause which will produce an error when compiled against an 
>>> SDK where the enum includes cases that are not covered.  I can imagine 
>>> cases where this catch-all case would need to do something other than abort 
>>> the program so I do not like the `switch!` suggestion that has been 
>>> discussed.  The programmer should still be responsible for determining the 
>>> behavior of unknown cases.
>> ..
>>> While library authors have a legitimate need to reserve the right to 
>>> introduce new cases for some enums this need can be met without taking away 
>>> a useful tool for generating static compiler errors when code does not 
>>> align with intent (in this case, the intent being to cover all known 
>>> cases).  Switch statements working with these kinds of enums should be 
>>> required to cover unknown cases but should be able to do so while still 
>>> being statically checked with regards to known cases.  
>> 
>> I think that this could be the crux of some major confusion, the root of 
>> which is the difference between source packages and binary packages that are 
>> updated outside your control (e.g. the OS, or a dynamic library that is 
>> updated independently of your app like a 3rd party plugin).  Consider:
>> 
>> 1) When dealing with independently updated binary packages, your code *has* 
>> to implement some behavior for unexpected cases if the enum is 
>> non-exhaustive.  It isn’t acceptable to not handle that case, and it isn’t 
>> acceptable to abort because then your app will start crashing when a new OS 
>> comes out. You have to build some sort of fallback into your app.
>> 
>> 2) When dealing with a source package that contributes to your app (e.g. 
>> through SwiftPM), *YOU* control when you update that package, and therefore 
>> it is entirely reasonable to exhaustively handle enums even if that package 
>> owner didn’t “intend” for them to be exhaustive.  When *you* chose to update 
>> the package, you get the “unhandled case” error, and you have maximal 
>> “knowability” about the package’s behavior.
>> 
>> 
>> It seems that your concern stems from the fact that the feature as proposed 
>> is aligned around module boundaries, and therefore overly punishes source 
>> packages like #2.  I hope you agree that in case #1, that the feature as 
>> proposed is the right and only thing we can do: you really do have to handle 
>> unknown future cases somehow.
>> 
>> If I’m getting this right, then maybe there is a variant of the proposal 
>> that ties the error/warning behavior to whether or not a module is a source 
>> module vs a binary module.  The problem with that right now is that we have 
>> no infrastructure in the language to know this…
> 
> Hi Chris, thanks for your reply.
> 
> The concern you describe isn’t exactly what I was describing but it is 
> related.  John McCall recently posted a sketch of a solution to the concern 
> you describe which looked great to me.  I don’t have time to look up the link 
> this morning but I think it was in this review thread.
> 
> The actual concern I am describing is where a 3rd party library (or app) 
> wants to switch over a non-exhaustive enum provided by a module that is a 
> binary (not source) dependency.  The author of the 3rd party library may have 
> a legitimate reason to switch over an enum despite the author of the binary 
> module reserving the right to add additional cases.  
> 
> When this circumstance arises they will do it using the tools provided by the 
> language.  Regardless of the final language solution they obviously need to 
> cover unknown cases - their library could be shipping on a device which 
> receives an update to the binary dependency that contains a new case.  I 
> agree with you that a language-defined crash is not appropriate.  The author 
> of the switch must take responsibility for the behavior of unknown cases.  
> 
> I am arguing that these “pseudo-exhaustive” switch statements will exist in 
> the wild.  The 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Xiaodi Wu via swift-evolution
On Tue, Jan 2, 2018 at 1:46 PM, Matthew Johnson 
wrote:

>
>
> Sent from my iPad
>
> On Jan 2, 2018, at 12:48 PM, Xiaodi Wu  wrote:
>
> On Tue, Jan 2, 2018 at 9:38 AM, Matthew Johnson via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>>
>> Sent from my iPad
>>
>> On Jan 1, 2018, at 11:47 PM, Chris Lattner  wrote:
>>
>> On Dec 31, 2017, at 12:14 PM, Matthew Johnson via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> I agree that we need a solution to the problem described.  I also agree
>> that non-exhaustive is most in keeping with the overall design of Swift at
>> module boundaries.  However, I believe this proposal should be modified
>> before being accepted
>>
>>
>> Thanks for writing this up - you’ve explained a common concern in an
>> interesting way:
>>
>> This is likely to be a relatively rare need mostly encountered by 3rd
>> party libraries but it will happen.  When it does happen it would be really
>> unfortunate to be forced to use a `default` clause rather than something
>> like a `future` clause which will produce an error when compiled against an
>> SDK where the enum includes cases that are not covered.  I can imagine
>> cases where this catch-all case would need to do something *other than *abort
>> the program so I do not like the `switch!` suggestion that has been
>> discussed.  The programmer should still be responsible for determining the
>> behavior of unknown cases.
>>
>> ..
>>
>> While library authors have a legitimate need to reserve the right to
>> introduce new cases for some enums this need can be met without taking away
>> a useful tool for generating static compiler errors when code does not
>> align with intent (in this case, the intent being to cover all known
>> cases).  Switch statements working with these kinds of enums should be
>> required to cover unknown cases but should be able to do so while still
>> being statically checked with regards to known cases.
>>
>>
>> I think that this could be the crux of some major confusion, the root of
>> which is the difference between source packages and binary packages that
>> are updated outside your control (e.g. the OS, or a dynamic library that is
>> updated independently of your app like a 3rd party plugin).  Consider:
>>
>> 1) When dealing with independently updated binary packages, your code
>> *has* to implement some behavior for unexpected cases if the enum is
>> non-exhaustive.  It isn’t acceptable to not handle that case, and it isn’t
>> acceptable to abort because then your app will start crashing when a new OS
>> comes out. You have to build some sort of fallback into your app.
>>
>> 2) When dealing with a source package that contributes to your app (e.g.
>> through SwiftPM), *YOU* control when you update that package, and therefore
>> it is entirely reasonable to exhaustively handle enums even if that package
>> owner didn’t “intend” for them to be exhaustive.  When *you* chose to
>> update the package, you get the “unhandled case” error, and you have
>> maximal “knowability” about the package’s behavior.
>>
>>
>> It seems that your concern stems from the fact that the feature as
>> proposed is aligned around module boundaries, and therefore overly punishes
>> source packages like #2.  I hope you agree that in case #1, that the
>> feature as proposed is the right and only thing we can do: you really do
>> have to handle unknown future cases somehow.
>>
>> If I’m getting this right, then maybe there is a variant of the proposal
>> that ties the error/warning behavior to whether or not a module is a source
>> module vs a binary module.  The problem with that right now is that we have
>> no infrastructure in the language to know this…
>>
>>
>> Hi Chris, thanks for your reply.
>>
>> The concern you describe isn’t exactly what I was describing but it is
>> related.  John McCall recently posted a sketch of a solution to the concern
>> you describe which looked great to me.  I don’t have time to look up the
>> link this morning but I think it was in this review thread.
>>
>> The actual concern I am describing is where a 3rd party library (or app)
>> wants to switch over a non-exhaustive enum provided by a module that is a
>> binary (not source) dependency.  The author of the 3rd party library may
>> have a legitimate reason to switch over an enum despite the author of the
>> binary module reserving the right to add additional cases.
>>
>> When this circumstance arises they will do it using the tools provided by
>> the language.  Regardless of the final language solution they obviously
>> need to cover unknown cases - their library could be shipping on a device
>> which receives an update to the binary dependency that contains a new
>> case.  I agree with you that a language-defined crash is not appropriate.
>> The author of the switch must take responsibility for the behavior of
>> unknown cases.
>>
>> I am arguing that these 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Jan 2, 2018, at 12:48 PM, Xiaodi Wu  wrote:
> 
>> On Tue, Jan 2, 2018 at 9:38 AM, Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> 
>> Sent from my iPad
>> 
>> On Jan 1, 2018, at 11:47 PM, Chris Lattner  wrote:
>> 
 On Dec 31, 2017, at 12:14 PM, Matthew Johnson via swift-evolution 
  wrote:
 
 I agree that we need a solution to the problem described.  I also agree 
 that non-exhaustive is most in keeping with the overall design of Swift at 
 module boundaries.  However, I believe this proposal should be modified 
 before being accepted
>>> 
>>> Thanks for writing this up - you’ve explained a common concern in an 
>>> interesting way:
>>> 
 This is likely to be a relatively rare need mostly encountered by 3rd 
 party libraries but it will happen.  When it does happen it would be 
 really unfortunate to be forced to use a `default` clause rather than 
 something like a `future` clause which will produce an error when compiled 
 against an SDK where the enum includes cases that are not covered.  I can 
 imagine cases where this catch-all case would need to do something other 
 than abort the program so I do not like the `switch!` suggestion that has 
 been discussed.  The programmer should still be responsible for 
 determining the behavior of unknown cases.
>>> ..
 While library authors have a legitimate need to reserve the right to 
 introduce new cases for some enums this need can be met without taking 
 away a useful tool for generating static compiler errors when code does 
 not align with intent (in this case, the intent being to cover all known 
 cases).  Switch statements working with these kinds of enums should be 
 required to cover unknown cases but should be able to do so while still 
 being statically checked with regards to known cases.  
>>> 
>>> I think that this could be the crux of some major confusion, the root of 
>>> which is the difference between source packages and binary packages that 
>>> are updated outside your control (e.g. the OS, or a dynamic library that is 
>>> updated independently of your app like a 3rd party plugin).  Consider:
>>> 
>>> 1) When dealing with independently updated binary packages, your code *has* 
>>> to implement some behavior for unexpected cases if the enum is 
>>> non-exhaustive.  It isn’t acceptable to not handle that case, and it isn’t 
>>> acceptable to abort because then your app will start crashing when a new OS 
>>> comes out. You have to build some sort of fallback into your app.
>>> 
>>> 2) When dealing with a source package that contributes to your app (e.g. 
>>> through SwiftPM), *YOU* control when you update that package, and therefore 
>>> it is entirely reasonable to exhaustively handle enums even if that package 
>>> owner didn’t “intend” for them to be exhaustive.  When *you* chose to 
>>> update the package, you get the “unhandled case” error, and you have 
>>> maximal “knowability” about the package’s behavior.
>>> 
>>> 
>>> It seems that your concern stems from the fact that the feature as proposed 
>>> is aligned around module boundaries, and therefore overly punishes source 
>>> packages like #2.  I hope you agree that in case #1, that the feature as 
>>> proposed is the right and only thing we can do: you really do have to 
>>> handle unknown future cases somehow.
>>> 
>>> If I’m getting this right, then maybe there is a variant of the proposal 
>>> that ties the error/warning behavior to whether or not a module is a source 
>>> module vs a binary module.  The problem with that right now is that we have 
>>> no infrastructure in the language to know this…
>> 
>> Hi Chris, thanks for your reply.
>> 
>> The concern you describe isn’t exactly what I was describing but it is 
>> related.  John McCall recently posted a sketch of a solution to the concern 
>> you describe which looked great to me.  I don’t have time to look up the 
>> link this morning but I think it was in this review thread.
>> 
>> The actual concern I am describing is where a 3rd party library (or app) 
>> wants to switch over a non-exhaustive enum provided by a module that is a 
>> binary (not source) dependency.  The author of the 3rd party library may 
>> have a legitimate reason to switch over an enum despite the author of the 
>> binary module reserving the right to add additional cases.  
>> 
>> When this circumstance arises they will do it using the tools provided by 
>> the language.  Regardless of the final language solution they obviously need 
>> to cover unknown cases - their library could be shipping on a device which 
>> receives an update to the binary dependency that contains a new case.  I 
>> agree with you that a language-defined crash is not appropriate.  The author 
>> of the switch must take responsibility for the behavior of 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Xiaodi Wu via swift-evolution
On Tue, Jan 2, 2018 at 1:27 PM, Goffredo Marocchi  wrote:

> Hello all,
>
> On 2 Jan 2018, at 18:36, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Tue, Jan 2, 2018 at 12:11 PM, Jason Merchant via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> I think this whole thing has been unnecessarily convoluted. As a result,
>> the majority of the replies are rabbit holes.
>>
>> In my opinion, the true root of the concept in question is as follows:
>>
>> *A list of something is desired:*
>> 1 - Pancake
>> 2 - Waffle
>> 3 - Juice
>>
>> *Developer wishes to be able to:*
>> *A)* Add new things to the list of choices in the future as they come up
>> with new ideas
>> *B)* Sometimes select one of the choices to be chosen as the normal
>> choice if no choice is made by the user
>>
>> A and B are *separate desires*. In some circumstances a developer may
>> want to add a new choice and make it the normal choice when there was no
>> normal choice was clarified before.
>>
>
> I don't think this is an accurate summary of the problem being tackled
> here. Rather, we are how to enable the vendor of a nonexhaustive enum to
> add new cases without breaking binaries compiled against previous versions.
> There is little here to do with what a "default" should be. Indeed, it is
> an explicit design decision of Swift not to support types having an
> implicit default value.
>
>
> There is no way a library developer of libraries bundled in the app can
> break the app by adding new cases. They may cause compiler issues when the
> app author tries to update the library, but it will not break existing apps.
>
> The concern for updating enums is mostly an Apple / OS related concern for
> libraries/dynamic frameworks the app does not ship with, but links to at
> runtime and we should have an exception for that. We should not use the
> same solution for both and lose exhaustiveness checks when we do not need
> to. It would be wrong.
>

Right, this proposal is about enabling ABI stability and is about libraries
that don't ship with the app.

However, I disagree strongly with your point above. There should not be
dialects of Swift depending on how you link a framework. The point made
above is salient that there are, semantically, certain enums that are
exhaustive (for example, Optional, which can only have two cases), and
others that are nonexhaustive (for example, a list of foods, which will
never be complete).

Those dynamic frameworks should be the one that have to opt-in (even better
> if it is done automatically for them) in non-exhaustive extra resilient
> behaviour, not libraries you ship in the app.
>
> The app developer should be informed and have to address the new cases or
> the removal of old cases.
>
>
>
>> 
>>
>> *Part 2:*
>>
>> After this simple desire is clear, there should be two discussions:
>> *A)* In a text only coding language, what would we like the syntax to
>> look like? (Without regard to past-bias. What should it really be, forget
>> what mistaken design choices were made in Swift in the past)
>> *B)* How do we approach making this happen behind the scenes?
>>
>> *Bonus:* Given that some of us have changed our approach to programming
>> significantly beyond text based coding, and into more dynamic mediums of
>> programming in other niches, and even here and there in Xcode - I would
>> recommend considering how the IDE would show a modern version of this
>> concept. I feel too often that Swift design syntax has a *lack of
>> awareness between the distinctions of what the IDE should do, as opposed to
>> what the syntax of the language should be*, and what should be handled
>> behind the scenes by automated tooling.
>>
>> _
>>
>> *My opinion*, in answering the above questions is in preference to a
>> simple easy to read and write syntax, something like the following:
>>
>> choices Breakfast {
>> Pancake, *Waffle*, Juice
>> }
>>
>> If a "default" choice is desired, it is obvious to me that I would select
>> the choice from the IDE, and it would be visually indicated that it was the
>> default.
>>
>> When changes occur, whether new choices are added, old ones are removed
>> or changed, or a default is added, changed, or removed - a behind the
>> scenes automated tool analyzes the changes and presents migration options
>> through the IDE.
>>
>> _
>>
>> Sincerely,
>> Jason
>>
>>
>>>
>>
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Goffredo Marocchi via swift-evolution
Hello all,

> On 2 Jan 2018, at 18:36, Xiaodi Wu via swift-evolution 
>  wrote:
> 
>> On Tue, Jan 2, 2018 at 12:11 PM, Jason Merchant via swift-evolution 
>>  wrote:
>> I think this whole thing has been unnecessarily convoluted. As a result, the 
>> majority of the replies are rabbit holes.
>> 
>> In my opinion, the true root of the concept in question is as follows:
>> 
>> A list of something is desired:
>> 1 - Pancake
>> 2 - Waffle
>> 3 - Juice
>> 
>> Developer wishes to be able to:
>> A) Add new things to the list of choices in the future as they come up with 
>> new ideas
>> B) Sometimes select one of the choices to be chosen as the normal choice if 
>> no choice is made by the user
>> 
>> A and B are separate desires. In some circumstances a developer may want to 
>> add a new choice and make it the normal choice when there was no normal 
>> choice was clarified before.
> 
> I don't think this is an accurate summary of the problem being tackled here. 
> Rather, we are how to enable the vendor of a nonexhaustive enum to add new 
> cases without breaking binaries compiled against previous versions. There is 
> little here to do with what a "default" should be. Indeed, it is an explicit 
> design decision of Swift not to support types having an implicit default 
> value.

There is no way a library developer of libraries bundled in the app can break 
the app by adding new cases. They may cause compiler issues when the app author 
tries to update the library, but it will not break existing apps.

The concern for updating enums is mostly an Apple / OS related concern for 
libraries/dynamic frameworks the app does not ship with, but links to at 
runtime and we should have an exception for that. We should not use the same 
solution for both and lose exhaustiveness checks when we do not need to. It 
would be wrong.

Those dynamic frameworks should be the one that have to opt-in (even better if 
it is done automatically for them) in non-exhaustive extra resilient behaviour, 
not libraries you ship in the app. 

The app developer should be informed and have to address the new cases or the 
removal of old cases.

>  
>> 
>> 
>> Part 2:
>> 
>> After this simple desire is clear, there should be two discussions:
>> A) In a text only coding language, what would we like the syntax to look 
>> like? (Without regard to past-bias. What should it really be, forget what 
>> mistaken design choices were made in Swift in the past)
>> B) How do we approach making this happen behind the scenes?
>> 
>> Bonus: Given that some of us have changed our approach to programming 
>> significantly beyond text based coding, and into more dynamic mediums of 
>> programming in other niches, and even here and there in Xcode - I would 
>> recommend considering how the IDE would show a modern version of this 
>> concept. I feel too often that Swift design syntax has a lack of awareness 
>> between the distinctions of what the IDE should do, as opposed to what the 
>> syntax of the language should be, and what should be handled behind the 
>> scenes by automated tooling.
>> 
>> _
>> 
>> My opinion, in answering the above questions is in preference to a simple 
>> easy to read and write syntax, something like the following:
>> 
>> choices Breakfast {
>> Pancake, Waffle, Juice
>> }
>> 
>> If a "default" choice is desired, it is obvious to me that I would select 
>> the choice from the IDE, and it would be visually indicated that it was the 
>> default.
>> 
>> When changes occur, whether new choices are added, old ones are removed or 
>> changed, or a default is added, changed, or removed - a behind the scenes 
>> automated tool analyzes the changes and presents migration options through 
>> the IDE.
>> 
>> _
>> 
>> Sincerely,
>> Jason
>> 
>>> 
>> 
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Xiaodi Wu via swift-evolution
On Tue, Jan 2, 2018 at 9:38 AM, Matthew Johnson via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> Sent from my iPad
>
> On Jan 1, 2018, at 11:47 PM, Chris Lattner  wrote:
>
> On Dec 31, 2017, at 12:14 PM, Matthew Johnson via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> I agree that we need a solution to the problem described.  I also agree
> that non-exhaustive is most in keeping with the overall design of Swift at
> module boundaries.  However, I believe this proposal should be modified
> before being accepted
>
>
> Thanks for writing this up - you’ve explained a common concern in an
> interesting way:
>
> This is likely to be a relatively rare need mostly encountered by 3rd
> party libraries but it will happen.  When it does happen it would be really
> unfortunate to be forced to use a `default` clause rather than something
> like a `future` clause which will produce an error when compiled against an
> SDK where the enum includes cases that are not covered.  I can imagine
> cases where this catch-all case would need to do something *other than *abort
> the program so I do not like the `switch!` suggestion that has been
> discussed.  The programmer should still be responsible for determining the
> behavior of unknown cases.
>
> ..
>
> While library authors have a legitimate need to reserve the right to
> introduce new cases for some enums this need can be met without taking away
> a useful tool for generating static compiler errors when code does not
> align with intent (in this case, the intent being to cover all known
> cases).  Switch statements working with these kinds of enums should be
> required to cover unknown cases but should be able to do so while still
> being statically checked with regards to known cases.
>
>
> I think that this could be the crux of some major confusion, the root of
> which is the difference between source packages and binary packages that
> are updated outside your control (e.g. the OS, or a dynamic library that is
> updated independently of your app like a 3rd party plugin).  Consider:
>
> 1) When dealing with independently updated binary packages, your code
> *has* to implement some behavior for unexpected cases if the enum is
> non-exhaustive.  It isn’t acceptable to not handle that case, and it isn’t
> acceptable to abort because then your app will start crashing when a new OS
> comes out. You have to build some sort of fallback into your app.
>
> 2) When dealing with a source package that contributes to your app (e.g.
> through SwiftPM), *YOU* control when you update that package, and therefore
> it is entirely reasonable to exhaustively handle enums even if that package
> owner didn’t “intend” for them to be exhaustive.  When *you* chose to
> update the package, you get the “unhandled case” error, and you have
> maximal “knowability” about the package’s behavior.
>
>
> It seems that your concern stems from the fact that the feature as
> proposed is aligned around module boundaries, and therefore overly punishes
> source packages like #2.  I hope you agree that in case #1, that the
> feature as proposed is the right and only thing we can do: you really do
> have to handle unknown future cases somehow.
>
> If I’m getting this right, then maybe there is a variant of the proposal
> that ties the error/warning behavior to whether or not a module is a source
> module vs a binary module.  The problem with that right now is that we have
> no infrastructure in the language to know this…
>
>
> Hi Chris, thanks for your reply.
>
> The concern you describe isn’t exactly what I was describing but it is
> related.  John McCall recently posted a sketch of a solution to the concern
> you describe which looked great to me.  I don’t have time to look up the
> link this morning but I think it was in this review thread.
>
> The actual concern I am describing is where a 3rd party library (or app)
> wants to switch over a non-exhaustive enum provided by a module that is a
> binary (not source) dependency.  The author of the 3rd party library may
> have a legitimate reason to switch over an enum despite the author of the
> binary module reserving the right to add additional cases.
>
> When this circumstance arises they will do it using the tools provided by
> the language.  Regardless of the final language solution they obviously
> need to cover unknown cases - their library could be shipping on a device
> which receives an update to the binary dependency that contains a new
> case.  I agree with you that a language-defined crash is not appropriate.
> The author of the switch must take responsibility for the behavior of
> unknown cases.
>
> I am arguing that these “pseudo-exhaustive” switch statements *will*
> exist in the wild.  The crucial point of contention is whether or not the
> language provides assistance to the author of the 3rd party library in
> updating their library when the enum provided by the binary dependency
> changes.  Is 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Xiaodi Wu via swift-evolution
On Tue, Jan 2, 2018 at 12:11 PM, Jason Merchant via swift-evolution <
swift-evolution@swift.org> wrote:

> I think this whole thing has been unnecessarily convoluted. As a result,
> the majority of the replies are rabbit holes.
>
> In my opinion, the true root of the concept in question is as follows:
>
> *A list of something is desired:*
> 1 - Pancake
> 2 - Waffle
> 3 - Juice
>
> *Developer wishes to be able to:*
> *A)* Add new things to the list of choices in the future as they come up
> with new ideas
> *B)* Sometimes select one of the choices to be chosen as the normal
> choice if no choice is made by the user
>
> A and B are *separate desires*. In some circumstances a developer may
> want to add a new choice and make it the normal choice when there was no
> normal choice was clarified before.
>

I don't think this is an accurate summary of the problem being tackled
here. Rather, we are how to enable the vendor of a nonexhaustive enum to
add new cases without breaking binaries compiled against previous versions.
There is little here to do with what a "default" should be. Indeed, it is
an explicit design decision of Swift not to support types having an
implicit default value.


> 
>
> *Part 2:*
>
> After this simple desire is clear, there should be two discussions:
> *A)* In a text only coding language, what would we like the syntax to
> look like? (Without regard to past-bias. What should it really be, forget
> what mistaken design choices were made in Swift in the past)
> *B)* How do we approach making this happen behind the scenes?
>
> *Bonus:* Given that some of us have changed our approach to programming
> significantly beyond text based coding, and into more dynamic mediums of
> programming in other niches, and even here and there in Xcode - I would
> recommend considering how the IDE would show a modern version of this
> concept. I feel too often that Swift design syntax has a *lack of
> awareness between the distinctions of what the IDE should do, as opposed to
> what the syntax of the language should be*, and what should be handled
> behind the scenes by automated tooling.
>
> _
>
> *My opinion*, in answering the above questions is in preference to a
> simple easy to read and write syntax, something like the following:
>
> choices Breakfast {
> Pancake, *Waffle*, Juice
> }
>
> If a "default" choice is desired, it is obvious to me that I would select
> the choice from the IDE, and it would be visually indicated that it was the
> default.
>
> When changes occur, whether new choices are added, old ones are removed or
> changed, or a default is added, changed, or removed - a behind the scenes
> automated tool analyzes the changes and presents migration options through
> the IDE.
>
> _
>
> Sincerely,
> Jason
>
>
>>
>
> ___
> 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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Jason Merchant via swift-evolution
I think this whole thing has been unnecessarily convoluted. As a result,
the majority of the replies are rabbit holes.

In my opinion, the true root of the concept in question is as follows:

*A list of something is desired:*
1 - Pancake
2 - Waffle
3 - Juice

*Developer wishes to be able to:*
*A)* Add new things to the list of choices in the future as they come up
with new ideas
*B)* Sometimes select one of the choices to be chosen as the normal choice
if no choice is made by the user

A and B are *separate desires*. In some circumstances a developer may want
to add a new choice and make it the normal choice when there was no normal
choice was clarified before.



*Part 2:*

After this simple desire is clear, there should be two discussions:
*A)* In a text only coding language, what would we like the syntax to look
like? (Without regard to past-bias. What should it really be, forget what
mistaken design choices were made in Swift in the past)
*B)* How do we approach making this happen behind the scenes?

*Bonus:* Given that some of us have changed our approach to programming
significantly beyond text based coding, and into more dynamic mediums of
programming in other niches, and even here and there in Xcode - I would
recommend considering how the IDE would show a modern version of this
concept. I feel too often that Swift design syntax has a *lack of awareness
between the distinctions of what the IDE should do, as opposed to what the
syntax of the language should be*, and what should be handled behind the
scenes by automated tooling.

_

*My opinion*, in answering the above questions is in preference to a simple
easy to read and write syntax, something like the following:

choices Breakfast {
Pancake, *Waffle*, Juice
}

If a "default" choice is desired, it is obvious to me that I would select
the choice from the IDE, and it would be visually indicated that it was the
default.

When changes occur, whether new choices are added, old ones are removed or
changed, or a default is added, changed, or removed - a behind the scenes
automated tool analyzes the changes and presents migration options through
the IDE.

_

Sincerely,
Jason


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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Matthew Johnson via swift-evolution


Sent from my iPad

>> On Jan 1, 2018, at 11:47 PM, Chris Lattner  wrote:
>> 
>> On Dec 31, 2017, at 12:14 PM, Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> I agree that we need a solution to the problem described.  I also agree that 
>> non-exhaustive is most in keeping with the overall design of Swift at module 
>> boundaries.  However, I believe this proposal should be modified before 
>> being accepted
> 
> Thanks for writing this up - you’ve explained a common concern in an 
> interesting way:
> 
>> This is likely to be a relatively rare need mostly encountered by 3rd party 
>> libraries but it will happen.  When it does happen it would be really 
>> unfortunate to be forced to use a `default` clause rather than something 
>> like a `future` clause which will produce an error when compiled against an 
>> SDK where the enum includes cases that are not covered.  I can imagine cases 
>> where this catch-all case would need to do something other than abort the 
>> program so I do not like the `switch!` suggestion that has been discussed.  
>> The programmer should still be responsible for determining the behavior of 
>> unknown cases.
> ..
>> While library authors have a legitimate need to reserve the right to 
>> introduce new cases for some enums this need can be met without taking away 
>> a useful tool for generating static compiler errors when code does not align 
>> with intent (in this case, the intent being to cover all known cases).  
>> Switch statements working with these kinds of enums should be required to 
>> cover unknown cases but should be able to do so while still being statically 
>> checked with regards to known cases.  
> 
> I think that this could be the crux of some major confusion, the root of 
> which is the difference between source packages and binary packages that are 
> updated outside your control (e.g. the OS, or a dynamic library that is 
> updated independently of your app like a 3rd party plugin).  Consider:
> 
> 1) When dealing with independently updated binary packages, your code *has* 
> to implement some behavior for unexpected cases if the enum is 
> non-exhaustive.  It isn’t acceptable to not handle that case, and it isn’t 
> acceptable to abort because then your app will start crashing when a new OS 
> comes out. You have to build some sort of fallback into your app.
> 
> 2) When dealing with a source package that contributes to your app (e.g. 
> through SwiftPM), *YOU* control when you update that package, and therefore 
> it is entirely reasonable to exhaustively handle enums even if that package 
> owner didn’t “intend” for them to be exhaustive.  When *you* chose to update 
> the package, you get the “unhandled case” error, and you have maximal 
> “knowability” about the package’s behavior.
> 
> 
> It seems that your concern stems from the fact that the feature as proposed 
> is aligned around module boundaries, and therefore overly punishes source 
> packages like #2.  I hope you agree that in case #1, that the feature as 
> proposed is the right and only thing we can do: you really do have to handle 
> unknown future cases somehow.
> 
> If I’m getting this right, then maybe there is a variant of the proposal that 
> ties the error/warning behavior to whether or not a module is a source module 
> vs a binary module.  The problem with that right now is that we have no 
> infrastructure in the language to know this…

Hi Chris, thanks for your reply.

The concern you describe isn’t exactly what I was describing but it is related. 
 John McCall recently posted a sketch of a solution to the concern you describe 
which looked great to me.  I don’t have time to look up the link this morning 
but I think it was in this review thread.

The actual concern I am describing is where a 3rd party library (or app) wants 
to switch over a non-exhaustive enum provided by a module that is a binary (not 
source) dependency.  The author of the 3rd party library may have a legitimate 
reason to switch over an enum despite the author of the binary module reserving 
the right to add additional cases.  

When this circumstance arises they will do it using the tools provided by the 
language.  Regardless of the final language solution they obviously need to 
cover unknown cases - their library could be shipping on a device which 
receives an update to the binary dependency that contains a new case.  I agree 
with you that a language-defined crash is not appropriate.  The author of the 
switch must take responsibility for the behavior of unknown cases.  

I am arguing that these “pseudo-exhaustive” switch statements will exist in the 
wild.  The crucial point of contention is whether or not the language provides 
assistance to the author of the 3rd party library in updating their library 
when the enum provided by the binary dependency changes.  Is the author forced 
to use a `default` case which turns of exhaustiveness 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Marc Schlichte via swift-evolution
 We use enums also when modeling JSON responses from our servers. To allow the server side to add new cases without breaking existing clients, we always add an `undefined` case to our enums. Binary frameworks might do the same when exporting enums. When clients compile to a newer version of the framework, new cases will be added and checked by the compiler for exhausiveness. The new version will still contain `undefined` though for the next binary / server-side change.CheersMarc   Von: swift-evolution@swift.orgGesendet: 2. Januar 2018 6:47 vorm.An: matt...@anandabits.comAntworten: clatt...@nondot.orgCc: swift-evolution@swift.orgBetreff: Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums  On Dec 31, 2017, at 12:14 PM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:I agree that we need a solution to the problem described.  I also agree that non-exhaustive is most in keeping with the overall design of Swift at module boundaries.  However, I believe this proposal should be modified before being acceptedThanks for writing this up - you’ve explained a common concern in an interesting way:This is likely to be a relatively rare need mostly encountered by 3rd party libraries but it will happen.  When it does happen it would be really unfortunate to be forced to use a `default` clause rather than something like a `future` clause which will produce an error when compiled against an SDK where the enum includes cases that are not covered.  I can imagine cases where this catch-all case would need to do something other than abort the program so I do not like the `switch!` suggestion that has been discussed.  The programmer should still be responsible for determining the behavior of unknown cases...While library authors have a legitimate need to reserve the right to introduce new cases for some enums this need can be met without taking away a useful tool for generating static compiler errors when code does not align with intent (in this case, the intent being to cover all known cases).  Switch statements working with these kinds of enums should be required to cover unknown cases but should be able to do so while still being statically checked with regards to known cases.  I think that this could be the crux of some major confusion, the root of which is the difference between source packages and binary packages that are updated outside your control (e.g. the OS, or a dynamic library that is updated independently of your app like a 3rd party plugin).  Consider:1) When dealing with independently updated binary packages, your code *has* to implement some behavior for unexpected cases if the enum is non-exhaustive.  It isn’t acceptable to not handle that case, and it isn’t acceptable to abort because then your app will start crashing when a new OS comes out. You have to build some sort of fallback into your app.2) When dealing with a source package that contributes to your app (e.g. through SwiftPM), *YOU* control when you update that package, and therefore it is entirely reasonable to exhaustively handle enums even if that package owner didn’t “intend” for them to be exhaustive.  When *you* chose to update the package, you get the “unhandled case” error, and you have maximal “knowability” about the package’s behavior.It seems that your concern stems from the fact that the feature as proposed is aligned around module boundaries, and therefore overly punishes source packages like #2.  I hope you agree that in case #1, that the feature as proposed is the right and only thing we can do: you really do have to handle unknown future cases somehow.If I’m getting this right, then maybe there is a variant of the proposal that ties the error/warning behavior to whether or not a module is a source module vs a binary module.  The problem with that right now is that we have no infrastructure in the language to know this…-Chris___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Nevin Brackett-Rozinsky via swift-evolution
On Tue, Jan 2, 2018 at 12:47 AM, Chris Lattner via swift-evolution <
swift-evolution@swift.org> wrote:
>
>
> 1) When dealing with independently updated binary packages, your code
> *has* to implement some behavior for unexpected cases if the enum is
> non-exhaustive.  It isn’t acceptable to not handle that case, and it isn’t
> acceptable to abort because then your app will start crashing when a new OS
> comes out. You have to build some sort of fallback into your app.
>

Yes, absolutely.



> 2) When dealing with a source package that contributes to your app (e.g.
> through SwiftPM), *YOU* control when you update that package, and therefore
> it is entirely reasonable to exhaustively handle enums even if that package
> owner didn’t “intend” for them to be exhaustive.  When *you* chose to
> update the package, you get the “unhandled case” error, and you have
> maximal “knowability” about the package’s behavior.
>

I agree 100%



> It seems that your concern stems from the fact that the feature as
> proposed is aligned around module boundaries, and therefore overly punishes
> source packages like #2.  I hope you agree that in case #1, that the
> feature as proposed is the right and only thing we can do: you really do
> have to handle unknown future cases somehow.
>

I take slight exception to the word “only” here: the proposal as written
does not offer compile-time feedback to inform client programmers that
external enums on which they “switch” have new cases, because they are
required to include a “default” clause.

Yes, those client programmers need to handle unknown cases, but they *also*
deserve the compiler’s assistance in identifying when such cases have been
added. I don’t know if a “future” keyword is the best approach, but we
ought to include some way to warn (not error) when compiling a switch
statement that the author intends to be exhaustive-over-all-known-cases
while also handling unknown ones.



> If I’m getting this right, then maybe there is a variant of the proposal
> that ties the error/warning behavior to whether or not a module is a source
> module vs a binary module.  The problem with that right now is that we have
> no infrastructure in the language to know this…
>
> -Chris
>

If we can make that work, this proposal will be much more palatable.

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-01 Thread Dave DeLong via swift-evolution


> On Jan 1, 2018, at 10:47 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
>> On Dec 31, 2017, at 12:14 PM, Matthew Johnson via swift-evolution 
>> > wrote:
>> 
>> I agree that we need a solution to the problem described.  I also agree that 
>> non-exhaustive is most in keeping with the overall design of Swift at module 
>> boundaries.  However, I believe this proposal should be modified before 
>> being accepted
> 
> Thanks for writing this up - you’ve explained a common concern in an 
> interesting way:
> 
>> This is likely to be a relatively rare need mostly encountered by 3rd party 
>> libraries but it will happen.  When it does happen it would be really 
>> unfortunate to be forced to use a `default` clause rather than something 
>> like a `future` clause which will produce an error when compiled against an 
>> SDK where the enum includes cases that are not covered.  I can imagine cases 
>> where this catch-all case would need to do something other than abort the 
>> program so I do not like the `switch!` suggestion that has been discussed.  
>> The programmer should still be responsible for determining the behavior of 
>> unknown cases.
> ..
>> While library authors have a legitimate need to reserve the right to 
>> introduce new cases for some enums this need can be met without taking away 
>> a useful tool for generating static compiler errors when code does not align 
>> with intent (in this case, the intent being to cover all known cases).  
>> Switch statements working with these kinds of enums should be required to 
>> cover unknown cases but should be able to do so while still being statically 
>> checked with regards to known cases.  
> 
> I think that this could be the crux of some major confusion, the root of 
> which is the difference between source packages and binary packages that are 
> updated outside your control (e.g. the OS, or a dynamic library that is 
> updated independently of your app like a 3rd party plugin).  Consider:
> 
> 1) When dealing with independently updated binary packages, your code *has* 
> to implement some behavior for unexpected cases if the enum is 
> non-exhaustive.  It isn’t acceptable to not handle that case, and it isn’t 
> acceptable to abort because then your app will start crashing when a new OS 
> comes out. You have to build some sort of fallback into your app.
> 
> 2) When dealing with a source package that contributes to your app (e.g. 
> through SwiftPM), *YOU* control when you update that package, and therefore 
> it is entirely reasonable to exhaustively handle enums even if that package 
> owner didn’t “intend” for them to be exhaustive.  When *you* chose to update 
> the package, you get the “unhandled case” error, and you have maximal 
> “knowability” about the package’s behavior.
> 
> 
> It seems that your concern stems from the fact that the feature as proposed 
> is aligned around module boundaries, and therefore overly punishes source 
> packages like #2.  I hope you agree that in case #1, that the feature as 
> proposed is the right and only thing we can do: you really do have to handle 
> unknown future cases somehow.
> 
> If I’m getting this right, then maybe there is a variant of the proposal that 
> ties the error/warning behavior to whether or not a module is a source module 
> vs a binary module.  The problem with that right now is that we have no 
> infrastructure in the language to know this…

YES . This is the conclusion I’ve been coming to as well as I’ve been mulling 
it over.

Exhaustiveness is *only* an issue for modules that are updated independently of 
my app (ie, via an OS or other externally-linked library changing). Modules 
that are shipped with my app are unaffected with this.

I’d really love it if the build system could know that “this module is bundled 
with your app and therefore switches on its enums don't need a default case but 
this other module isn’t bundled with the app, and so therefore switches on its 
enums DO needs a default case”.

Personally, I’m falling on the side of “all enums from external modules are 
non-exhaustive”, but I recognize there are some cases where that’s semantically 
incorrect (Optional, for one; NSComparisonResult for another). In those 
cases, I think I’d prefer to have an attribute on the enum that is overly long 
and scary in order to emphasize that, once shipped, this enum must never change 
again. Something like:

@mustNeverEverEverChangeInAFutureRelease public enum Optional {
case none
case some(T)
}

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-01 Thread Chris Lattner via swift-evolution
> On Dec 31, 2017, at 12:14 PM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> I agree that we need a solution to the problem described.  I also agree that 
> non-exhaustive is most in keeping with the overall design of Swift at module 
> boundaries.  However, I believe this proposal should be modified before being 
> accepted

Thanks for writing this up - you’ve explained a common concern in an 
interesting way:

> This is likely to be a relatively rare need mostly encountered by 3rd party 
> libraries but it will happen.  When it does happen it would be really 
> unfortunate to be forced to use a `default` clause rather than something like 
> a `future` clause which will produce an error when compiled against an SDK 
> where the enum includes cases that are not covered.  I can imagine cases 
> where this catch-all case would need to do something other than abort the 
> program so I do not like the `switch!` suggestion that has been discussed.  
> The programmer should still be responsible for determining the behavior of 
> unknown cases.
..
> While library authors have a legitimate need to reserve the right to 
> introduce new cases for some enums this need can be met without taking away a 
> useful tool for generating static compiler errors when code does not align 
> with intent (in this case, the intent being to cover all known cases).  
> Switch statements working with these kinds of enums should be required to 
> cover unknown cases but should be able to do so while still being statically 
> checked with regards to known cases.  

I think that this could be the crux of some major confusion, the root of which 
is the difference between source packages and binary packages that are updated 
outside your control (e.g. the OS, or a dynamic library that is updated 
independently of your app like a 3rd party plugin).  Consider:

1) When dealing with independently updated binary packages, your code *has* to 
implement some behavior for unexpected cases if the enum is non-exhaustive.  It 
isn’t acceptable to not handle that case, and it isn’t acceptable to abort 
because then your app will start crashing when a new OS comes out. You have to 
build some sort of fallback into your app.

2) When dealing with a source package that contributes to your app (e.g. 
through SwiftPM), *YOU* control when you update that package, and therefore it 
is entirely reasonable to exhaustively handle enums even if that package owner 
didn’t “intend” for them to be exhaustive.  When *you* chose to update the 
package, you get the “unhandled case” error, and you have maximal “knowability” 
about the package’s behavior.


It seems that your concern stems from the fact that the feature as proposed is 
aligned around module boundaries, and therefore overly punishes source packages 
like #2.  I hope you agree that in case #1, that the feature as proposed is the 
right and only thing we can do: you really do have to handle unknown future 
cases somehow.

If I’m getting this right, then maybe there is a variant of the proposal that 
ties the error/warning behavior to whether or not a module is a source module 
vs a binary module.  The problem with that right now is that we have no 
infrastructure in the language to know this…

-Chris




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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-31 Thread John McCall via swift-evolution

> On Dec 31, 2017, at 1:21 PM, Cheyo Jimenez  wrote:
> 
> 
> 
> On Dec 31, 2017, at 8:59 AM, Ben Rimmington via swift-evolution 
>  wrote:
> 
>>> On 21 Dec 2017, at 03:32, John McCall wrote:
>>> 
> On Dec 20, 2017, at 10:16 PM, Brent Royal-Gordon wrote:
> 
> On Dec 19, 2017, at 2:58 PM, Ted Kremenek wrote:
> 
>   • What is your evaluation of the proposal?
 
 I am pleased with the broad strokes of this design. I have quibbles with 
 three areas:
 
 1. The `@exhaustive` attribute may be confusing because the term doesn't 
 suggest versioning. My best alternative suggestion is `@frozen`, which 
 matches existing programming terminology: something that has been frozen 
 will not be changed in the future.
>>> 
>>> I rather like @frozen.  We could use that across language features, so that 
>>> we don't end up with a keyword per kind of declaration.
>> 
>> Could this also be used on functions to make them inlinable?
>> i.e. The body of the function has been frozen.
>> 
>> ```
>> @frozen
>> public func a()
>> 
>> @available(*, frozen)
>> public func b()
>> 
>> @available(swift, introduced: 4.1, frozen: 5.0)
>> public func c()
>> 
>> ```
> 
> My understanding is that frozen / exhaustible is guaranteed by the compiler 
> while inlineable is more of a strong suggestion to the compiler. It would be 
> confusing to use the same word for both.

Well, this is both true, and false, and true again.

It's true that frozen/inlineable on a function leaves the choice of whether to 
actually perform inlining (or other interprocedural optimizations like 
specialization) up to the compiler, whereas the impact of frozen on a type has 
a direct and reliably-observable impact in the sense of lifting certain 
semantic restrictions.

But from another perspective, the meaning of the attribute to the implementor 
is the same in both cases: it means that the implementation is the same across 
versions.  frozen on a type means that the basic storage structure of the type 
won't change (i.e. it has exactly the same stored properties/cases), and frozen 
on a function means that the behavior of the function won't change.

But then again, while we can reliably check the correctness of frozen on a 
type, we can't really check that for a function.  We can check 
frozen-correctness on a type because we don't mind forbidding non-trivial 
changes to the storage structure: i.e. the set of stored properties/cases (and 
their types) have to remain exactly the same, meaning you can't even do 
"obviously equivalent" changes like combining two stored properties into a 
single property of tuple type.  But we don't want to be that strict with 
functions because we do want to allow some non-trivial differences: it's 
frequently possible to improve the implementation of a function without 
changing its behavior, and we don't want to make that impossible, but we also 
don't really want to get into the business of requiring library authors to 
prove the semantic equivalence of two different function bodies.  That means we 
just have to take implementors at their word that using the new function body 
instead of the old isn't too annoying a difference.  I know Joe Groff has 
proposed in the past that we use a somewhat different semantic model for 
inlineable functions, one that promises that we use the newest available 
functionality, and I think there's some merit to that.

To me, the important questions around keyword choice are:
  - whether the operations feel sufficiently different that using the same 
keyword is going to feel awkward;
  - whether we might be preventing useful expressiveness by using the same 
keyword (the thing that occurs to me is that having a separate attribute for 
inlineable might let us easily mass-annotate an extension, which seems like a 
common use-case); and
  - whether we can get community agreement about it, which might seem "meta", 
but sometimes one must pick one's battles.

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-31 Thread Matthew Johnson via swift-evolution
I have been busy over the holidays and have been considering the arguments in 
this thread so my review is late in coming.
> What is your evaluation of the proposal?
> 
I agree that we need a solution to the problem described.  I also agree that 
non-exhaustive is most in keeping with the overall design of Swift at module 
boundaries.  However, I believe this proposal should be modified before being 
accepted

My primary concern (shard with many others) is that this proposal takes away an 
important tool of exhaustiveness checking in cases where we need to switch over 
an enum vended by a library which was not declared exhaustive.  

This is likely to be a relatively rare need mostly encountered by 3rd party 
libraries but it will happen.  When it does happen it would be really 
unfortunate to be forced to use a `default` clause rather than something like a 
`future` clause which will produce an error when compiled against an SDK where 
the enum includes cases that are not covered.  I can imagine cases where this 
catch-all case would need to do something other than abort the program so I do 
not like the `switch!` suggestion that has been discussed.  The programmer 
should still be responsible for determining the behavior of unknown cases.

I find the argument of untestable code to be completely unconvincing.  As has 
been noted several times in this thread, when all known cases are covered in a 
switch statement the code is equally untestable whether the “other" pattern is 
spelled `default` or `future`.  There has been some discussion of finding a way 
for the compiler to support an extra test-only value somehow.  A tool like this 
could be quite useful regardless of how the “other” pattern is spelled but the 
presence or absence of this tool should not influence the decision to include 
“future” or not.

While library authors have a legitimate need to reserve the right to introduce 
new cases for some enums this need can be met without taking away a useful tool 
for generating static compiler errors when code does not align with intent (in 
this case, the intent being to cover all known cases).  Switch statements 
working with these kinds of enums should be required to cover unknown cases but 
should be able to do so while still being statically checked with regards to 
known cases.  

People are going to write these kinds of switch statements whether the language 
helps them out or not.  Instead of taking a moral standpoint that says “that is 
bad, don’t do it” the language should continue to provide assistance to the 
degree it can.  If the core team remains unconvinced about use cases for these 
kinds of "pseudo-exhaustive” switches I suggest a brief extension to the review 
with a specific request for example use cases.  I believe several good examples 
could be quickly identified in existing open source libraries.

A secondary concern I have is the @exhaustive keyword itself.  I strongly 
believe Swift will be better suited by a more general keyword that is also 
applicable in other contexts.  

I authored earlier discussions about how exhaustiveness could fit into the 
access control system.  This is discussed as an alternative under “closed” and 
“open”.  I think “closed” as a “greater than public” availability with respect 
to switch statements is perfectly sensible.  In this design the access control 
hierarchy would have two branches in different directions that are both 
"greater than public”.  This direction had some proponents but didn’t appear to 
gain traction with the core team.  In case the core team discusses this option 
I do still prefer it.

Another direction that has been discussed in this thread is to use a keyword 
that is shared with fixed layout structs.  Both of these feel like better 
options than a special case, enum-only attribute.  On the other hand, this is a 
relatively minor concern.
> Is the problem being addressed significant enough to warrant a change to 
> Swift?
> 
Yes.
> Does this proposal fit well with the feel and direction of Swift?
> 
For the most part.  However, it does introduce a special case attribute 
specifically for enums.  I would prefer if we try to avoid that and believe it 
is in keeping with the direction of Swift to try and avoid these.
> If you have used other languages or libraries with a similar feature, how do 
> you feel that this proposal compares to those?
> 
I have not worked with a language that supported both exhaustive and 
non-exhaustive enums.
> How much effort did you put into your review? A glance, a quick reading, or 
> an in-depth study?
> 
In-depth study of the proposal and all of the threads on the list.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-31 Thread Cheyo Jimenez via swift-evolution


On Dec 31, 2017, at 8:59 AM, Ben Rimmington via swift-evolution 
 wrote:

>> On 21 Dec 2017, at 03:32, John McCall wrote:
>> 
 On Dec 20, 2017, at 10:16 PM, Brent Royal-Gordon wrote:
 
 On Dec 19, 2017, at 2:58 PM, Ted Kremenek wrote:
 
• What is your evaluation of the proposal?
>>> 
>>> I am pleased with the broad strokes of this design. I have quibbles with 
>>> three areas:
>>> 
>>> 1. The `@exhaustive` attribute may be confusing because the term doesn't 
>>> suggest versioning. My best alternative suggestion is `@frozen`, which 
>>> matches existing programming terminology: something that has been frozen 
>>> will not be changed in the future.
>> 
>> I rather like @frozen.  We could use that across language features, so that 
>> we don't end up with a keyword per kind of declaration.
> 
> Could this also be used on functions to make them inlinable?
> i.e. The body of the function has been frozen.
> 
> ```
> @frozen
> public func a()
> 
> @available(*, frozen)
> public func b()
> 
> @available(swift, introduced: 4.1, frozen: 5.0)
> public func c()
> 
> ```

My understanding is that frozen / exhaustible is guaranteed by the compiler 
while inlineable is more of a strong suggestion to the compiler. It would be 
confusing to use the same word for both. 
> 
> 
> 
> 
> -- Ben
> 
> ___
> 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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-31 Thread Ben Rimmington via swift-evolution
> On 21 Dec 2017, at 03:32, John McCall wrote:
> 
>> On Dec 20, 2017, at 10:16 PM, Brent Royal-Gordon wrote:
>> 
>>> On Dec 19, 2017, at 2:58 PM, Ted Kremenek wrote:
>>> 
>>> • What is your evaluation of the proposal?
>> 
>> I am pleased with the broad strokes of this design. I have quibbles with 
>> three areas:
>> 
>> 1. The `@exhaustive` attribute may be confusing because the term doesn't 
>> suggest versioning. My best alternative suggestion is `@frozen`, which 
>> matches existing programming terminology: something that has been frozen 
>> will not be changed in the future.
> 
> I rather like @frozen.  We could use that across language features, so that 
> we don't end up with a keyword per kind of declaration.

Could this also be used on functions to make them inlinable?
i.e. The body of the function has been frozen.

```
@frozen
public func a()

@available(*, frozen)
public func b()

@available(swift, introduced: 4.1, frozen: 5.0)
public func c()

```




-- Ben

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-28 Thread Jean-Daniel via swift-evolution


> Le 28 déc. 2017 à 21:17, Eneko Alonso via swift-evolution 
>  a écrit :
> 
> Hello everyone, 
> 
> My name is Eneko Alonso, iOS developer, new here on the list.
> 
> Is there a good summary anywhere that condenses the pros and cons of this new 
> feature that have been discussed so far?
> 
> It is not clear to me why non-exhaustive would be the default, requiring 
> adding `@exhaustive` otherwise. Has anyone discussed doing it the other way 
> around, this is, defaulting to exhaustive (no changes with prior Swift 
> versions) and adding a `@nonExhaustive` tag instead as needed?

IIUC, this is to help binary stability.
If a library developer write an enum without knowing about « @exhaustive », it 
can safely add another enum in a v2 of the library without breaking all the 
clients.


> 
> Apologies if this has been covered already.
> 
> Regards and thank you everyone for making Swift better!
> Eneko
> 
> 
>> On Dec 27, 2017, at 10:26 PM, Riley Testut via swift-evolution 
>> > wrote:
>> 
>> Actually, from the other email thread about this same topic (thank god 
>> forums are almost here), I see the proposed syntax “final switch” for what I 
>> referred to as “switch!”, which I prefer.
>> 
>> On Dec 28, 2017, at 12:17 AM, Riley Testut via swift-evolution 
>> > wrote:
>> 
>>> -1.
>>> 
>>> I agree this is a problem, but I think this is the wrong solution. I think 
>>> the solution should be on the client side, not on the framework author’s 
>>> side.
>>> 
>>> I would be fine if enums from imported modules are non-exhaustive, as long 
>>> as I can choose to treat them as exhaustive if I want to. And in that case, 
>>> if a new case is introduced, I think a fatal error is a reasonable result.
>>> 
>>> The proposed “switch!” command would do just this, and I think that is the 
>>> better answer for this. Adding an @exhaustive attribute doesn’t actually 
>>> prevent someone from adding a case anyway, which I think is a big (and not 
>>> really solvable) issue 路‍♂️
>>> 
>>> I know much has been said about this, but it’s just my 2c.
>>> 
>>> On Dec 27, 2017, at 9:42 AM, Thorsten Seitz via swift-evolution 
>>> > wrote:
>>> 
 
 
> The proposal is available here:
> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>  
> 
> What is your evaluation of the proposal?
> 
 
 -1
 
 I would much prefer the solution proposed by Andrew Bennett in another 
 thread which solves all problems very nicely including the testability of 
 future cases by giving them a placeholder name:
 
 From Andrew’s mail:
> public enum HomeworkExcuse {
>   case eatenByPet
>   case thoughtItWasDueNextWeek
>   fallback unknown // NEW
> }
> 
> Then I believe you would be able to have an exhaustive switch like this:
> 
> switch thing {
>   case eatenByPet: break
>   case thoughtItWasDueNextWeek: break
>   case unknown: break
> }
> 
> Which would still allow compile-time errors if new cases are introduced, 
> while providing a concise way to show something is not exhaustible.
> 
> This would also support existing enums with "unknown" equivalent cases 
> would be able to explicitly label those fields as fallback without 
> needing to make large code changes.
> 
> I see no reason why you shouldn't be able to use ".unknown", which should 
> still allow this to be testable.
 
 i.e. Andrew’s idea is to introduce a placeholder case instead of marking 
 the enum as exhaustive/non-exhaustive. This gives the future cases a 
 handle to be switched on and to be tested against. Very elegant.
 
> Is the problem being addressed significant enough to warrant a change to 
> Swift?
> 
 Yes, but the proposed solution is not as good as it should be, neglecting 
 to provide compile-time errors if new cases are introduced.
> Does this proposal fit well with the feel and direction of Swift?
> 
 No, due to its shortcomings.
> If you have used other languages or libraries with a similar feature, how 
> do you feel that this proposal compares to those?
> 
 None, but see Andrew Bennett’s idea above.
> How much effort did you put into your review? A glance, a quick reading, 
> or an in-depth study?
> 
 Followed most of the discussion and review threads.
 
 -Thorsten
 ___
 swift-evolution mailing list
 swift-evolution@swift.org 
 https://lists.swift.org/mailman/listinfo/swift-evolution 
 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-28 Thread Eneko Alonso via swift-evolution
Hello everyone, 

My name is Eneko Alonso, iOS developer, new here on the list.

Is there a good summary anywhere that condenses the pros and cons of this new 
feature that have been discussed so far?

It is not clear to me why non-exhaustive would be the default, requiring adding 
`@exhaustive` otherwise. Has anyone discussed doing it the other way around, 
this is, defaulting to exhaustive (no changes with prior Swift versions) and 
adding a `@nonExhaustive` tag instead as needed?

Apologies if this has been covered already.

Regards and thank you everyone for making Swift better!
Eneko


> On Dec 27, 2017, at 10:26 PM, Riley Testut via swift-evolution 
>  wrote:
> 
> Actually, from the other email thread about this same topic (thank god forums 
> are almost here), I see the proposed syntax “final switch” for what I 
> referred to as “switch!”, which I prefer.
> 
> On Dec 28, 2017, at 12:17 AM, Riley Testut via swift-evolution 
> > wrote:
> 
>> -1.
>> 
>> I agree this is a problem, but I think this is the wrong solution. I think 
>> the solution should be on the client side, not on the framework author’s 
>> side.
>> 
>> I would be fine if enums from imported modules are non-exhaustive, as long 
>> as I can choose to treat them as exhaustive if I want to. And in that case, 
>> if a new case is introduced, I think a fatal error is a reasonable result.
>> 
>> The proposed “switch!” command would do just this, and I think that is the 
>> better answer for this. Adding an @exhaustive attribute doesn’t actually 
>> prevent someone from adding a case anyway, which I think is a big (and not 
>> really solvable) issue 路‍♂️
>> 
>> I know much has been said about this, but it’s just my 2c.
>> 
>> On Dec 27, 2017, at 9:42 AM, Thorsten Seitz via swift-evolution 
>> > wrote:
>> 
>>> 
>>> 
 The proposal is available here:
 https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
  
 
 What is your evaluation of the proposal?
 
>>> 
>>> -1
>>> 
>>> I would much prefer the solution proposed by Andrew Bennett in another 
>>> thread which solves all problems very nicely including the testability of 
>>> future cases by giving them a placeholder name:
>>> 
>>> From Andrew’s mail:
 public enum HomeworkExcuse {
   case eatenByPet
   case thoughtItWasDueNextWeek
   fallback unknown // NEW
 }
 
 Then I believe you would be able to have an exhaustive switch like this:
 
 switch thing {
   case eatenByPet: break
   case thoughtItWasDueNextWeek: break
   case unknown: break
 }
 
 Which would still allow compile-time errors if new cases are introduced, 
 while providing a concise way to show something is not exhaustible.
 
 This would also support existing enums with "unknown" equivalent cases 
 would be able to explicitly label those fields as fallback without needing 
 to make large code changes.
 
 I see no reason why you shouldn't be able to use ".unknown", which should 
 still allow this to be testable.
>>> 
>>> i.e. Andrew’s idea is to introduce a placeholder case instead of marking 
>>> the enum as exhaustive/non-exhaustive. This gives the future cases a handle 
>>> to be switched on and to be tested against. Very elegant.
>>> 
 Is the problem being addressed significant enough to warrant a change to 
 Swift?
 
>>> Yes, but the proposed solution is not as good as it should be, neglecting 
>>> to provide compile-time errors if new cases are introduced.
 Does this proposal fit well with the feel and direction of Swift?
 
>>> No, due to its shortcomings.
 If you have used other languages or libraries with a similar feature, how 
 do you feel that this proposal compares to those?
 
>>> None, but see Andrew Bennett’s idea above.
 How much effort did you put into your review? A glance, a quick reading, 
 or an in-depth study?
 
>>> Followed most of the discussion and review threads.
>>> 
>>> -Thorsten
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org 
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-27 Thread Riley Testut via swift-evolution
Actually, from the other email thread about this same topic (thank god forums 
are almost here), I see the proposed syntax “final switch” for what I referred 
to as “switch!”, which I prefer.

> On Dec 28, 2017, at 12:17 AM, Riley Testut via swift-evolution 
>  wrote:
> 
> -1.
> 
> I agree this is a problem, but I think this is the wrong solution. I think 
> the solution should be on the client side, not on the framework author’s side.
> 
> I would be fine if enums from imported modules are non-exhaustive, as long as 
> I can choose to treat them as exhaustive if I want to. And in that case, if a 
> new case is introduced, I think a fatal error is a reasonable result.
> 
> The proposed “switch!” command would do just this, and I think that is the 
> better answer for this. Adding an @exhaustive attribute doesn’t actually 
> prevent someone from adding a case anyway, which I think is a big (and not 
> really solvable) issue 路‍♂️
> 
> I know much has been said about this, but it’s just my 2c.
> 
>> On Dec 27, 2017, at 9:42 AM, Thorsten Seitz via swift-evolution 
>>  wrote:
>> 
>> 
>> 
>>> The proposal is available here:
>>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>>> What is your evaluation of the proposal?
>>> 
>> 
>> -1
>> 
>> I would much prefer the solution proposed by Andrew Bennett in another 
>> thread which solves all problems very nicely including the testability of 
>> future cases by giving them a placeholder name:
>> 
>> From Andrew’s mail:
>>> public enum HomeworkExcuse {
>>>   case eatenByPet
>>>   case thoughtItWasDueNextWeek
>>>   fallback unknown // NEW
>>> }
>>> 
>>> Then I believe you would be able to have an exhaustive switch like this:
>>> 
>>> switch thing {
>>>   case eatenByPet: break
>>>   case thoughtItWasDueNextWeek: break
>>>   case unknown: break
>>> }
>>> 
>>> Which would still allow compile-time errors if new cases are introduced, 
>>> while providing a concise way to show something is not exhaustible.
>>> 
>>> This would also support existing enums with "unknown" equivalent cases 
>>> would be able to explicitly label those fields as fallback without needing 
>>> to make large code changes.
>>> 
>>> I see no reason why you shouldn't be able to use ".unknown", which should 
>>> still allow this to be testable.
>> 
>> i.e. Andrew’s idea is to introduce a placeholder case instead of marking the 
>> enum as exhaustive/non-exhaustive. This gives the future cases a handle to 
>> be switched on and to be tested against. Very elegant.
>> 
>>> Is the problem being addressed significant enough to warrant a change to 
>>> Swift?
>>> 
>> Yes, but the proposed solution is not as good as it should be, neglecting to 
>> provide compile-time errors if new cases are introduced.
>>> Does this proposal fit well with the feel and direction of Swift?
>>> 
>> No, due to its shortcomings.
>>> If you have used other languages or libraries with a similar feature, how 
>>> do you feel that this proposal compares to those?
>>> 
>> None, but see Andrew Bennett’s idea above.
>>> How much effort did you put into your review? A glance, a quick reading, or 
>>> an in-depth study?
>>> 
>> Followed most of the discussion and review threads.
>> 
>> -Thorsten
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-27 Thread Riley Testut via swift-evolution
-1.

I agree this is a problem, but I think this is the wrong solution. I think the 
solution should be on the client side, not on the framework author’s side.

I would be fine if enums from imported modules are non-exhaustive, as long as I 
can choose to treat them as exhaustive if I want to. And in that case, if a new 
case is introduced, I think a fatal error is a reasonable result.

The proposed “switch!” command would do just this, and I think that is the 
better answer for this. Adding an @exhaustive attribute doesn’t actually 
prevent someone from adding a case anyway, which I think is a big (and not 
really solvable) issue 路‍♂️

I know much has been said about this, but it’s just my 2c.

> On Dec 27, 2017, at 9:42 AM, Thorsten Seitz via swift-evolution 
>  wrote:
> 
> 
> 
>> The proposal is available here:
>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>> What is your evaluation of the proposal?
>> 
> 
> -1
> 
> I would much prefer the solution proposed by Andrew Bennett in another thread 
> which solves all problems very nicely including the testability of future 
> cases by giving them a placeholder name:
> 
> From Andrew’s mail:
>> public enum HomeworkExcuse {
>>   case eatenByPet
>>   case thoughtItWasDueNextWeek
>>   fallback unknown // NEW
>> }
>> 
>> Then I believe you would be able to have an exhaustive switch like this:
>> 
>> switch thing {
>>   case eatenByPet: break
>>   case thoughtItWasDueNextWeek: break
>>   case unknown: break
>> }
>> 
>> Which would still allow compile-time errors if new cases are introduced, 
>> while providing a concise way to show something is not exhaustible.
>> 
>> This would also support existing enums with "unknown" equivalent cases would 
>> be able to explicitly label those fields as fallback without needing to make 
>> large code changes.
>> 
>> I see no reason why you shouldn't be able to use ".unknown", which should 
>> still allow this to be testable.
> 
> i.e. Andrew’s idea is to introduce a placeholder case instead of marking the 
> enum as exhaustive/non-exhaustive. This gives the future cases a handle to be 
> switched on and to be tested against. Very elegant.
> 
>> Is the problem being addressed significant enough to warrant a change to 
>> Swift?
>> 
> Yes, but the proposed solution is not as good as it should be, neglecting to 
> provide compile-time errors if new cases are introduced.
>> Does this proposal fit well with the feel and direction of Swift?
>> 
> No, due to its shortcomings.
>> If you have used other languages or libraries with a similar feature, how do 
>> you feel that this proposal compares to those?
>> 
> None, but see Andrew Bennett’s idea above.
>> How much effort did you put into your review? A glance, a quick reading, or 
>> an in-depth study?
>> 
> Followed most of the discussion and review threads.
> 
> -Thorsten
> ___
> 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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-27 Thread Cheyo Jimenez via swift-evolution


> On Dec 25, 2017, at 9:14 AM, Cheyo Jimenez via swift-evolution 
>  wrote:
> 
> 
> 
>> On Dec 22, 2017, at 8:49 AM, Cheyo Jose Jimenez  wrote:
>> 
>> 
>> 
>>> On Dec 20, 2017, at 11:12 PM, Cheyo Jimenez  wrote:
>>> 
>>> 
>>> 
 On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution 
  wrote:
 
 The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs through 
 January 3, 2018.
 
 The proposal is available here:
 
 https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
 Reviews are an important part of the Swift evolution process. All review 
 feedback should be sent to the swift-evolution mailing list at:
 
 https://lists.swift.org/mailman/listinfo/swift-evolution
 or, if you would like to keep your feedback private, directly to the 
 review manager. 
 
 When replying, please try to keep the proposal link at the top of the 
 message:
 
 Proposal link: 
 https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
 ...
 Reply text
 ...
 Other replies
 What goes into a review of a proposal?
 
 The goal of the review process is to improve the proposal under review 
 through constructive criticism and, eventually, determine the direction of 
 Swift. 
 
 When reviewing a proposal, here are some questions to consider:
 
 What is your evaluation of the proposal?
 
>>> +1 except for the name. @frozenExposed @fixedMembers @frozenMembers. 
>>> preferably something that aligns with the other notion of not being able to 
>>> add public members to structs. This will help treat structs with static 
>>> members in the same way which would be ideal.  I don't think enums should 
>>> have their own attitude.
 Is the problem being addressed significant enough to warrant a change to 
 Swift?
 
>>> don't know. im not a library author. ill defer to other library authors. 
>> 
>> I want to revise my review here. While I am not a library author I am a 
>> library consumer. 
>> 
>> Having the ability treat a non exhaustive enum as exhaustive should be 
>> introduced with this. I like the idea of a 
>> `final switch`
>> 
>> I think it communicate clearly that I want this to be treated as exhaustive 
>> even if it is already exhaustive. Having something like future, unknowns 
>> would be weird to me. 
>> 
>> Another option would be being able to cast a enum as exhaustive. I am not 
>> sure how that would work. I do not like switch!  
> 
> Preferably I’d like to say: 
> 
> switch (@exhaustive x){...}
> 
> Would this be allowed?
> 
> let @exhaustive myEnum=  x
> 
> typealias  @exhaustive Y = X
> 
> if let @exhaustive x = x {
>  switch x {...} // exhaustive here. 
> }
> 
> Could this be addressed in the proposal? 

I would also expect case _  to only match known cases since _ acts like a wild 
char. 

switch x { // x is non-exhaustive here. 
  case _ : fatalError("compile time error when missing cases ") // known cases 
at compile time 
  default: fatalError("runtime error when missing cases") // unknown cases. 
}

It makes sense for default and case _ to do the same thing for exhaustive enums 
but not for non exhaustive. 

Could this be addressed in the proposal too?  Thanks in advance. 


> 
 Does this proposal fit well with the feel and direction of Swift?
 
>>> yes. 
 If you have used other languages or libraries with a similar feature, how 
 do you feel that this proposal compares to those?
 
>>> n/a
 How much effort did you put into your review? A glance, a quick reading, 
 or an in-depth study?
 
>>> followed the previous discussion. read the proposal. 
 Thanks,
 Ted Kremenek
 Review Manager
 ___
 swift-evolution mailing list
 swift-evolution@swift.org
 https://lists.swift.org/mailman/listinfo/swift-evolution
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-27 Thread Thorsten Seitz via swift-evolution


> The proposal is available here:
> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>  
> 
> What is your evaluation of the proposal?
> 

-1

I would much prefer the solution proposed by Andrew Bennett in another thread 
which solves all problems very nicely including the testability of future cases 
by giving them a placeholder name:

>From Andrew’s mail:
> public enum HomeworkExcuse {
>   case eatenByPet
>   case thoughtItWasDueNextWeek
>   fallback unknown // NEW
> }
> 
> Then I believe you would be able to have an exhaustive switch like this:
> 
> switch thing {
>   case eatenByPet: break
>   case thoughtItWasDueNextWeek: break
>   case unknown: break
> }
> 
> Which would still allow compile-time errors if new cases are introduced, 
> while providing a concise way to show something is not exhaustible.
> 
> This would also support existing enums with "unknown" equivalent cases would 
> be able to explicitly label those fields as fallback without needing to make 
> large code changes.
> 
> I see no reason why you shouldn't be able to use ".unknown", which should 
> still allow this to be testable.

i.e. Andrew’s idea is to introduce a placeholder case instead of marking the 
enum as exhaustive/non-exhaustive. This gives the future cases a handle to be 
switched on and to be tested against. Very elegant.

> Is the problem being addressed significant enough to warrant a change to 
> Swift?
> 
Yes, but the proposed solution is not as good as it should be, neglecting to 
provide compile-time errors if new cases are introduced.
> Does this proposal fit well with the feel and direction of Swift?
> 
No, due to its shortcomings.
> If you have used other languages or libraries with a similar feature, how do 
> you feel that this proposal compares to those?
> 
None, but see Andrew Bennett’s idea above.
> How much effort did you put into your review? A glance, a quick reading, or 
> an in-depth study?
> 
Followed most of the discussion and review threads.

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-27 Thread Zach Waldowski via swift-evolution
Sorry to glomm on to my own comments:

I think there’s a lot of reasonable push-back to requiring a default
case on non-exhaustive enums. I personally don’t want to see a “future
case” because I think it’s mystery-meat. However, in the happy path, as
a developer I do want *some* notification by the compiler that I may
need to handle a new case, even if my code is already in the wild
handling the case through a default. To fulfill Swift’s safety and
stability goals, it  needs to both avoid creating suddenly invalid code
at compile time and  avoid UB at runtime. The community should take note
that this all a bit of cutting  a Gordian knot on the part of the
language, but it's worthwhile to avoid adding cruft and bugs.
Sincerely,
  Zachary Waldowski
  z...@waldowski.me

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-27 Thread Zach Waldowski via swift-evolution
On Tue, Dec 19, 2017, at 5:58 PM, Ted Kremenek wrote:
>  * What is your evaluation of the proposal?
+1.

I strongly prefer all additions to service ABI follow progressive
disclosure, but it’s not reason alone to make the annotation be mystery
meat. Like the inlining proposal, the spelling needs some consideration
by the core team to provide an ergonomic through-line through the
language. I liked reusing `final` way back when the proposal first came
up, but that ship appears to have sailed. If an annotation is our
preference, I do like `@frozen` if we see it come up in interesting ways
elsewhere.
>  * Is the problem being addressed significant enough to warrant a
>change to Swift?
I see this proposal and its discussion mostly as prevarication on the
spelling and the default behavior. Those aside, it solves a bug, so bar-
none something must be done. In a perfect world, no annotation or
closed/open would be needed, but this is unrealistic, and a solution
that involves compile-time diagnostics over runtime failures is
preferable.
>  * Does this proposal fit well with the feel and direction of Swift?
ABI stability is a high-level goal, and this fits within it.

The Core Team and Apple could do a better job with messaging its
compatibility impact. Though I understand it now, changing a feature’s
behavior is indeed surprising at this point. My understanding is that
nothing will change for creating enums in the single target happy path,
with a stretch goal being to extend that to all  source targets that
produce a single (in Apple terminology) bundle. I know y’all can’t
discuss future dev tools directions, but it may have helped us to know
the plan for what constitutes the compiler “seeing” an enum’s source to
make a resilience decision.
>  * If you have used other languages or libraries with a similar
>feature, how do you feel that this proposal compares to those?
I’m most familiar if the impact of this problem on ObjC, where it was
only really solved for Apple. We’re forging new territory for solving
this at the ABI level for any binary module, so some uncertainty is to
be expected.
>  * How much effort did you put into your review? A glance, a quick
>reading, or an in-depth study?
I’ve followed the proposal in depth since its early stages.

Sincerely,
  Zachary Waldowski
  z...@waldowski.me
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-25 Thread Cheyo Jimenez via swift-evolution


> On Dec 22, 2017, at 8:49 AM, Cheyo Jose Jimenez  wrote:
> 
> 
> 
>> On Dec 20, 2017, at 11:12 PM, Cheyo Jimenez  wrote:
>> 
>> 
>> 
>>> On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution 
>>>  wrote:
>>> 
>>> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs through 
>>> January 3, 2018.
>>> 
>>> The proposal is available here:
>>> 
>>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>>> Reviews are an important part of the Swift evolution process. All review 
>>> feedback should be sent to the swift-evolution mailing list at:
>>> 
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> or, if you would like to keep your feedback private, directly to the review 
>>> manager. 
>>> 
>>> When replying, please try to keep the proposal link at the top of the 
>>> message:
>>> 
>>> Proposal link: 
>>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>>> ...
>>> Reply text
>>> ...
>>> Other replies
>>> What goes into a review of a proposal?
>>> 
>>> The goal of the review process is to improve the proposal under review 
>>> through constructive criticism and, eventually, determine the direction of 
>>> Swift. 
>>> 
>>> When reviewing a proposal, here are some questions to consider:
>>> 
>>> What is your evaluation of the proposal?
>>> 
>> +1 except for the name. @frozenExposed @fixedMembers @frozenMembers. 
>> preferably something that aligns with the other notion of not being able to 
>> add public members to structs. This will help treat structs with static 
>> members in the same way which would be ideal.  I don't think enums should 
>> have their own attitude.
>>> Is the problem being addressed significant enough to warrant a change to 
>>> Swift?
>>> 
>> don't know. im not a library author. ill defer to other library authors. 
> 
> I want to revise my review here. While I am not a library author I am a 
> library consumer. 
> 
> Having the ability treat a non exhaustive enum as exhaustive should be 
> introduced with this. I like the idea of a 
> `final switch`
> 
> I think it communicate clearly that I want this to be treated as exhaustive 
> even if it is already exhaustive. Having something like future, unknowns 
> would be weird to me. 
> 
> Another option would be being able to cast a enum as exhaustive. I am not 
> sure how that would work. I do not like switch!  

Preferably I’d like to say: 

switch (@exhaustive x){...}

Would this be allowed?

let @exhaustive myEnum=  x

typealias  @exhaustive Y = X

if let @exhaustive x = x {
 switch x {...} // exhaustive here. 
}

Could this be addressed in the proposal? 

>>> Does this proposal fit well with the feel and direction of Swift?
>>> 
>> yes. 
>>> If you have used other languages or libraries with a similar feature, how 
>>> do you feel that this proposal compares to those?
>>> 
>> n/a
>>> How much effort did you put into your review? A glance, a quick reading, or 
>>> an in-depth study?
>>> 
>> followed the previous discussion. read the proposal. 
>>> Thanks,
>>> Ted Kremenek
>>> Review Manager
>>> ___
>>> 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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-23 Thread Slava Pestov via swift-evolution
Hi Dave,

The broader problem is being considered holistically, and we’re designing and 
implementing various pieces of the solution as part of the ABI stability effort 
for Swift 5. Some of these pieces impact the language, hence you’ll be seeing 
some evolution proposals. Non-exhaustive enums is one part, the inlinable 
proposal out for review right now is another part. There are a few more related 
proposals in the pipeline also.

Perhaps we need to do a better job of explaining how these things all tie 
together. In the mean time you can read about the overall design here: 
https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst 


Slava

> On Dec 23, 2017, at 11:17 AM, Dave DeLong via swift-evolution 
>  wrote:
> 
> Continuing on this vein, there is another huge reason this proposal is 
> incomplete and won’t solve the problem.
> 
> This proposal, as I outlined previously, is all about binary compatibility 
> and functional resilience in the face of changing libraries. However, it 
> falls woefully short by only considering the binary implications of changing 
> enums.
> 
> The problem of binary compatibility extends *far* beyond the mutation of 
> enums between library versions. By only considering the “enum problem”, we 
> are ignoring a much larger and worse problem that will be even easier for 
> libraries to succumb to. It’s easy as a library author to inadvertently 
> rename a method or change the type of a parameter, or add a parameter, or 
> change the return type, or change the implementation semantics, or remove a 
> type, or remove a function, in such a way that a linking app cannot handle. 
> This is why the burden of binary compatibility rightfully rests on library 
> authors, and not app authors. 
> 
> The thing that changes has the responsibility to maintain compatibility for 
> the thing that hasn’t changed.
> 
> We should absolutely not implement this proposal; it only addresses a single 
> portion of a very large problem. Instead, we should figure out what the 
> broader binary compatibility story is. If we can answer *that* and provide 
> the necessary features to address it, then enum resilience will naturally 
> fall out of it. Focusing on the enum problem is focusing on the wrong problem.
> 
> Dave
> 
>> On Dec 21, 2017, at 11:02 AM, Dave DeLong > > wrote:
>> 
>> I realized further why we should not implement this proposal: It forces the 
>> problem of binary compatibility on the app developer, when experience has 
>> shown us that problem is better handled by the libraries.
>> 
>> Binary Compatibility
>> 
>> “Binary compatibility” is the notion that, even if the libraries you link 
>> against change, your app will still behave as it did when it was first 
>> compiled. For Swift apps these days, we don’t really have this problem, 
>> *yet*. We do have the problem of “binary compatibility” with Apple-provided 
>> frameworks, but those are all written in Objective-C, and so the question of 
>> “Swift” binary compatibility is still up-in-the-air.
>> 
>> Post-ABI stability, we still won’t have much issue with swift binary 
>> compatibility on Apple platforms, because there isn’t a mechanism to ship a 
>> framework to your users independently of an app update. So from the app POV, 
>> none of this will be a problem for Apple platform developers.
>> 
>> It will be a problem for non-Apple platform developers. As a simple example, 
>> let’s say I write a web app in Swift, and deploy it to a server that has 
>> some built-in Swift-on-the-server libraries. Here, my Swift app is decoupled 
>> from the libraries, and either one can update independently of each other. 
>> If the server owner decides to update from Swift 6 to Swift 6.1, that’s 
>> cool. But my web app should continue to run and behave *as if* the server 
>> were still running Swift 6, because it has not been re-compiled to use Swift 
>> 6.1 features.
>> 
>> This is the situation today on Apple platforms. Every app deployed to an 
>> Apple device includes a little piece of information in the executable file 
>> indicating which SDK was used to compile the app. At runtime, the system 
>> frameworks read this value and then alter their behavior accordingly. This 
>> is why apps written against the iOS 9 SDK continue to work on iOS 11 
>> devices; UIKit and friends are altering their behavior to provide iOS 9 
>> semantics. 
>> 
>> This is “binary compatibility”: the binary (your app) continues to be 
>> compatible with the dynamically linked frameworks present on the system, 
>> even though those frameworks may change.
>> 
>> When you have a setup where the frameworks do NOT provide binary 
>> compatibility, you end up in DLL Hell [1]. This is the same frustrating 
>> scenario when you’re in when you’re doing stuff with homebrew and find that 
>> this package you want 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-23 Thread Cheyo Jose Jimenez via swift-evolution


> On Dec 23, 2017, at 3:19 AM, Thomas Roughton via swift-evolution 
>  wrote:
> 
> Looking at the feedback to this proposal, it looks like a common thread is 
> people wanting to make sure they’re notified when new cases are introduced 
> (the ‘future’ keyword’). However, if I’m understanding correctly, the 
> resistance to adding such a keyword is that it becomes complicated when 
> there’s e.g. both a ‘future’ and ‘default’ case, with two different sets of 
> behaviour. I missed the earlier discussion around this proposal so forgive me 
> if this is a concept that’s been brought up before.
> 
> A possible alternative would be to build on that concept, but place the 
> weight on the ‘switch’ statement. I’d propose something like the following 
> for a non-exhaustive enum that currently has cases ‘a’ and ‘b’.
> 
> @complete switch nonExhaustiveEnum {
>case a:
>print(“a”)
>case b:
>print(“b”)
>future:
>break
> }

The `final switch` mentioned in the proposal seems like a good solution to this 
problem. 
http://dlang.org/statement.html#FinalSwitchStatement


> 
> where the semantics would be that in a @complete switch statement, all known 
> cases must be explicitly switched. The ‘future’ case would have the same 
> run-time semantics as a default case for a non-@complete switch (I’m sticking 
> with the ‘future’ name here since I think it’s clearer, but continuing to use 
> ‘default’ would also work). If the external library is modified and the user 
> code is then recompiled, Swift would error at compile time saying that there 
> were unhandled cases.
> 
> Obviously, this still requires adding keywords to the language and some 
> degree of complexity, but does mean the behaviour change is isolated to a 
> fairly simple compile-time check.
> 
> Thomas
> ___
> 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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-23 Thread Dave DeLong via swift-evolution
Continuing on this vein, there is another huge reason this proposal is 
incomplete and won’t solve the problem.

This proposal, as I outlined previously, is all about binary compatibility and 
functional resilience in the face of changing libraries. However, it falls 
woefully short by only considering the binary implications of changing enums.

The problem of binary compatibility extends *far* beyond the mutation of enums 
between library versions. By only considering the “enum problem”, we are 
ignoring a much larger and worse problem that will be even easier for libraries 
to succumb to. It’s easy as a library author to inadvertently rename a method 
or change the type of a parameter, or add a parameter, or change the return 
type, or change the implementation semantics, or remove a type, or remove a 
function, in such a way that a linking app cannot handle. This is why the 
burden of binary compatibility rightfully rests on library authors, and not app 
authors. 

The thing that changes has the responsibility to maintain compatibility for the 
thing that hasn’t changed.

We should absolutely not implement this proposal; it only addresses a single 
portion of a very large problem. Instead, we should figure out what the broader 
binary compatibility story is. If we can answer *that* and provide the 
necessary features to address it, then enum resilience will naturally fall out 
of it. Focusing on the enum problem is focusing on the wrong problem.

Dave

> On Dec 21, 2017, at 11:02 AM, Dave DeLong  wrote:
> 
> I realized further why we should not implement this proposal: It forces the 
> problem of binary compatibility on the app developer, when experience has 
> shown us that problem is better handled by the libraries.
> 
> Binary Compatibility
> 
> “Binary compatibility” is the notion that, even if the libraries you link 
> against change, your app will still behave as it did when it was first 
> compiled. For Swift apps these days, we don’t really have this problem, 
> *yet*. We do have the problem of “binary compatibility” with Apple-provided 
> frameworks, but those are all written in Objective-C, and so the question of 
> “Swift” binary compatibility is still up-in-the-air.
> 
> Post-ABI stability, we still won’t have much issue with swift binary 
> compatibility on Apple platforms, because there isn’t a mechanism to ship a 
> framework to your users independently of an app update. So from the app POV, 
> none of this will be a problem for Apple platform developers.
> 
> It will be a problem for non-Apple platform developers. As a simple example, 
> let’s say I write a web app in Swift, and deploy it to a server that has some 
> built-in Swift-on-the-server libraries. Here, my Swift app is decoupled from 
> the libraries, and either one can update independently of each other. If the 
> server owner decides to update from Swift 6 to Swift 6.1, that’s cool. But my 
> web app should continue to run and behave *as if* the server were still 
> running Swift 6, because it has not been re-compiled to use Swift 6.1 
> features.
> 
> This is the situation today on Apple platforms. Every app deployed to an 
> Apple device includes a little piece of information in the executable file 
> indicating which SDK was used to compile the app. At runtime, the system 
> frameworks read this value and then alter their behavior accordingly. This is 
> why apps written against the iOS 9 SDK continue to work on iOS 11 devices; 
> UIKit and friends are altering their behavior to provide iOS 9 semantics. 
> 
> This is “binary compatibility”: the binary (your app) continues to be 
> compatible with the dynamically linked frameworks present on the system, even 
> though those frameworks may change.
> 
> When you have a setup where the frameworks do NOT provide binary 
> compatibility, you end up in DLL Hell [1]. This is the same frustrating 
> scenario when you’re in when you’re doing stuff with homebrew and find that 
> this package you want has multiple dependencies, but these dependencies want 
> different versions of the same library. [2]
> 
> Exhaustive Enums
> 
> All of the discussion around exhaustive enums has been from the point-of-view 
> of “what should the behavior be when the libraries change”. Thinking back, 
> I’m actually surprised this is a question at all, because Apple answered this 
> *years* ago: THE BEHAVIOR SHOULD REMAIN UNCHANGED. It is up to the library 
> authors to ensure that they’re doing what the compiled-and-unchanging 
> application is expecting them to do.
> 
> This discussion around exhaustive enums is basically saying “can we force the 
> developers to deal with binary incompatibility?”. We absolutely should not. 
> There are far more app developers than library developers, and it would be a 
> massively wasteful expenditure of engineering effort to force each and every 
> app developer to deal with binary incompatibility, when the library can do it 
> for them. That is 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-23 Thread Jonathan Hull via swift-evolution

> On Dec 21, 2017, at 11:07 AM, Jordan Rose  wrote:
> 
> Thanks for your comments, Jon. Responses inline.
> 
>> On Dec 20, 2017, at 12:46, Jonathan Hull > > wrote:
>> 
>> 
>>> On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution 
>>> > wrote:
>>> When reviewing a proposal, here are some questions to consider:
>>> 
>>> What is your evaluation of the proposal?
>>> 
>> Strong -1 as is.
>> 
>> I think I would support having an explicit ‘futureCase’ which is different 
>> from ‘default’.  Requiring default is asking for bugs.  With a separate 
>> ‘futureCase’, we would still get a compile-time error when all of the 
>> current cases aren’t handled.  Note that ‘ futureCase’ is also different 
>> than ‘default’ in that it wouldn’t have to go at the bottom.  It would only 
>> be triggered when the value isn’t one of the values which was known at 
>> compile time.  We should also bike shed the name of ‘futureCase’ to come up 
>> with something that might allow us to make other types of extendable enums…. 
>>  Maybe something like ‘unknownCase’ or ‘unexpectedCase’.
>> 
>> As for the issue of testing, we could add (later) a universally unexpected 
>> case that non-exhaustive enums can be set to for testing. I am not convinced 
>> that this is actually a big enough issue to warrant that though. Forcing 
>> ‘default’ is a much larger real-world problem, IMO (and this use of 
>> ‘default’ is just as untestable).
> 
> Both of these are discussed in "Alternatives considered", and they have flaws 
> that led me to leave them out of the proposal. Do you have any ideas on how 
> to improve on that?

What are the flaws?  I saw that the ‘Future’ case can’t be tested… but using 
‘default’ is just as untestable in the same way.  Others have given lots of 
examples where it will actually be used.

I think we should reframe it so that instead of talking about exhaustive vs. 
non-exhaustive, all switches need to be exhaustive… but switches over these 
enums need to handle unexpected cases to be considered exhaustive.

I know it is marked as an “alternative”, but it seems clear to me that having 
an ‘unexpected’ case (which only matches cases not known at compile time) is 
the clear answer here.  Something like 75% of  responses have mentioned it.


> 
>> 
>> I also dislike the name @exhaustive because I think it will cause confusion 
>> (i.e. “Of course my Enum is exhaustive”).  I think we should just have 
>> @fixed for both enums and structs. The word fixed has the connotation that 
>> it shouldn’t change.
> 
> I don't think anybody loves "exhaustive", but using the same attribute for 
> enums and structs isn't really appropriate, as discussed in my response to 
> Karl yesterday 
> .
>  I'm not opposed to a better name if we can gravitate towards one, though.

I really like @frozen.  It has a much clearer connotation of what it means, and 
can be used for structs too.

Thanks,
Jon

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-23 Thread Thomas Roughton via swift-evolution
Looking at the feedback to this proposal, it looks like a common thread is 
people wanting to make sure they’re notified when new cases are introduced (the 
‘future’ keyword’). However, if I’m understanding correctly, the resistance to 
adding such a keyword is that it becomes complicated when there’s e.g. both a 
‘future’ and ‘default’ case, with two different sets of behaviour. I missed the 
earlier discussion around this proposal so forgive me if this is a concept 
that’s been brought up before.

A possible alternative would be to build on that concept, but place the weight 
on the ‘switch’ statement. I’d propose something like the following for a 
non-exhaustive enum that currently has cases ‘a’ and ‘b’.

@complete switch nonExhaustiveEnum {
case a:
print(“a”)
case b:
print(“b”)
future:
break
}

where the semantics would be that in a @complete switch statement, all known 
cases must be explicitly switched. The ‘future’ case would have the same 
run-time semantics as a default case for a non-@complete switch (I’m sticking 
with the ‘future’ name here since I think it’s clearer, but continuing to use 
‘default’ would also work). If the external library is modified and the user 
code is then recompiled, Swift would error at compile time saying that there 
were unhandled cases.

Obviously, this still requires adding keywords to the language and some degree 
of complexity, but does mean the behaviour change is isolated to a fairly 
simple compile-time check.

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-22 Thread Cheyo Jose Jimenez via swift-evolution


> On Dec 20, 2017, at 11:12 PM, Cheyo Jimenez  wrote:
> 
> 
> 
>> On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution 
>>  wrote:
>> 
>> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs through 
>> January 3, 2018.
>> 
>> The proposal is available here:
>> 
>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>> Reviews are an important part of the Swift evolution process. All review 
>> feedback should be sent to the swift-evolution mailing list at:
>> 
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> or, if you would like to keep your feedback private, directly to the review 
>> manager. 
>> 
>> When replying, please try to keep the proposal link at the top of the 
>> message:
>> 
>> Proposal link: 
>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>> ...
>> Reply text
>> ...
>> Other replies
>> What goes into a review of a proposal?
>> 
>> The goal of the review process is to improve the proposal under review 
>> through constructive criticism and, eventually, determine the direction of 
>> Swift. 
>> 
>> When reviewing a proposal, here are some questions to consider:
>> 
>> What is your evaluation of the proposal?
>> 
> +1 except for the name. @frozenExposed @fixedMembers @frozenMembers. 
> preferably something that aligns with the other notion of not being able to 
> add public members to structs. This will help treat structs with static 
> members in the same way which would be ideal.  I don't think enums should 
> have their own attitude.
>> Is the problem being addressed significant enough to warrant a change to 
>> Swift?
>> 
> don't know. im not a library author. ill defer to other library authors. 

I want to revise my review here. While I am not a library author I am a library 
consumer. 

Having the ability treat a non exhaustive enum as exhaustive should be 
introduced with this. I like the idea of a 
`final switch`

I think it communicate clearly that I want this to be treated as exhaustive 
even if it is already exhaustive. Having something like future, unknowns would 
be weird to me. 

Another option would be being able to cast a enum as exhaustive. I am not sure 
how that would work. I do not like switch!  

>> Does this proposal fit well with the feel and direction of Swift?
>> 
> yes. 
>> If you have used other languages or libraries with a similar feature, how do 
>> you feel that this proposal compares to those?
>> 
> n/a
>> How much effort did you put into your review? A glance, a quick reading, or 
>> an in-depth study?
>> 
> followed the previous discussion. read the proposal. 
>> Thanks,
>> Ted Kremenek
>> Review Manager
>> ___
>> 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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-22 Thread Brent Royal-Gordon via swift-evolution
> On Dec 21, 2017, at 10:02 AM, Dave DeLong via swift-evolution 
>  wrote:
> 
> I would love to see some sort of formal API versioning that we could do 
> instead in libraries, along with easy runtime support for checking the linked 
> version of libraries, making it easy to strategize implementations based on 
> version, etc.

This feature would have to be applied not only to switching on enums, but to 
*every* operation on a resilient value. In practice, I think it generalizes to 
one of:

1. Pass a linked-against version number to every resilient call.

2. Have a way to fetch a substitute witness table for a given module 
version.

Either one of these seems like a tall order.

-- 
Brent Royal-Gordon
Architechies

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Charlie Monroe via swift-evolution


> On Dec 21, 2017, at 8:17 PM, Jordan Rose  wrote:
> 
> 
> 
>> On Dec 20, 2017, at 12:54, Charlie Monroe > > wrote:
>> 
>> I think that the main confusion here stems from the word library as we are 
>> addressing something that can be divided further (and this is IMHO as many 
>> macOS/iOS devs see it):
>> 
>> - libraries that come with the OS - here, it absolutely makes sense to make 
>> the enums non-exhaustive as the apps are linked against these libraries and 
>> the user installs a binary that will load these at launch and they are not 
>> bundled with the app - the developer can't control future OS releases and he 
>> wants the app to run on a future OS release.
>> - libraries that are bundled with the app - be it PM, CocoaPods or something 
>> else - you typically update your dependencies once in a while and they 
>> change. And you want to be notified by the compiler about possible changes - 
>> extended enums, in this case. Because let's be honest - if your app has a 
>> dozen dependencies and you come to the app after a year of no development, 
>> Swift 5 came along during that period, you want to update these libraries to 
>> Swift-5-compatible versions. And no one has the time to go through all 
>> change logs - even if they were kept up-to-date and thorough, which I can't 
>> say that I've seen in many instances.
>> 
>> I know that this is a limited view from the perspective of an app developer 
>> and that potentially, e.g. on Linux, there may be libraries written in Swift 
>> that you may want to install via package managers and depend on them once 
>> the ABI is stable, but the choice to make them non-exhaustive by default is 
>> not in line with everything else in Swift - everything else is generally 
>> closed by default - public (-> final in other modules), no access modified 
>> (-> internal), ...
>> 
>> For me, it's a -1 as it is now. I'd prefer exhaustive-by-default, 
>> ObjC/C-import non-exhaustive by default (the way ObjC classes are open by 
>> default vs. public). When it comes to the switch statement, there definitely 
>> needs to be an option to make an exhaustive switch over all 
>> compile-time-known values with a warning shall a new one be added. Without 
>> that, the code will become incredibly prone to errors and hard to maintain.
> 
> This does bring up another option, which is to differentiate Apple-provided 
> libraries (and in general, libraries with binary compatibility concerns, i.e. 
> libraries that may be different at run-time from what you compiled against) 
> from bundled / built-from-source libraries. Slava and I have been very leery 
> of this because it fragments the language into dialects, and has the 
> potential to confuse people when they try to write code that behaves like an 
> Apple framework, but I suppose it is an option.

I wouldn't differentiate, I would just try to think which should be the 
default. Which is more common? Which will be the more common scenario? I would 
dare say that vast majority (currently) falls under b) - and in these cases, it 
makes more sense to make the enum exhaustive by default.

> 
> Jordan
> 
> 
>> 
>>> On Dec 20, 2017, at 9:35 PM, Karl Wagner via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> 
 On 20. Dec 2017, at 19:54, Jordan Rose > wrote:
 
 
 
> On Dec 20, 2017, at 05:36, Karl Wagner via swift-evolution 
> > wrote:
> 
> 
> 
>> On 19. Dec 2017, at 23:58, Ted Kremenek via swift-evolution 
>> > wrote:
>> 
>> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs 
>> through January 3, 2018.
>> 
>> The proposal is available here:
>> 
>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>>  
>> +1,
>>  it needs to happen (and ASAP, since it _will_ introduce source-breaking 
>> changes one way or the other).
> 
> I think non-exhaustive is the correct default. However, does this not 
> mean that, by default, enums will be boxed because the receiver doesn’t 
> know their potential size?
 
 It's not always boxing, but yes, there will be more indirection if the 
 compiler can't see the contents of the enum. (More on that below.)
 
 
> That would mean that the best transition path for multi-module Apps would 
> be to make your enums @exhaustive, rather than adding “default” 
> statements (which is unfortunate, because I imagine when this change 
> hits, the way you’ll notice will be complaints about missing “default” 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Rod Brown via swift-evolution
Thanks for this response, John.

I think you’re right. This would be very helpful. It a) helps those who are 
source compiling with their app, and b) avoids fragmenting the language because 
it would be a core understanding of the code you are compiling, rather than 
creating a new “variant” of Swift for the binary compatible framework vs client 
code.

- Rod

> On 22 Dec 2017, at 6:26 am, John McCall via swift-evolution 
>  wrote:
> 
> 
>>> On Dec 21, 2017, at 2:03 PM, Jordan Rose via swift-evolution 
>>>  wrote:
>>> 
>>> 
>>> 
 On Dec 20, 2017, at 12:35, Karl Wagner  wrote:
 
 
 
> On 20. Dec 2017, at 19:54, Jordan Rose  wrote:
> 
> 
> 
>> On Dec 20, 2017, at 05:36, Karl Wagner via swift-evolution 
>>  wrote:
>> 
>> 
>> 
>> On 19. Dec 2017, at 23:58, Ted Kremenek via swift-evolution 
>>  wrote:
>> 
>> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs 
>> through January 3, 2018.
>> 
>> The proposal is available here:
>> 
>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
> +1, it needs to happen (and ASAP, since it _will_ introduce 
> source-breaking changes one way or the other).
> 
> I think non-exhaustive is the correct default. However, does this not 
> mean that, by default, enums will be boxed because the receiver doesn’t 
> know their potential size?
 
 It's not always boxing, but yes, there will be more indirection if the 
 compiler can't see the contents of the enum. (More on that below.)
 
 
> That would mean that the best transition path for multi-module Apps would 
> be to make your enums @exhaustive, rather than adding “default” 
> statements (which is unfortunate, because I imagine when this change 
> hits, the way you’ll notice will be complaints about missing “default” 
> statements).
 
 Yep, that's going to be the recommendation. The current minimal-for-review 
 implementation does not do this but I'd like to figure out how to improve 
 that; at the very least it might be a sensible thing to do in the migrator.
 
> 
> I do have some thoughts about how we could ease the transition (for this 
> and other resilience-related changes), but it’s best to leave that to a 
> separate discussion.
> 
> The one thing I’m still not overly fond of is the name - I would like us 
> to keep the set of resilience/optimisation related keywords to a minimum. 
> “exhaustive” for enums feels an awful lot like “fixed_contents” for 
> structs - couldn’t we come up with a single name which could be used for 
> both? I don’t think anybody’s going to want to use “exhaustive” for 
> structs.
 
 The core team was very focused on this too, but I contend that 
 "exhaustive" is not about optimization and really isn't even about 
 "resilience" (i.e. the ability to evolve a library's API while preserving 
 binary compatibility). It's a semantic feature of an enum, much like 
 'open' or 'final' is for classes, and it affects what a client can or 
 can't do with an enum. For libaries compiled from source, it won't affect 
 performance at all—the compiler still knows the full set of cases in the 
 current version of the library even if the programmer is forced to 
 consider future versions.
 
 I'm working on the fixed-contents proposal now, though it won't be ready 
 for a while, and the same thing applies there: for structs compiled from 
 source, the compiler can still do all the same optimizations. It's only 
 when the library has binary compatibility concerns that we need to use 
 extra indirection, and then "fixed-contents" becomes important. (As 
 currently designed, it doesn't affect what clients can do with the struct 
 at all.) This means that I don't expect a "normal" package author to write 
 "fixed-contents" at all (however it ends up being spelled), whereas 
 "exhaustive" is a fairly normal thing to consider whenever you make an 
 enum public.
 
 I hope that convinces you that "fixed-contents" and "exhaustive" don't 
 need to have the same name. I don't think anyone loves the particular name 
 "exhaustive", but as you see in the "Alternatives considered" we didn't 
 manage to come up with anything significantly better. If reviewers all 
 prefer something else we'd consider changing it.
 
 Thanks for responding!
 Jordan
 
>>> 
>>> When you say “libraries compiled from source”, what do you mean?
>> 
>> - Other targets in your project
>> - Source packages built through SwiftPM / CocoaPods / Carthage / other
>> 
>> And I was being imprecise with the terminology, but also

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread David Owens via swift-evolution
I very much agree with the high-level of the proposal. The concept definitely 
needs to exist. However, I feel that the options presented do so in a 
non-intuitive way.

There are two concepts here: closed and open listing of values that make up a 
set of possible options to be used. I think of this much like struct vs. class 
in terms having to determine conceptually which is the right approach for the 
problem you are solving. As such, I feel that this is a significant enough 
difference between the concepts that it warrants a declarative difference via a 
keyword, not just some annotation.

Further, for me personally, putting conditional differences on access level has 
always been a very annoying and frustrating experience in Swift, and this adds 
to that. Using a keyword to distinguish helps with that.

I don’t know the best spelling for, but I’d want something like this:

enumset GregorianWeekday
{ 
case monday // ISO 8601 says weeks start on Monday
case tuesday
case wednesday
case thursday
case friday
case saturday
case sunday
}

That’s the exhaustive list, no others can be added. Access level does not 
matter.

enum Emotions
{
case happy
case sad
case angry
}

This is a non-exhaustive list. Others can be added via extensions. Access level 
does not matter.

-David

> On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution 
>  wrote:
> 
> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs through 
> January 3, 2018.
> 
> The proposal is available here:
> 
> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>  
> 
> Reviews are an important part of the Swift evolution process. All review 
> feedback should be sent to the swift-evolution mailing list at:
> 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 
> or, if you would like to keep your feedback private, directly to the review 
> manager. 
> 
> When replying, please try to keep the proposal link at the top of the message:
> 
> Proposal link: 
> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>  
> 
> ...
> Reply text
> ...
> Other replies
> What goes into a review of a proposal?
> 
> The goal of the review process is to improve the proposal under review 
> through constructive criticism and, eventually, determine the direction of 
> Swift. 
> 
> When reviewing a proposal, here are some questions to consider:
> 
> What is your evaluation of the proposal?
> 
> Is the problem being addressed significant enough to warrant a change to 
> Swift?
> 
> Does this proposal fit well with the feel and direction of Swift?
> 
> If you have used other languages or libraries with a similar feature, how do 
> you feel that this proposal compares to those?
> 
> How much effort did you put into your review? A glance, a quick reading, or 
> an in-depth study?
> 
> Thanks,
> Ted Kremenek
> Review Manager
> ___
> 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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Rex Fenley via swift-evolution
I agree with everything said by Brent Royal-Gordon, however a -1 without
the addition of a `future` case or something similar.

   -

   What is your evaluation of the proposal?

-1, this solution solves a real problem but introduces a very significant
drawback. It should include a solution that preserves exhaustive pattern
matching for the user.

   -

   Is the problem being addressed significant enough to warrant a change to
   Swift?

Yes, absolutely.

   -

   Does this proposal fit well with the feel and direction of Swift?

Feels like 1 step forward and 1 step back. Solves a real problem and
introduces a real new one.

   -

   If you have used other languages or libraries with a similar feature,
   how do you feel that this proposal compares to those?

Rust settled on exhaustive as the default case, signaling the importance of
preserving exhaustive pattern matching. I've run into bugs in Objective-C,
where there is no exhaustive pattern matching, and that's been a pain -
since enums are more powerful in Swift the consequences may be worse.

   -

   How much effort did you put into your review? A glance, a quick reading,
   or an in-depth study?

I've actively participated in previous discussions on the topic, and read
the proposal top-to-bottom for this review. I leverage enums and exhaustive
pattern matching significantly in my own code.

> On Dec 20, 2017, at 10:16 PM, Brent Royal-Gordon via swift-evolution <
swift-evolution@swift.org> wrote:
>
>> On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution <
swift-evolution@swift.org> wrote:
>>
>>  • What is your evaluation of the proposal?
>
> I am pleased with the broad strokes of this design. I have quibbles with
three areas:
>
> 1. The `@exhaustive` attribute may be confusing because the term doesn't
suggest versioning. My best alternative suggestion is `@frozen`, which
matches existing programming terminology: something that has been frozen
will not be changed in the future.
>
> 2. I think we need some kind of `future` keyword in `switch` statements.
Even though a nonexhaustive enum may gain additional cases in the future,
it's still useful for the compiler to diagnose that you forgot *known*
cases.
>
> You say that "switches over non-exhaustive enums should be uncommon", and
this is true for many—perhaps most—non-exhaustive enums, but there is still
a large class of non-exhaustive enums which need to be switched over. These
are the ones I called "category 2" in my previous email in this thread.
`SKPaymentTransactionState` is the example I previously used; others might
include `Stream.Status` (if not exhaustive), `CLAuthorizationStatus`,
`EKParticipantType`, `PKPaymentMethodType`, and `MKMapType`. Each of these
could plausibly have more cases added; each has a good reason why you might
switch over cases (such as display in a user interface); and each ought to
be promptly updated when a new OS version introduces new cases. Without
compiler assistance, those updates won't happen.
>
> If we plan to add private cases in a future version of Swift, `future`
may not be the best keyword. `unknown`, `invalid` (or `case #invalid`),
etc. may be better.
>
> 3. I am very skeptical of treating all enums as exhaustive if imported by
`@testable import`. The only reason I can see not to do this is that
forcing you to provide `default` might hide tests that need to be updated
for new enum cases—but this is the exact problem that `future` is trying to
solve. By contrast, treating them as non-exhaustive forces you to actually
notice when an enum is published as nonexhaustive and consider whether
that's the right approach.
>
> None of these are showstoppers if left unaddressed, but I think the
design would be better if we fixed them.
>
>>  • Is the problem being addressed significant enough to warrant a
change to Swift?
>
> Yes. I have no idea how Swift programs currently behave when a future
framework version adds a case, but I can't imagine they do anything good.
>
>>  • Does this proposal fit well with the feel and direction of Swift?
>
> Yes, with the exception of conflating `default` and `future`, which
removes useful correctness checks.
>
>>  • If you have used other languages or libraries with a similar
feature, how do you feel that this proposal compares to those?
>
> I've experienced bugs in Objective-C caused by the compiler not knowing
an enum might have additional, unknown cases. Debugging them sucked.
>
>>  • How much effort did you put into your review? A glance, a quick
reading, or an in-depth study?
>
> I've participated in multiple rounds of discussion on this topic, and
read the proposal top-to-bottom for this review.
>
> --
> Brent Royal-Gordon
> Architechies
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-- 

Rex Fenley  |  IOS DEVELOPER

Remind.com  |  BLOG 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Matthew Johnson via swift-evolution

> On Dec 21, 2017, at 2:17 PM, John McCall  wrote:
> 
> 
>> On Dec 21, 2017, at 3:10 PM, Matthew Johnson > > wrote:
>> 
>> 
>>> On Dec 21, 2017, at 2:06 PM, John McCall >> > wrote:
>>> 
>>> 
 On Dec 21, 2017, at 2:41 PM, Matthew Johnson > wrote:
 
 
> On Dec 21, 2017, at 1:26 PM, John McCall via swift-evolution 
> > wrote:
> 
>> 
>> On Dec 21, 2017, at 2:03 PM, Jordan Rose via swift-evolution 
>> > wrote:
>> 
>> 
>> 
>>> On Dec 20, 2017, at 12:35, Karl Wagner >> > wrote:
>>> 
>>> 
>>> 
 On 20. Dec 2017, at 19:54, Jordan Rose > wrote:
 
 
 
> On Dec 20, 2017, at 05:36, Karl Wagner via swift-evolution 
> > wrote:
> 
> 
> 
>> On 19. Dec 2017, at 23:58, Ted Kremenek via swift-evolution 
>> > wrote:
>> 
>> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs 
>> through January 3, 2018.
>> 
>> The proposal is available here:
>> 
>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>>  
>> +1,
>>  it needs to happen (and ASAP, since it _will_ introduce 
>> source-breaking changes one way or the other).
> 
> I think non-exhaustive is the correct default. However, does this not 
> mean that, by default, enums will be boxed because the receiver 
> doesn’t know their potential size?
 
 It's not always boxing, but yes, there will be more indirection if the 
 compiler can't see the contents of the enum. (More on that below.)
 
 
> That would mean that the best transition path for multi-module Apps 
> would be to make your enums @exhaustive, rather than adding “default” 
> statements (which is unfortunate, because I imagine when this change 
> hits, the way you’ll notice will be complaints about missing 
> “default” statements).
 
 Yep, that's going to be the recommendation. The current 
 minimal-for-review implementation does not do this but I'd like to 
 figure out how to improve that; at the very least it might be a 
 sensible thing to do in the migrator.
 
> 
> I do have some thoughts about how we could ease the transition (for 
> this and other resilience-related changes), but it’s best to leave 
> that to a separate discussion.
> 
> The one thing I’m still not overly fond of is the name - I would like 
> us to keep the set of resilience/optimisation related keywords to a 
> minimum. “exhaustive” for enums feels an awful lot like 
> “fixed_contents” for structs - couldn’t we come up with a single name 
> which could be used for both? I don’t think anybody’s going to want 
> to use “exhaustive” for structs.
 
 The core team was very focused on this too, but I contend that 
 "exhaustive" is not about optimization and really isn't even about 
 "resilience" (i.e. the ability to evolve a library's API while 
 preserving binary compatibility). It's a semantic feature of an enum, 
 much like 'open' or 'final' is for classes, and it affects what a 
 client can or can't do with an enum. For libaries compiled from 
 source, it won't affect performance at all—the compiler still knows 
 the full set of cases in the current version of the library even if 
 the programmer is forced to consider future versions.
 
 I'm working on the fixed-contents proposal now, though it won't be 
 ready for a while, and the same thing applies there: for structs 
 compiled from source, the compiler can still do all the same 
 optimizations. It's only when the library has binary compatibility 
 concerns that we need to use extra indirection, and then 
 "fixed-contents" becomes important. (As currently designed, it doesn't 
 affect what clients can do with the struct at all.) This means that I 
 don't expect a "normal" package author to write "fixed-contents" at 
 all (however it ends up being spelled), whereas "exhaustive" is 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread John McCall via swift-evolution

> On Dec 21, 2017, at 3:10 PM, Matthew Johnson  wrote:
> 
> 
>> On Dec 21, 2017, at 2:06 PM, John McCall > > wrote:
>> 
>> 
>>> On Dec 21, 2017, at 2:41 PM, Matthew Johnson >> > wrote:
>>> 
>>> 
 On Dec 21, 2017, at 1:26 PM, John McCall via swift-evolution 
 > wrote:
 
> 
> On Dec 21, 2017, at 2:03 PM, Jordan Rose via swift-evolution 
> > wrote:
> 
> 
> 
>> On Dec 20, 2017, at 12:35, Karl Wagner > > wrote:
>> 
>> 
>> 
>>> On 20. Dec 2017, at 19:54, Jordan Rose >> > wrote:
>>> 
>>> 
>>> 
 On Dec 20, 2017, at 05:36, Karl Wagner via swift-evolution 
 > wrote:
 
 
 
> On 19. Dec 2017, at 23:58, Ted Kremenek via swift-evolution 
> > wrote:
> 
> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs 
> through January 3, 2018.
> 
> The proposal is available here:
> 
> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>  
> +1,
>  it needs to happen (and ASAP, since it _will_ introduce 
> source-breaking changes one way or the other).
 
 I think non-exhaustive is the correct default. However, does this not 
 mean that, by default, enums will be boxed because the receiver 
 doesn’t know their potential size?
>>> 
>>> It's not always boxing, but yes, there will be more indirection if the 
>>> compiler can't see the contents of the enum. (More on that below.)
>>> 
>>> 
 That would mean that the best transition path for multi-module Apps 
 would be to make your enums @exhaustive, rather than adding “default” 
 statements (which is unfortunate, because I imagine when this change 
 hits, the way you’ll notice will be complaints about missing “default” 
 statements).
>>> 
>>> Yep, that's going to be the recommendation. The current 
>>> minimal-for-review implementation does not do this but I'd like to 
>>> figure out how to improve that; at the very least it might be a 
>>> sensible thing to do in the migrator.
>>> 
 
 I do have some thoughts about how we could ease the transition (for 
 this and other resilience-related changes), but it’s best to leave 
 that to a separate discussion.
 
 The one thing I’m still not overly fond of is the name - I would like 
 us to keep the set of resilience/optimisation related keywords to a 
 minimum. “exhaustive” for enums feels an awful lot like 
 “fixed_contents” for structs - couldn’t we come up with a single name 
 which could be used for both? I don’t think anybody’s going to want to 
 use “exhaustive” for structs.
>>> 
>>> The core team was very focused on this too, but I contend that 
>>> "exhaustive" is not about optimization and really isn't even about 
>>> "resilience" (i.e. the ability to evolve a library's API while 
>>> preserving binary compatibility). It's a semantic feature of an enum, 
>>> much like 'open' or 'final' is for classes, and it affects what a 
>>> client can or can't do with an enum. For libaries compiled from source, 
>>> it won't affect performance at all—the compiler still knows the full 
>>> set of cases in the current version of the library even if the 
>>> programmer is forced to consider future versions.
>>> 
>>> I'm working on the fixed-contents proposal now, though it won't be 
>>> ready for a while, and the same thing applies there: for structs 
>>> compiled from source, the compiler can still do all the same 
>>> optimizations. It's only when the library has binary compatibility 
>>> concerns that we need to use extra indirection, and then 
>>> "fixed-contents" becomes important. (As currently designed, it doesn't 
>>> affect what clients can do with the struct at all.) This means that I 
>>> don't expect a "normal" package author to write "fixed-contents" at all 
>>> (however it ends up being spelled), whereas "exhaustive" is a fairly 
>>> normal thing to consider whenever you make an enum public.
>>> 
>>> I hope that convinces you that "fixed-contents" and "exhaustive" don't 
>>> need to have the same name. I don't 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Nevin Brackett-Rozinsky via swift-evolution
Making enums non-exhaustive solves a problem for authors of precompiled
frameworks which apps can dynamically link against. These libraries need to
preserve binary compatibility, in the sense that apps should continue to
work with newer versions of the library.

Now, that creates a problem for app developers, wherein the compiler no
longer informs them when their switch statements don’t cover all known enum
cases. This can be solved by introducing “future” for switch statements,
which acts like “default” but will warn if it is provably reachable.

Perhaps the most common scenario, however, is developers who write
multi-module apps. Such apps could include modules with the same author,
modules included as source, and even precompiled binary modules. As long as
these are all bundled with the app, they cannot possibly change out from
under it at runtime, so binary-compatibility is not a concern.

I think it is important that any solution to the problems of dynamically
linked libraries should not adversely impact authors of multi-module apps.

It sounds like John McCall has an approach to handle this with version
locking of dependencies.

Another possibility is to say that public enums are non-exhaustive by
default if the module is built with resilience enabled, but if resilience
is not enabled then enums are exhaustive.

Alternatively, we could introduce a concept of “the entire thing I am
building, including all its statically-linked modules”, and let enums be
exhaustive within that domain while still defaulting to non-exhaustive
outside it.

I am glad to see vigorous debate and brainstorming on this thread, and I am
confident that we will find a good solution.

Nevin



On Thu, Dec 21, 2017 at 2:26 PM, John McCall via swift-evolution <
swift-evolution@swift.org> wrote:

>
> On Dec 21, 2017, at 2:03 PM, Jordan Rose via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
>
> On Dec 20, 2017, at 12:35, Karl Wagner  wrote:
>
>
>
> On 20. Dec 2017, at 19:54, Jordan Rose  wrote:
>
>
>
> On Dec 20, 2017, at 05:36, Karl Wagner via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
>
> On 19. Dec 2017, at 23:58, Ted Kremenek via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs through 
> *January
> 3, 2018*.
>
> The proposal is available here:
>
> https://github.com/apple/swift-evolution/blob/master/
> proposals/0192-non-exhaustive-enums.md
>
> +1, it needs to happen (and ASAP, since it _will_ introduce
> source-breaking changes one way or the other).
>
> I think non-exhaustive is the correct default. However, does this not mean
> that, by default, enums will be boxed because the receiver doesn’t know
> their potential size?
>
>
> It's not always boxing, but yes, there will be more indirection if the
> *compiler* can't see the contents of the enum. (More on that below.)
>
>
> That would mean that the best transition path for multi-module Apps would
> be to make your enums @exhaustive, rather than adding “default” statements
> (which is unfortunate, because I imagine when this change hits, the way
> you’ll notice will be complaints about missing “default” statements).
>
>
> Yep, that's going to be the recommendation. The current minimal-for-review
> implementation does not do this but I'd like to figure out how to improve
> that; at the very least it might be a sensible thing to do in the migrator.
>
>
> I do have some thoughts about how we could ease the transition (for this
> and other resilience-related changes), but it’s best to leave that to a
> separate discussion.
>
> The one thing I’m still not overly fond of is the name - I would like us
> to keep the set of resilience/optimisation related keywords to a minimum.
> “exhaustive” for enums feels an awful lot like “fixed_contents” for structs
> - couldn’t we come up with a single name which could be used for both? I
> don’t think anybody’s going to want to use “exhaustive” for structs.
>
>
> The core team was very focused on this too, but I contend that
> "exhaustive" is not about optimization and really isn't even about
> "resilience" (i.e. the ability to evolve a library's API while preserving
> binary compatibility). It's a semantic feature of an enum, much like 'open'
> or 'final' is for classes, and it affects what a client can or can't do
> with an enum. For libaries compiled from source, it won't affect
> performance at all—the *compiler* still knows the full set of cases in the
>  *current* version of the library even if the programmer is forced to
> consider future versions.
>
> I'm working on the fixed-contents proposal now, though it won't be ready
> for a while, and the same thing applies there: for structs compiled from
> source, the compiler can still do all the same optimizations. It's only
> when the library has binary compatibility concerns that we need to use
> extra indirection, and then "fixed-contents" becomes 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Matthew Johnson via swift-evolution

> On Dec 21, 2017, at 2:06 PM, John McCall  wrote:
> 
> 
>> On Dec 21, 2017, at 2:41 PM, Matthew Johnson > > wrote:
>> 
>> 
>>> On Dec 21, 2017, at 1:26 PM, John McCall via swift-evolution 
>>> > wrote:
>>> 
 
 On Dec 21, 2017, at 2:03 PM, Jordan Rose via swift-evolution 
 > wrote:
 
 
 
> On Dec 20, 2017, at 12:35, Karl Wagner  > wrote:
> 
> 
> 
>> On 20. Dec 2017, at 19:54, Jordan Rose > > wrote:
>> 
>> 
>> 
>>> On Dec 20, 2017, at 05:36, Karl Wagner via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> 
 On 19. Dec 2017, at 23:58, Ted Kremenek via swift-evolution 
 > wrote:
 
 The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs 
 through January 3, 2018.
 
 The proposal is available here:
 
 https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
  
 +1,
  it needs to happen (and ASAP, since it _will_ introduce 
 source-breaking changes one way or the other).
>>> 
>>> I think non-exhaustive is the correct default. However, does this not 
>>> mean that, by default, enums will be boxed because the receiver doesn’t 
>>> know their potential size?
>> 
>> It's not always boxing, but yes, there will be more indirection if the 
>> compiler can't see the contents of the enum. (More on that below.)
>> 
>> 
>>> That would mean that the best transition path for multi-module Apps 
>>> would be to make your enums @exhaustive, rather than adding “default” 
>>> statements (which is unfortunate, because I imagine when this change 
>>> hits, the way you’ll notice will be complaints about missing “default” 
>>> statements).
>> 
>> Yep, that's going to be the recommendation. The current 
>> minimal-for-review implementation does not do this but I'd like to 
>> figure out how to improve that; at the very least it might be a sensible 
>> thing to do in the migrator.
>> 
>>> 
>>> I do have some thoughts about how we could ease the transition (for 
>>> this and other resilience-related changes), but it’s best to leave that 
>>> to a separate discussion.
>>> 
>>> The one thing I’m still not overly fond of is the name - I would like 
>>> us to keep the set of resilience/optimisation related keywords to a 
>>> minimum. “exhaustive” for enums feels an awful lot like 
>>> “fixed_contents” for structs - couldn’t we come up with a single name 
>>> which could be used for both? I don’t think anybody’s going to want to 
>>> use “exhaustive” for structs.
>> 
>> The core team was very focused on this too, but I contend that 
>> "exhaustive" is not about optimization and really isn't even about 
>> "resilience" (i.e. the ability to evolve a library's API while 
>> preserving binary compatibility). It's a semantic feature of an enum, 
>> much like 'open' or 'final' is for classes, and it affects what a client 
>> can or can't do with an enum. For libaries compiled from source, it 
>> won't affect performance at all—the compiler still knows the full set of 
>> cases in the current version of the library even if the programmer is 
>> forced to consider future versions.
>> 
>> I'm working on the fixed-contents proposal now, though it won't be ready 
>> for a while, and the same thing applies there: for structs compiled from 
>> source, the compiler can still do all the same optimizations. It's only 
>> when the library has binary compatibility concerns that we need to use 
>> extra indirection, and then "fixed-contents" becomes important. (As 
>> currently designed, it doesn't affect what clients can do with the 
>> struct at all.) This means that I don't expect a "normal" package author 
>> to write "fixed-contents" at all (however it ends up being spelled), 
>> whereas "exhaustive" is a fairly normal thing to consider whenever you 
>> make an enum public.
>> 
>> I hope that convinces you that "fixed-contents" and "exhaustive" don't 
>> need to have the same name. I don't think anyone loves the particular 
>> name "exhaustive", but as you see in the "Alternatives considered" we 
>> didn't manage to come up with anything significantly better. If 
>> reviewers all prefer 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread John McCall via swift-evolution

> On Dec 21, 2017, at 2:41 PM, Matthew Johnson  wrote:
> 
> 
>> On Dec 21, 2017, at 1:26 PM, John McCall via swift-evolution 
>> > wrote:
>> 
>>> 
>>> On Dec 21, 2017, at 2:03 PM, Jordan Rose via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> 
 On Dec 20, 2017, at 12:35, Karl Wagner > wrote:
 
 
 
> On 20. Dec 2017, at 19:54, Jordan Rose  > wrote:
> 
> 
> 
>> On Dec 20, 2017, at 05:36, Karl Wagner via swift-evolution 
>> > wrote:
>> 
>> 
>> 
>>> On 19. Dec 2017, at 23:58, Ted Kremenek via swift-evolution 
>>> > wrote:
>>> 
>>> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs 
>>> through January 3, 2018.
>>> 
>>> The proposal is available here:
>>> 
>>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>>>  
>>> +1,
>>>  it needs to happen (and ASAP, since it _will_ introduce 
>>> source-breaking changes one way or the other).
>> 
>> I think non-exhaustive is the correct default. However, does this not 
>> mean that, by default, enums will be boxed because the receiver doesn’t 
>> know their potential size?
> 
> It's not always boxing, but yes, there will be more indirection if the 
> compiler can't see the contents of the enum. (More on that below.)
> 
> 
>> That would mean that the best transition path for multi-module Apps 
>> would be to make your enums @exhaustive, rather than adding “default” 
>> statements (which is unfortunate, because I imagine when this change 
>> hits, the way you’ll notice will be complaints about missing “default” 
>> statements).
> 
> Yep, that's going to be the recommendation. The current 
> minimal-for-review implementation does not do this but I'd like to figure 
> out how to improve that; at the very least it might be a sensible thing 
> to do in the migrator.
> 
>> 
>> I do have some thoughts about how we could ease the transition (for this 
>> and other resilience-related changes), but it’s best to leave that to a 
>> separate discussion.
>> 
>> The one thing I’m still not overly fond of is the name - I would like us 
>> to keep the set of resilience/optimisation related keywords to a 
>> minimum. “exhaustive” for enums feels an awful lot like “fixed_contents” 
>> for structs - couldn’t we come up with a single name which could be used 
>> for both? I don’t think anybody’s going to want to use “exhaustive” for 
>> structs.
> 
> The core team was very focused on this too, but I contend that 
> "exhaustive" is not about optimization and really isn't even about 
> "resilience" (i.e. the ability to evolve a library's API while preserving 
> binary compatibility). It's a semantic feature of an enum, much like 
> 'open' or 'final' is for classes, and it affects what a client can or 
> can't do with an enum. For libaries compiled from source, it won't affect 
> performance at all—the compiler still knows the full set of cases in the 
> current version of the library even if the programmer is forced to 
> consider future versions.
> 
> I'm working on the fixed-contents proposal now, though it won't be ready 
> for a while, and the same thing applies there: for structs compiled from 
> source, the compiler can still do all the same optimizations. It's only 
> when the library has binary compatibility concerns that we need to use 
> extra indirection, and then "fixed-contents" becomes important. (As 
> currently designed, it doesn't affect what clients can do with the struct 
> at all.) This means that I don't expect a "normal" package author to 
> write "fixed-contents" at all (however it ends up being spelled), whereas 
> "exhaustive" is a fairly normal thing to consider whenever you make an 
> enum public.
> 
> I hope that convinces you that "fixed-contents" and "exhaustive" don't 
> need to have the same name. I don't think anyone loves the particular 
> name "exhaustive", but as you see in the "Alternatives considered" we 
> didn't manage to come up with anything significantly better. If reviewers 
> all prefer something else we'd consider changing it.
> 
> Thanks for responding!
> Jordan
> 
 
 When you say “libraries compiled from source”, what do you mean?
>>> 
>>> - Other targets in your project

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Goffredo Marocchi via swift-evolution
+1 kind of eye opening looking at it from that angle :/.

Sent from my iPhone

> On 21 Dec 2017, at 18:02, Dave DeLong via swift-evolution 
>  wrote:
> 
> I realized further why we should not implement this proposal: It forces the 
> problem of binary compatibility on the app developer, when experience has 
> shown us that problem is better handled by the libraries.
> 
> Binary Compatibility
> 
> “Binary compatibility” is the notion that, even if the libraries you link 
> against change, your app will still behave as it did when it was first 
> compiled. For Swift apps these days, we don’t really have this problem, 
> *yet*. We do have the problem of “binary compatibility” with Apple-provided 
> frameworks, but those are all written in Objective-C, and so the question of 
> “Swift” binary compatibility is still up-in-the-air.
> 
> Post-ABI stability, we still won’t have much issue with swift binary 
> compatibility on Apple platforms, because there isn’t a mechanism to ship a 
> framework to your users independently of an app update. So from the app POV, 
> none of this will be a problem for Apple platform developers.
> 
> It will be a problem for non-Apple platform developers. As a simple example, 
> let’s say I write a web app in Swift, and deploy it to a server that has some 
> built-in Swift-on-the-server libraries. Here, my Swift app is decoupled from 
> the libraries, and either one can update independently of each other. If the 
> server owner decides to update from Swift 6 to Swift 6.1, that’s cool. But my 
> web app should continue to run and behave *as if* the server were still 
> running Swift 6, because it has not been re-compiled to use Swift 6.1 
> features.
> 
> This is the situation today on Apple platforms. Every app deployed to an 
> Apple device includes a little piece of information in the executable file 
> indicating which SDK was used to compile the app. At runtime, the system 
> frameworks read this value and then alter their behavior accordingly. This is 
> why apps written against the iOS 9 SDK continue to work on iOS 11 devices; 
> UIKit and friends are altering their behavior to provide iOS 9 semantics. 
> 
> This is “binary compatibility”: the binary (your app) continues to be 
> compatible with the dynamically linked frameworks present on the system, even 
> though those frameworks may change.
> 
> When you have a setup where the frameworks do NOT provide binary 
> compatibility, you end up in DLL Hell [1]. This is the same frustrating 
> scenario when you’re in when you’re doing stuff with homebrew and find that 
> this package you want has multiple dependencies, but these dependencies want 
> different versions of the same library. [2]
> 
> Exhaustive Enums
> 
> All of the discussion around exhaustive enums has been from the point-of-view 
> of “what should the behavior be when the libraries change”. Thinking back, 
> I’m actually surprised this is a question at all, because Apple answered this 
> *years* ago: THE BEHAVIOR SHOULD REMAIN UNCHANGED. It is up to the library 
> authors to ensure that they’re doing what the compiled-and-unchanging 
> application is expecting them to do.
> 
> This discussion around exhaustive enums is basically saying “can we force the 
> developers to deal with binary incompatibility?”. We absolutely should not. 
> There are far more app developers than library developers, and it would be a 
> massively wasteful expenditure of engineering effort to force each and every 
> app developer to deal with binary incompatibility, when the library can do it 
> for them. That is the entire *purpose* of having libraries: abstract out a 
> problem so that I, as an app developer, don’t have to spend the effort to do 
> it myself.
> 
> Where We Should Go
> 
> Instead of forcing developers to deal with incompatible libraries, we should 
> be discussing ways to make binary compatibility easier to implement in 
> libraries.
> 
> One of the major problems I struggled with as a UIKit engineer was the 
> presence of huge numbers of “if … else” checks in the code to deal with 
> binary compatibility. It exploded the cyclomatic complexity of the classes 
> and was a major source of technical debt that I struggled to not add to.
> 
> I would love to see some sort of formal API versioning that we could do 
> instead in libraries, along with easy runtime support for checking the linked 
> version of libraries, making it easy to strategize implementations based on 
> version, etc.
> 
> But forcing developers to deal with binary incompatibility is a solution 
> we’ve long known to be a bad one. We should not perpetuate that sin in Swift.
> 
> Dave
> 
> [1]: https://en.wikipedia.org/wiki/DLL_Hell
> [2]: https://en.wikipedia.org/wiki/Dependency_hell
> 
> 
>> On Dec 20, 2017, at 10:23 AM, Dave DeLong via swift-evolution 
>>  wrote:
>> 
>> 
>> 
>>> On Dec 19, 2017, at 3:58 PM, Ted Kremenek via swift-evolution 
>>> 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Ash Furrow via swift-evolution
Okay, thanks Jordan. I appreciate your perspective, and I admit that the 
proposal is technically compelling. My criticism was from a place of respect 
and admiration, and while I may have missed the deeper technical points of the 
proposal, I’ll still caution about how this change will be received by the 
Swift developer community. Proposals like this one could benefit from a 
plain-language explanation that this (as Joe Groff explained on twitter) fixes 
a bug. Maybe even a few more before and after examples? That would help the 
proposal get ahead of any negative reaction.

Ash

-- 
Ash Furrow
https://ashfurrow.com/

On December 21, 2017 at 1:55:40 PM, Jordan Rose (jordan_r...@apple.com) wrote:

Thanks for your response, Ash. Comments inline.


On Dec 20, 2017, at 11:49, Ash Furrow via swift-evolution 
 wrote:

Proposal link: 
https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md

What is your evaluation of the proposal?

-1.

Is the problem being addressed significant enough to warrant a change to Swift?

I’m afraid not.

>From my perspective as a Swift user, this change represents nontrivial 
>language churn without providing a solution to a problem I have. The proposal 
>doesn’t describe any benefits to me as an open source library maintainer or as 
>a Swift developer. With earnest respect, the motivation section reads like 
>“enums grow sometimes, but we like to exhaustively switch over them, so 
>wouldn’t it be cool if …”, which is only a theoretical motivation. It fails to 
>describe how and why this proposal would improve my Swift code or my 
>experience using Swift.

This appears to be a solution to a non-existing problem. I worry that making 
this change will alienate developers from Swift and I caution against accepting 
it.

I wish it were, but unfortunately it's a very real problem. Cases are added to 
Cocoa all the time, and currently it is undefined behavior if one of those 
cases makes it into a switch defined in Swift. ("undefined behavior" = "no 
guarantees of memory safety, type safety, or even which functions are going to 
get invoked in the rest of the function") This is a terrible state of affairs 
that we need to do something about, and "make it a deterministic trap" isn't a 
good enough answer.

We also already know that we have clients that want to add new cases to Swift 
enums without breaking source or binary compatibility: the Apple overlays. It's 
true that this is more of a "theoretical motivation" for source framework 
authors at this time.



Does this proposal fit well with the feel and direction of Swift?

It may have at one time point in time, but not now.

The chaotic churn of the language, the syntax, and the standard library is 
supposed to be behind us. We need to accept that things fell into place as they 
did, often in imperfect ways. We probably could correct all the imperfections, 
but when would we ever stop? Language churn has a cost. This proposal is 
something that I could definitely see being a part of Swift 2 or Swift 3, but 
we have already decided that enums are exhaustive. This change, and changes 
fundamental to the cognitive model Swift programmers already have of their 
tool, need to be heavily weighted against language churn

There's a difference between imperfections that mean something is a bit harder 
to use, or not named the right thing, and imperfections that lead to crashes or 
core capabilities not being expressible. Being able to add cases to enums is 
something Cocoa developers have relied on for years in Objective-C, and so it 
isn't really sensible to not have this feature in Swift. I definitely wish we 
could have gotten to it sooner.



If you have used other languages or libraries with a similar feature, how do 
you feel that this proposal compares to those?

Scala’s match syntax bears a striking resemblance to Swift’s switch syntax; 
however, Scala does not require exhaustive cases. If the developer does not 
include a default case and none of the cases match the expression, an exception 
is thrown. Because of Swift’s error-handling model, I don’t know that this 
behaviour would be desirable either (though I will say it makes sense in Scala).

This is certainly an option; it's in the proposal under "Alternatives 
considered" as 'switch!' (causing a deterministic trap rather than an 
exception). That doesn't seem sufficient to deal with the realities of Cocoa, 
though.

Jordan



How much effort did you put into your review? A glance, a quick reading, or an 
in-depth study?

I read most of the proposal (okay I skimmed some of the nitty-gritty, but I 
read to the end of “Source compatibility”) as well as looked over the 
pre-review threads and skimmed GitHub pull request thread.

-- 
Ash Furrow
https://ashfurrow.com/

On December 19, 2017 at 5:58:14 PM, Ted Kremenek via swift-evolution 
(swift-evolution@swift.org) wrote:

The review of "SE 0192 - Non-Exhaustive Enums" 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Matthew Johnson via swift-evolution

> On Dec 21, 2017, at 1:26 PM, John McCall via swift-evolution 
>  wrote:
> 
>> 
>> On Dec 21, 2017, at 2:03 PM, Jordan Rose via swift-evolution 
>> > wrote:
>> 
>> 
>> 
>>> On Dec 20, 2017, at 12:35, Karl Wagner >> > wrote:
>>> 
>>> 
>>> 
 On 20. Dec 2017, at 19:54, Jordan Rose > wrote:
 
 
 
> On Dec 20, 2017, at 05:36, Karl Wagner via swift-evolution 
> > wrote:
> 
> 
> 
>> On 19. Dec 2017, at 23:58, Ted Kremenek via swift-evolution 
>> > wrote:
>> 
>> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs 
>> through January 3, 2018.
>> 
>> The proposal is available here:
>> 
>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>>  
>> +1,
>>  it needs to happen (and ASAP, since it _will_ introduce source-breaking 
>> changes one way or the other).
> 
> I think non-exhaustive is the correct default. However, does this not 
> mean that, by default, enums will be boxed because the receiver doesn’t 
> know their potential size?
 
 It's not always boxing, but yes, there will be more indirection if the 
 compiler can't see the contents of the enum. (More on that below.)
 
 
> That would mean that the best transition path for multi-module Apps would 
> be to make your enums @exhaustive, rather than adding “default” 
> statements (which is unfortunate, because I imagine when this change 
> hits, the way you’ll notice will be complaints about missing “default” 
> statements).
 
 Yep, that's going to be the recommendation. The current minimal-for-review 
 implementation does not do this but I'd like to figure out how to improve 
 that; at the very least it might be a sensible thing to do in the migrator.
 
> 
> I do have some thoughts about how we could ease the transition (for this 
> and other resilience-related changes), but it’s best to leave that to a 
> separate discussion.
> 
> The one thing I’m still not overly fond of is the name - I would like us 
> to keep the set of resilience/optimisation related keywords to a minimum. 
> “exhaustive” for enums feels an awful lot like “fixed_contents” for 
> structs - couldn’t we come up with a single name which could be used for 
> both? I don’t think anybody’s going to want to use “exhaustive” for 
> structs.
 
 The core team was very focused on this too, but I contend that 
 "exhaustive" is not about optimization and really isn't even about 
 "resilience" (i.e. the ability to evolve a library's API while preserving 
 binary compatibility). It's a semantic feature of an enum, much like 
 'open' or 'final' is for classes, and it affects what a client can or 
 can't do with an enum. For libaries compiled from source, it won't affect 
 performance at all—the compiler still knows the full set of cases in the 
 current version of the library even if the programmer is forced to 
 consider future versions.
 
 I'm working on the fixed-contents proposal now, though it won't be ready 
 for a while, and the same thing applies there: for structs compiled from 
 source, the compiler can still do all the same optimizations. It's only 
 when the library has binary compatibility concerns that we need to use 
 extra indirection, and then "fixed-contents" becomes important. (As 
 currently designed, it doesn't affect what clients can do with the struct 
 at all.) This means that I don't expect a "normal" package author to write 
 "fixed-contents" at all (however it ends up being spelled), whereas 
 "exhaustive" is a fairly normal thing to consider whenever you make an 
 enum public.
 
 I hope that convinces you that "fixed-contents" and "exhaustive" don't 
 need to have the same name. I don't think anyone loves the particular name 
 "exhaustive", but as you see in the "Alternatives considered" we didn't 
 manage to come up with anything significantly better. If reviewers all 
 prefer something else we'd consider changing it.
 
 Thanks for responding!
 Jordan
 
>>> 
>>> When you say “libraries compiled from source”, what do you mean?
>> 
>> - Other targets in your project
>> - Source packages built through SwiftPM / CocoaPods / Carthage / other
>> 
>> And I was being imprecise with the terminology, but also
>> 
>> - Libraries built by someone else but designed to be embedded into an app, 
>> so 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread John McCall via swift-evolution

> On Dec 21, 2017, at 2:03 PM, Jordan Rose via swift-evolution 
>  wrote:
> 
> 
> 
>> On Dec 20, 2017, at 12:35, Karl Wagner > > wrote:
>> 
>> 
>> 
>>> On 20. Dec 2017, at 19:54, Jordan Rose >> > wrote:
>>> 
>>> 
>>> 
 On Dec 20, 2017, at 05:36, Karl Wagner via swift-evolution 
 > wrote:
 
 
 
> On 19. Dec 2017, at 23:58, Ted Kremenek via swift-evolution 
> > wrote:
> 
> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs 
> through January 3, 2018.
> 
> The proposal is available here:
> 
> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>  
> +1,
>  it needs to happen (and ASAP, since it _will_ introduce source-breaking 
> changes one way or the other).
 
 I think non-exhaustive is the correct default. However, does this not mean 
 that, by default, enums will be boxed because the receiver doesn’t know 
 their potential size?
>>> 
>>> It's not always boxing, but yes, there will be more indirection if the 
>>> compiler can't see the contents of the enum. (More on that below.)
>>> 
>>> 
 That would mean that the best transition path for multi-module Apps would 
 be to make your enums @exhaustive, rather than adding “default” statements 
 (which is unfortunate, because I imagine when this change hits, the way 
 you’ll notice will be complaints about missing “default” statements).
>>> 
>>> Yep, that's going to be the recommendation. The current minimal-for-review 
>>> implementation does not do this but I'd like to figure out how to improve 
>>> that; at the very least it might be a sensible thing to do in the migrator.
>>> 
 
 I do have some thoughts about how we could ease the transition (for this 
 and other resilience-related changes), but it’s best to leave that to a 
 separate discussion.
 
 The one thing I’m still not overly fond of is the name - I would like us 
 to keep the set of resilience/optimisation related keywords to a minimum. 
 “exhaustive” for enums feels an awful lot like “fixed_contents” for 
 structs - couldn’t we come up with a single name which could be used for 
 both? I don’t think anybody’s going to want to use “exhaustive” for 
 structs.
>>> 
>>> The core team was very focused on this too, but I contend that "exhaustive" 
>>> is not about optimization and really isn't even about "resilience" (i.e. 
>>> the ability to evolve a library's API while preserving binary 
>>> compatibility). It's a semantic feature of an enum, much like 'open' or 
>>> 'final' is for classes, and it affects what a client can or can't do with 
>>> an enum. For libaries compiled from source, it won't affect performance at 
>>> all—the compiler still knows the full set of cases in the current version 
>>> of the library even if the programmer is forced to consider future versions.
>>> 
>>> I'm working on the fixed-contents proposal now, though it won't be ready 
>>> for a while, and the same thing applies there: for structs compiled from 
>>> source, the compiler can still do all the same optimizations. It's only 
>>> when the library has binary compatibility concerns that we need to use 
>>> extra indirection, and then "fixed-contents" becomes important. (As 
>>> currently designed, it doesn't affect what clients can do with the struct 
>>> at all.) This means that I don't expect a "normal" package author to write 
>>> "fixed-contents" at all (however it ends up being spelled), whereas 
>>> "exhaustive" is a fairly normal thing to consider whenever you make an enum 
>>> public.
>>> 
>>> I hope that convinces you that "fixed-contents" and "exhaustive" don't need 
>>> to have the same name. I don't think anyone loves the particular name 
>>> "exhaustive", but as you see in the "Alternatives considered" we didn't 
>>> manage to come up with anything significantly better. If reviewers all 
>>> prefer something else we'd consider changing it.
>>> 
>>> Thanks for responding!
>>> Jordan
>>> 
>> 
>> When you say “libraries compiled from source”, what do you mean?
> 
> - Other targets in your project
> - Source packages built through SwiftPM / CocoaPods / Carthage / other
> 
> And I was being imprecise with the terminology, but also
> 
> - Libraries built by someone else but designed to be embedded into an app, so 
> that there's no chance of a different version showing up at run-time.
> 
>> 
>> As for whether its a resilience feature: actually it is completely a 
>> resilience feature. The effects on switching are only side-effects; really 
>> what “exhaustive” or 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Jordan Rose via swift-evolution


> On Dec 20, 2017, at 12:54, Charlie Monroe  wrote:
> 
> I think that the main confusion here stems from the word library as we are 
> addressing something that can be divided further (and this is IMHO as many 
> macOS/iOS devs see it):
> 
> - libraries that come with the OS - here, it absolutely makes sense to make 
> the enums non-exhaustive as the apps are linked against these libraries and 
> the user installs a binary that will load these at launch and they are not 
> bundled with the app - the developer can't control future OS releases and he 
> wants the app to run on a future OS release.
> - libraries that are bundled with the app - be it PM, CocoaPods or something 
> else - you typically update your dependencies once in a while and they 
> change. And you want to be notified by the compiler about possible changes - 
> extended enums, in this case. Because let's be honest - if your app has a 
> dozen dependencies and you come to the app after a year of no development, 
> Swift 5 came along during that period, you want to update these libraries to 
> Swift-5-compatible versions. And no one has the time to go through all change 
> logs - even if they were kept up-to-date and thorough, which I can't say that 
> I've seen in many instances.
> 
> I know that this is a limited view from the perspective of an app developer 
> and that potentially, e.g. on Linux, there may be libraries written in Swift 
> that you may want to install via package managers and depend on them once the 
> ABI is stable, but the choice to make them non-exhaustive by default is not 
> in line with everything else in Swift - everything else is generally closed 
> by default - public (-> final in other modules), no access modified (-> 
> internal), ...
> 
> For me, it's a -1 as it is now. I'd prefer exhaustive-by-default, 
> ObjC/C-import non-exhaustive by default (the way ObjC classes are open by 
> default vs. public). When it comes to the switch statement, there definitely 
> needs to be an option to make an exhaustive switch over all 
> compile-time-known values with a warning shall a new one be added. Without 
> that, the code will become incredibly prone to errors and hard to maintain.

This does bring up another option, which is to differentiate Apple-provided 
libraries (and in general, libraries with binary compatibility concerns, i.e. 
libraries that may be different at run-time from what you compiled against) 
from bundled / built-from-source libraries. Slava and I have been very leery of 
this because it fragments the language into dialects, and has the potential to 
confuse people when they try to write code that behaves like an Apple 
framework, but I suppose it is an option.

Jordan


> 
>> On Dec 20, 2017, at 9:35 PM, Karl Wagner via swift-evolution 
>> > wrote:
>> 
>> 
>> 
>>> On 20. Dec 2017, at 19:54, Jordan Rose >> > wrote:
>>> 
>>> 
>>> 
 On Dec 20, 2017, at 05:36, Karl Wagner via swift-evolution 
 > wrote:
 
 
 
> On 19. Dec 2017, at 23:58, Ted Kremenek via swift-evolution 
> > wrote:
> 
> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs 
> through January 3, 2018.
> 
> The proposal is available here:
> 
> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>  
> +1,
>  it needs to happen (and ASAP, since it _will_ introduce source-breaking 
> changes one way or the other).
 
 I think non-exhaustive is the correct default. However, does this not mean 
 that, by default, enums will be boxed because the receiver doesn’t know 
 their potential size?
>>> 
>>> It's not always boxing, but yes, there will be more indirection if the 
>>> compiler can't see the contents of the enum. (More on that below.)
>>> 
>>> 
 That would mean that the best transition path for multi-module Apps would 
 be to make your enums @exhaustive, rather than adding “default” statements 
 (which is unfortunate, because I imagine when this change hits, the way 
 you’ll notice will be complaints about missing “default” statements).
>>> 
>>> Yep, that's going to be the recommendation. The current minimal-for-review 
>>> implementation does not do this but I'd like to figure out how to improve 
>>> that; at the very least it might be a sensible thing to do in the migrator.
>>> 
 
 I do have some thoughts about how we could ease the transition (for this 
 and other resilience-related changes), but it’s best to leave that to a 
 separate discussion.
 
 The one thing I’m still not overly fond of is the name - I 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Jordan Rose via swift-evolution


> On Dec 20, 2017, at 12:52, Colin Barrett  wrote:
> 
> 
>> On Dec 20, 2017, at 1:36 PM, Jordan Rose > > wrote:
>> 
>> Thanks for the links, Colin. I think neither of these approaches are 
>> appropriate for Swift, largely for the same reason: they can't be used to 
>> define a library's API. Polymorphic variants are ad-hoc union types (much 
>> like tuples are ad-hoc structs) which—apart from having other problems in 
>> Swift previously discussed on this list—means that you can't add new cases 
>> to them. That is, any API which takes `(red(r: Int) | green(g: Int) | 
>> blue(b: Int))` today can't add `alpha(a: Int)` in the future, because that 
>> would change the type.
>  
> It would change the type yes, but not in a binary incompatible way. Imagine 
> this for the OS version, using OCaml pseudocode
> 
> type VERS = [> `10_0 | `10_1 | … | `10_13 ]
> 
> Then, next year, you’d change VERS to be,
> 
> type VERS = [> `10_0 | `10_1 | … | `10_13 | `10_14 ]
> 
> Any code that dealt with a VERS would still work, as it had to handle that it 
> could contain other tags.

Sorry, I had this worked out in my head but then didn't put it into the email 
correctly! The sticking point is that Swift allows overloads by type, which 
means that argument types have to go into the mangled name of the function. 
(Another way to think of this is to say "to uniquely identify a function across 
releases, you must know its argument and return types as well as its full 
name".) That means that we can't just add a new case into the type, because it 
would change the function's type.

Okay, but what if VERS were an actual new type rather than just a typealias? 
Well, then you have a non-exhaustive enum.

(David Owens brought up on Twitter today that it could be a different kind of 
declaration rather than 'enum'. My response 
 was that that could 
work, but you end up in a worse case where (a) the two declarations are 
equivalent when they're not public, and (b) it's still easy to use the wrong 
one, especially going from Swift 1-4 habits.)


> 
>> ML-style exceptions have the opposite problem; they are completely 
>> unconstrained and so a client can add new "cases" without the library author 
>> being prepared. (Swift's error-handling model in general behaves a lot like 
>> this, except it doesn't get ML's knowledge of which errors might be thrown.)
> 
> Yes, I was imagining that this would be for something with an OCaml type like 
> [> ]  or TOP, which I don’t believe is a thing? My OCaml-fu is quite weak.
> 
>> I'd sum this up by saying Swift is differing from ML and from most other 
>> languages because it is solving a different problem. Swift is designed such 
>> that the compiler does not require whole-program knowledge to produce a 
>> correct, working, type-safe program. It will use any cross-module knowledge 
>> it can for optimization purposes, but the language semantics do not depend 
>> on it. And this is critical, as you note, for libraries with binary 
>> compatibility concerns.
> 
> That is… not different from ML? ML’s modules have precisely this properly, do 
> they not? Or am I misunderstanding what you’re saying here.

ML modules provide separation of concerns, but as far as I know they can't 
actually be swapped out at runtime, and if someone were to do this they 
wouldn't be allowed to add a new variant to an existing datatype.


> Thanks for the reply, it’s appreciated! Hope you’re well in California, 
> envious of your weather trudging thru the snow here in NYC.

Happy holidays, Colin, and everyone else on the list. :-)

Jordan


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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Jordan Rose via swift-evolution
Thanks for your comments, Jon. Responses inline.

> On Dec 20, 2017, at 12:46, Jonathan Hull  wrote:
> 
> 
>> On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution 
>> > wrote:
>> When reviewing a proposal, here are some questions to consider:
>> 
>> What is your evaluation of the proposal?
>> 
> Strong -1 as is.
> 
> I think I would support having an explicit ‘futureCase’ which is different 
> from ‘default’.  Requiring default is asking for bugs.  With a separate 
> ‘futureCase’, we would still get a compile-time error when all of the current 
> cases aren’t handled.  Note that ‘ futureCase’ is also different than 
> ‘default’ in that it wouldn’t have to go at the bottom.  It would only be 
> triggered when the value isn’t one of the values which was known at compile 
> time.  We should also bike shed the name of ‘futureCase’ to come up with 
> something that might allow us to make other types of extendable enums….  
> Maybe something like ‘unknownCase’ or ‘unexpectedCase’.
> 
> As for the issue of testing, we could add (later) a universally unexpected 
> case that non-exhaustive enums can be set to for testing. I am not convinced 
> that this is actually a big enough issue to warrant that though. Forcing 
> ‘default’ is a much larger real-world problem, IMO (and this use of ‘default’ 
> is just as untestable).

Both of these are discussed in "Alternatives considered", and they have flaws 
that led me to leave them out of the proposal. Do you have any ideas on how to 
improve on that?

> 
> I also dislike the name @exhaustive because I think it will cause confusion 
> (i.e. “Of course my Enum is exhaustive”).  I think we should just have @fixed 
> for both enums and structs. The word fixed has the connotation that it 
> shouldn’t change.

I don't think anybody loves "exhaustive", but using the same attribute for 
enums and structs isn't really appropriate, as discussed in my response to Karl 
yesterday 
.
 I'm not opposed to a better name if we can gravitate towards one, though.

Jordan



> 
>> Is the problem being addressed significant enough to warrant a change to 
>> Swift?
>> 
> Yes, I think the problem is significant, but this is not the correct solution.
>> Does this proposal fit well with the feel and direction of Swift?
>> 
> Not quite.  While I think ABI safety is Swifty, I feel like this design 
> actually encourages a lack of safety in other areas.  Much better to 
> explicitly deal with the issue of added/future cases in code than to hide it 
> with ‘default’.
> 
>> If you have used other languages or libraries with a similar feature, how do 
>> you feel that this proposal compares to those?
>> 
> I have used Enums in several languages, but Swift is the only one which has 
> required exhaustive enums… I have a hard time going back to languages which 
> don’t have it now.
> 
>> How much effort did you put into your review? A glance, a quick reading, or 
>> an in-depth study?
>> 
> Thoroughly read proposal, casually followed the original discussion.
> 
> Thanks,
> Jon
> 
> 

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Jordan Rose via swift-evolution


> On Dec 20, 2017, at 12:35, Karl Wagner  wrote:
> 
> 
> 
>> On 20. Dec 2017, at 19:54, Jordan Rose > > wrote:
>> 
>> 
>> 
>>> On Dec 20, 2017, at 05:36, Karl Wagner via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> 
 On 19. Dec 2017, at 23:58, Ted Kremenek via swift-evolution 
 > wrote:
 
 The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs through 
 January 3, 2018.
 
 The proposal is available here:
 
 https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
  
 +1,
  it needs to happen (and ASAP, since it _will_ introduce source-breaking 
 changes one way or the other).
>>> 
>>> I think non-exhaustive is the correct default. However, does this not mean 
>>> that, by default, enums will be boxed because the receiver doesn’t know 
>>> their potential size?
>> 
>> It's not always boxing, but yes, there will be more indirection if the 
>> compiler can't see the contents of the enum. (More on that below.)
>> 
>> 
>>> That would mean that the best transition path for multi-module Apps would 
>>> be to make your enums @exhaustive, rather than adding “default” statements 
>>> (which is unfortunate, because I imagine when this change hits, the way 
>>> you’ll notice will be complaints about missing “default” statements).
>> 
>> Yep, that's going to be the recommendation. The current minimal-for-review 
>> implementation does not do this but I'd like to figure out how to improve 
>> that; at the very least it might be a sensible thing to do in the migrator.
>> 
>>> 
>>> I do have some thoughts about how we could ease the transition (for this 
>>> and other resilience-related changes), but it’s best to leave that to a 
>>> separate discussion.
>>> 
>>> The one thing I’m still not overly fond of is the name - I would like us to 
>>> keep the set of resilience/optimisation related keywords to a minimum. 
>>> “exhaustive” for enums feels an awful lot like “fixed_contents” for structs 
>>> - couldn’t we come up with a single name which could be used for both? I 
>>> don’t think anybody’s going to want to use “exhaustive” for structs.
>> 
>> The core team was very focused on this too, but I contend that "exhaustive" 
>> is not about optimization and really isn't even about "resilience" (i.e. the 
>> ability to evolve a library's API while preserving binary compatibility). 
>> It's a semantic feature of an enum, much like 'open' or 'final' is for 
>> classes, and it affects what a client can or can't do with an enum. For 
>> libaries compiled from source, it won't affect performance at all—the 
>> compiler still knows the full set of cases in the current version of the 
>> library even if the programmer is forced to consider future versions.
>> 
>> I'm working on the fixed-contents proposal now, though it won't be ready for 
>> a while, and the same thing applies there: for structs compiled from source, 
>> the compiler can still do all the same optimizations. It's only when the 
>> library has binary compatibility concerns that we need to use extra 
>> indirection, and then "fixed-contents" becomes important. (As currently 
>> designed, it doesn't affect what clients can do with the struct at all.) 
>> This means that I don't expect a "normal" package author to write 
>> "fixed-contents" at all (however it ends up being spelled), whereas 
>> "exhaustive" is a fairly normal thing to consider whenever you make an enum 
>> public.
>> 
>> I hope that convinces you that "fixed-contents" and "exhaustive" don't need 
>> to have the same name. I don't think anyone loves the particular name 
>> "exhaustive", but as you see in the "Alternatives considered" we didn't 
>> manage to come up with anything significantly better. If reviewers all 
>> prefer something else we'd consider changing it.
>> 
>> Thanks for responding!
>> Jordan
>> 
> 
> When you say “libraries compiled from source”, what do you mean?

- Other targets in your project
- Source packages built through SwiftPM / CocoaPods / Carthage / other

And I was being imprecise with the terminology, but also

- Libraries built by someone else but designed to be embedded into an app, so 
that there's no chance of a different version showing up at run-time.

> 
> As for whether its a resilience feature: actually it is completely a 
> resilience feature. The effects on switching are only side-effects; really 
> what “exhaustive” or “nonexhaustive” are saying is literally that cases may 
> be added later. Even if we added private cases, you wouldn’t need to mark 
> those enums as specially exhaustive or not; that would be implied. It’s an 
> accommodation for things which don’t exist yet, so 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Jordan Rose via swift-evolution
Thanks for your response, Ash. Comments inline.


> On Dec 20, 2017, at 11:49, Ash Furrow via swift-evolution 
>  wrote:
> 
> Proposal link: 
> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>  
> 
> 
> What is your evaluation of the proposal?
> 
> -1.
> 
> Is the problem being addressed significant enough to warrant a change to 
> Swift?
> 
> I’m afraid not.
> 
> From my perspective as a Swift user, this change represents nontrivial 
> language churn without providing a solution to a problem I have. The proposal 
> doesn’t describe any benefits to me as an open source library maintainer or 
> as a Swift developer. With earnest respect, the motivation section reads like 
> “enums grow sometimes, but we like to exhaustively switch over them, so 
> wouldn’t it be cool if …”, which is only a theoretical motivation. It fails 
> to describe how and why this proposal would improve my Swift code or my 
> experience using Swift.
> 
> This appears to be a solution to a non-existing problem. I worry that making 
> this change will alienate developers from Swift and I caution against 
> accepting it.
> 
I wish it were, but unfortunately it's a very real problem. Cases are added to 
Cocoa all the time, and currently it is undefined behavior if one of those 
cases makes it into a switch defined in Swift. ("undefined behavior" = "no 
guarantees of memory safety, type safety, or even which functions are going to 
get invoked in the rest of the function") This is a terrible state of affairs 
that we need to do something about, and "make it a deterministic trap" isn't a 
good enough answer.

We also already know that we have clients that want to add new cases to Swift 
enums without breaking source or binary compatibility: the Apple overlays. It's 
true that this is more of a "theoretical motivation" for source framework 
authors at this time.



> Does this proposal fit well with the feel and direction of Swift?
> 
> It may have at one time point in time, but not now.
> 
> The chaotic churn of the language, the syntax, and the standard library is 
> supposed to be behind us. We need to accept that things fell into place as 
> they did, often in imperfect ways. We probably could correct all the 
> imperfections, but when would we ever stop? Language churn has a cost. This 
> proposal is something that I could definitely see being a part of Swift 2 or 
> Swift 3, but we have already decided that enums are exhaustive. This change, 
> and changes fundamental to the cognitive model Swift programmers already have 
> of their tool, need to be heavily weighted against language churn

There's a difference between imperfections that mean something is a bit harder 
to use, or not named the right thing, and imperfections that lead to crashes or 
core capabilities not being expressible. Being able to add cases to enums is 
something Cocoa developers have relied on for years in Objective-C, and so it 
isn't really sensible to not have this feature in Swift. I definitely wish we 
could have gotten to it sooner.


> 
> If you have used other languages or libraries with a similar feature, how do 
> you feel that this proposal compares to those?
> 
> Scala’s match syntax bears a striking resemblance to Swift’s switch syntax; 
> however, Scala does not require exhaustive cases. If the developer does not 
> include a default case and none of the cases match the expression, an 
> exception is thrown. Because of Swift’s error-handling model, I don’t know 
> that this behaviour would be desirable either (though I will say it makes 
> sense in Scala).

This is certainly an option; it's in the proposal under "Alternatives 
considered" as 'switch!' (causing a deterministic trap rather than an 
exception). That doesn't seem sufficient to deal with the realities of Cocoa, 
though.

Jordan


> 
> How much effort did you put into your review? A glance, a quick reading, or 
> an in-depth study?
> 
> I read most of the proposal (okay I skimmed some of the nitty-gritty, but I 
> read to the end of “Source compatibility”) as well as looked over the 
> pre-review threads and skimmed GitHub pull request thread.
> 
> -- 
> Ash Furrow
> https://ashfurrow.com/ 
> On December 19, 2017 at 5:58:14 PM, Ted Kremenek via swift-evolution 
> (swift-evolution@swift.org ) wrote:
> 
>> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs through 
>> January 3, 2018.
>> 
>> The proposal is available here:
>> 
>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>>  
>> 
>> Reviews are an important part of the Swift evolution process. All review 
>> feedback should be sent to the swift-evolution mailing 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Dave DeLong via swift-evolution
I realized further why we should not implement this proposal: It forces the 
problem of binary compatibility on the app developer, when experience has shown 
us that problem is better handled by the libraries.

Binary Compatibility

“Binary compatibility” is the notion that, even if the libraries you link 
against change, your app will still behave as it did when it was first 
compiled. For Swift apps these days, we don’t really have this problem, *yet*. 
We do have the problem of “binary compatibility” with Apple-provided 
frameworks, but those are all written in Objective-C, and so the question of 
“Swift” binary compatibility is still up-in-the-air.

Post-ABI stability, we still won’t have much issue with swift binary 
compatibility on Apple platforms, because there isn’t a mechanism to ship a 
framework to your users independently of an app update. So from the app POV, 
none of this will be a problem for Apple platform developers.

It will be a problem for non-Apple platform developers. As a simple example, 
let’s say I write a web app in Swift, and deploy it to a server that has some 
built-in Swift-on-the-server libraries. Here, my Swift app is decoupled from 
the libraries, and either one can update independently of each other. If the 
server owner decides to update from Swift 6 to Swift 6.1, that’s cool. But my 
web app should continue to run and behave *as if* the server were still running 
Swift 6, because it has not been re-compiled to use Swift 6.1 features.

This is the situation today on Apple platforms. Every app deployed to an Apple 
device includes a little piece of information in the executable file indicating 
which SDK was used to compile the app. At runtime, the system frameworks read 
this value and then alter their behavior accordingly. This is why apps written 
against the iOS 9 SDK continue to work on iOS 11 devices; UIKit and friends are 
altering their behavior to provide iOS 9 semantics. 

This is “binary compatibility”: the binary (your app) continues to be 
compatible with the dynamically linked frameworks present on the system, even 
though those frameworks may change.

When you have a setup where the frameworks do NOT provide binary compatibility, 
you end up in DLL Hell [1]. This is the same frustrating scenario when you’re 
in when you’re doing stuff with homebrew and find that this package you want 
has multiple dependencies, but these dependencies want different versions of 
the same library. [2]

Exhaustive Enums

All of the discussion around exhaustive enums has been from the point-of-view 
of “what should the behavior be when the libraries change”. Thinking back, I’m 
actually surprised this is a question at all, because Apple answered this 
*years* ago: THE BEHAVIOR SHOULD REMAIN UNCHANGED. It is up to the library 
authors to ensure that they’re doing what the compiled-and-unchanging 
application is expecting them to do.

This discussion around exhaustive enums is basically saying “can we force the 
developers to deal with binary incompatibility?”. We absolutely should not. 
There are far more app developers than library developers, and it would be a 
massively wasteful expenditure of engineering effort to force each and every 
app developer to deal with binary incompatibility, when the library can do it 
for them. That is the entire *purpose* of having libraries: abstract out a 
problem so that I, as an app developer, don’t have to spend the effort to do it 
myself.

Where We Should Go

Instead of forcing developers to deal with incompatible libraries, we should be 
discussing ways to make binary compatibility easier to implement in libraries.

One of the major problems I struggled with as a UIKit engineer was the presence 
of huge numbers of “if … else” checks in the code to deal with binary 
compatibility. It exploded the cyclomatic complexity of the classes and was a 
major source of technical debt that I struggled to not add to.

I would love to see some sort of formal API versioning that we could do instead 
in libraries, along with easy runtime support for checking the linked version 
of libraries, making it easy to strategize implementations based on version, 
etc.

But forcing developers to deal with binary incompatibility is a solution we’ve 
long known to be a bad one. We should not perpetuate that sin in Swift.

Dave

[1]: https://en.wikipedia.org/wiki/DLL_Hell 

[2]: https://en.wikipedia.org/wiki/Dependency_hell 



> On Dec 20, 2017, at 10:23 AM, Dave DeLong via swift-evolution 
>  wrote:
> 
> 
> 
>> On Dec 19, 2017, at 3:58 PM, Ted Kremenek via swift-evolution 
>> > wrote:
>> 
>> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs through 
>> January 3, 2018.
>> 
>> The proposal is available here:
>> 
>> 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Kevin Nattinger via swift-evolution
> On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution 
>  wrote:
> 
> The review of "SE 0192 - Non-Exhaustive Enums" begins now and runs through 
> January 3, 2018.
> 
> The proposal is available here:
> 
> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>  
> 
> What is your evaluation of the proposal?
> 
I was going to say -100 without future, +1 with, but other arguments on this 
thread have put me on the fence to mildly against, so -100 without future, -ε 
with.


In the proposal, there is the following text:
> The consequences of losing exhaustiveness checking for non-exhaustive enums 
> are discussed in the "Alternatives considered" section at the end of this 
> proposal.
> 
> A number of pre-reviewers have been concerned about the loss of 
> exhaustiveness checking and the subsequent difficulty in updating to a new 
> version of a dependency. In the original swift-evolution thread, Vladimir S. 
> describes the concerning scenario 
> 
>  in detail.
I find it deeply disturbing that this scenario is acknowledged as "concerning" 
and yet ignored without justification in the proposal proper, and in the 
"alternatives" dismissed solely based on a baseless assumption—that the 
situation will be "uncommon." Even if it were an uncommon case, the negative 
impact is still dire enough and without a good workaround that I'd argue 
strongly that the concern be addressed properly.

The justification put forward to reject a `future` case is that "The 
expectation is that switches over non-exhaustive enums are uncommon." However, 
there is no evidence to support that assertion, and there are a huge number of 
enums in even just Apple's frameworks that people reasonably can, and in some 
cases really should, switch over. Go through any of the iOS frameworks and find 
authorization enums and delegates with enums in a callback, and you're likely 
to find some that it makes sense for a client to switch over. Just a few off 
the top of my head that I have personally switched on:

CoreBluetooth
- CBManagerState
- CBPeripheralManagerAuthorizationStatus
- CBPeripheralState
CoreLocation
- CLAuthorizationStatus
- CLActivityType
CoreData
- NSFetchedResultsChangeType
MessageUI
- MessageComposeResult
UIKit
- UITableViewCellEditingStyle

Every framework that requires user permission has its own authorization enum, 
many have an additional state enum, and for most delegate callbacks with an 
enum argument it's often a good idea to switch over the cases.

As a real-life example above and beyond the one referenced above, In the fairly 
small codebase I'm working in at the moment, I count a bit over 12klocs, 80-ish 
switches, and 6 switches that would need a `future` case (non-exhaustive, from 
Apple frameworks). That's about one per 2klocs, It probably wouldn't scale 
linearly in larger projects, but just their prevalence in the apple frameworks 
as I pointed out above would suggest it does grow significantly.

The extra onus on project authors required by not including a future case for 
those cases would make upgrading libraries and iOS versions incredibly 
difficult and error-prone. To ensure correctness, you would have to go over 
every single switch in your app, figure out the type it's switching on, and if 
the type is external and nonexhaustive, check that there are no new cases. Even 
if this is "not expected to be the common case," omitting the `future` means 
you have to either keep track of where all your relevant switch statements are 
and check them on every upgrade, go through and evaluate every switch statement 
to figure out whether you need to check for extra cases, or go through the API 
diff, find any added enum cases, and find every switch in your codebase that 
switches on them. All three options are dangerously error-prone and 
unacceptable.

In summary, failing to include a future case but requiring default instead 
would place an unacceptable burden on every nontrivial project every time a 
library is upgraded and (and I don't say this lightly) would almost certainly 
be the biggest mistake the Swift community has ever made.

There is an existing implementation along with the PR, so has anyone tried this 
change a project of significant size that uses a variety of Apple frameworks? 
How many `default`s did you have to put in that should be `future`, and how 
would you feel about having to find all those places again and any more that 
may be put in in a year or two *without* compiler checking?
> Is the problem being addressed significant enough to warrant a change to 
> Swift?
> 
The problem needs to be addressed, certainly.
> Does this proposal fit well with the feel and direction of Swift?
> 
With future, sure. Without, absolutely not. As demonstrated 

  1   2   >