> On Dec 21, 2017, at 2:06 PM, John McCall <rjmcc...@apple.com> wrote: > > >> On Dec 21, 2017, at 2:41 PM, Matthew Johnson <matt...@anandabits.com >> <mailto:matt...@anandabits.com>> wrote: >> >> >>> On Dec 21, 2017, at 1:26 PM, John McCall via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>> >>>> >>>> On Dec 21, 2017, at 2:03 PM, Jordan Rose via swift-evolution >>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>>> >>>> >>>> >>>>> On Dec 20, 2017, at 12:35, Karl Wagner <razie...@gmail.com >>>>> <mailto:razie...@gmail.com>> wrote: >>>>> >>>>> >>>>> >>>>>> On 20. Dec 2017, at 19:54, Jordan Rose <jordan_r...@apple.com >>>>>> <mailto:jordan_r...@apple.com>> wrote: >>>>>> >>>>>> >>>>>> >>>>>>> On Dec 20, 2017, at 05:36, Karl Wagner via swift-evolution >>>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>>>>>> >>>>>>> >>>>>>> >>>>>>>> On 19. Dec 2017, at 23:58, Ted Kremenek via swift-evolution >>>>>>>> <swift-evolution@swift.org <mailto: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 >>>>>>>> >>>>>>>> <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 >>>> <https://github.com/apple/swift/blob/master/docs/Lexicon.rst>. 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. >> >> This model aligns pretty well with what I would like to see. It prevents us >> from paying a penalty when we don’t need the benefits provided by a >> restriction. >> >> Relating this back to the current proposal, would you expect an app to have >> the ability to switch over an enum provided by a version-locked dependency >> that is not annotated with @exhaustive without requiring a default clause? > > Yes, and as we find other places where program semantics depend on knowing > the implementation, I would expect them to follow suit. > > My guess is that enum exhaustiveness is probably more prominent than any > other such feature, and maybe even more prominent than all of them put > together, but possible examples include: > - automatically deriving protocol conformances, which we hope will > eventually be something you can do for an arbitrary protocol > - any other kind of structural metaprogramming we might add > - maybe memberwise struct initialization if there are no explicit > initializers, although this is arguably an access control question (just as > public/open is) > - ownership-related features that might make sense to restrict to stored > properties, like expecting a struct property to have a stable address, or > destructuring a struct with pattern-matching > > Now, some of these things might be nice to allow even for resilient types. I > know Joe has suggested adding some way of resiliently describing a structural > decomposition of a type, which you could then use to derive conformances, > etc. But since the basic motivation for restricting any of them is > source/binary compatibility, and since version-locking would tell us that the > programmer doesn't care about that, it seems sensible that version-locking > ought to suppress the restrictions. > >> Relating to @inlinable proposal also under review, would everything in a >> source dependency be automatically inlinable whether they were annotated as >> such or not (at least when version-locked)? > > Yes, and regardless of being version-locked. Inlining isn't semantically > visible: it's observable in various low-level ways, but it's not supposed to > affect basic program semantics except in incidental ways, e.g. by lowering > the memory requirements so that programs start working that didn't before. > So the compiler is generally always allowed to inline when the call is direct > and the callee has a known implementation; that's just standard "as if" > behavior. The fact that we can't do this today is just an unfortunate > consequence of our current build model.
This is all exciting to hear (as a long term direction)! Thank you for the elaboration. > > John.
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution