> On Dec 21, 2017, at 1: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 <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? 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)? > > John. > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org <mailto:swift-evolution@swift.org> > https://lists.swift.org/mailman/listinfo/swift-evolution > <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution