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 
> <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 <razie...@gmail.com> wrote:
>>>> 
>>>> 
>>>> 
>>>>> On 20. Dec 2017, at 19:54, Jordan Rose <jordan_r...@apple.com> 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 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 really, it is all about 
>>> resilience IMO.
>> 
>> "Resilience", as an admittedly fuzzily-defined term in the Swift project, 
>> specifically refers to what changes can be made without breaking binary 
>> compatibility. It does not refer to every change you can make to a library. 
>> (For comparison, adding a field to a struct is not source-breaking in Swift. 
>> We would like to make it not ABI-breaking either; that proposal's coming 
>> soon.)
>> 
>> 
>>> 
>>> Anyway, as I see it, library authors in general ought to be happy about 
>>> this:
>>> + Their libraries become safer by default, so they can make changes in the 
>>> future without having to worry about breakage
>>> + It doesn’t affect your code inside of a module, so it only affects types 
>>> they already explicitly marked “public”
>> 
>> That's the intent.
>> 
>>> 
>>> The only people who lose are multi-module App developers, because they are 
>>> “library authors” who don’t need to care about evolution, and now need to 
>>> add attributes to things they wouldn’t have to before, or suffer language 
>>> and performance penalties. Their libraries become less reusable and not 
>>> resilient-by-default.
>>> 
>>> For example, I have an App for which I wrote a cross-platform model 
>>> framework in Swift. When I compile it as a framework inside my App, it is 
>>> bundled there forever. However, I use the same code to build libraries for 
>>> Linux, which I would like to ship in binary form to 3rd-parties. Am I 
>>> supposed to litter my code with annotations to mark those types as final, 
>>> just to make the App fast and convenient to code? What happens when I need 
>>> to fix a bug and distribute an updated copy, this means the 3rd-parties 
>>> need to recompile (which they won’t do…).
>>> 
>>> Typically, for such a problem, I would recommend using a static library 
>>> instead. But we don’t have those, and anyway they’re not always the best 
>>> thing these days. So that’s why I started a new thread about creating a 
>>> “@static” import, so App developers can go back to all the conveniences 
>>> they had before.
>> 
>> There won't be a perf penalty, but yes, I do expect multi-module apps to use 
>> 'exhaustive' on most of their enums, because they don't need the 
>> futureproofing. Maybe this should have been mentioned more explicitly in the 
>> proposal.
> 
> As a perhaps more long-term design note, I think modules ought to have the 
> ability to version-lock themselves to one or more of their dependencies.  
> They would still be required to obey access control as if they were outside 
> those dependencies, but we would suppress some of the semantic consequences 
> of being outside the module, such as the need to assume non-exhaustiveness by 
> default.
> 
> That is, there would be two independent axes of library dependency: source 
> vs. binary and version-compatible vs. version-locked:
>   - a source dependency allows the compiler to take advantage of the 
> implementation of public entities when generating code
>   - a version-locked dependency allows the compiler to take advantage of the 
> implementation of public entities when enforcing semantics
> 
> Apps would generally elect to primarily use version-locked source 
> dependencies because they're just pulling down source libraries (e.g. from 
> github) and are comfortable with updating their code if the library changes.
> 
> Source libraries on github would generally want to use version-compatible 
> source dependencies because version-locking would put their clients in 
> "library hell" if the locking didn't all agree.
> 
> Binary dependencies could reasonably use either.
> 
> John.
> _______________________________________________
> 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

Reply via email to