I like this a lot. +1 Sent from my iPhone
> On Feb 7, 2017, at 21:22, Matthew Johnson <[email protected]> wrote: > > >> On Feb 7, 2017, at 1:45 PM, Robert Widmann via swift-evolution >> <[email protected]> wrote: >> >> I lean +1, but this answer on its own seems incomplete. Exhaustiveness is >> an important property, and it’s not clear what happens here now when you >> fall through a “complete” case tree without matching a pattern, and in that >> sense this plan solves a problem. But it also would hinder a “future-you” >> from going back and dealing with the ramifications of swapping a dependency >> for a newer version, in that with a default now covering the rest of the >> cases the compiler is unable to tell you which cases you are actually >> missing post-upgrade. >> >> Library Evolution includes what I think is the more complete response here: >> An @closed attribute for enums where a switch is guaranteed to be >> exhaustive. (Though, after the open discussion, I wonder if that keyword >> can’t be reused in some way to provide the inverse restriction instead). > > I agree that we probably need to allow both and the question is whether we > have a default or not, and if we do, which one is the default. > > Personally, if we have a default I would prefer for the default to be closed. > One of the most important attributes of enums is the fact that they > encompass a fixed set of known cases. I *want* my code to break if a new > case is added to an enum of another module I depend on. As the Library > Evolution document notes "adding new cases should not be done lightly. Any > clients attempting to do an exhaustive switch over all enum cases will likely > not handle new cases well.”. Perhaps if a module author is not willing to > commit to a fixed set of cases maybe publicly exposing an enum’s cases is not > the best way to model the API in question. > > I understand that making closed the default is the is slightly contrary to > the principle that a module author explicitly opts-in to public API > contracts. With that in mind, I would also consider it acceptable to decide > that there should be *no* default, as we did in the `open` discussion. > > It’s also worth noting that in the context of enums there are two ways in > which an enum might be considered open - open to future extension by the > module itself and open to extension by other modules. The latter most > closely matches the meaning of the `open` access modifier as it is currently > used and I believe it has been requested on the list once or twice. With > that in mind, I don’t think we should reuse the `open` keyword to mean “open > to extension in a future version of the module, but not open to extension by > users of the module”. That is basically equivalent to the meaning of > `public` for classes. > > This leads me to conclude that maybe the right answer here is to require > library authors to specify `closed` *or* `public` when exposing an enum > outside the module. This follows the principle of library authors explicitly > opting in to public API contracts, but also does not penalize the library > author with additional verbosity for the contract which is more likely to > lead to correct client code. > > >> >>> On Feb 7, 2017, at 10:12 AM, Tanner Nelson via swift-evolution >>> <[email protected]> wrote: >>> >>> Hello Swift Evolution, >>> >>> I'd like to propose that a warning be emitted when default cases are >>> omitted for enums from other modules. >>> >>> What this would look like: >>> >>> OtherModule: >>> ``` >>> public enum SomeEnum { >>> case one >>> case two >>> } >>> >>> public let global: SomeEnum = .one >>> ``` >>> >>> executable: >>> ``` >>> import OtherModule >>> >>> switch OtherModule.global { >>> case .one: break >>> case .two: break >>> ^~~~~ ⚠︎ Warning: Default case recommended for imported enums. Fix-it: >>> Add `default: break` >>> } >>> ``` >>> >>> Why: >>> >>> Allowing the omission of a default case in an exhaustive switch makes the >>> addition of a new case to the enum a breaking change. >>> In other words, if you're exhaustively switching on an enum from an >>> imported library, the imported library can break your code by adding a new >>> case to that enum (which the library authors may erroneously view as an >>> additive/minor-bump change). >>> >>> Background: >>> >>> As a maintainer of a Swift framework, public enums have been a pain point >>> in maintaining semver. They've made it difficult to implement additive >>> features and have necessitated the avoidance of enums in our future public >>> API plans. >>> >>> Related Twitter thread: >>> https://twitter.com/tanner0101/status/796860273760104454 >>> >>> Looking forward to hearing your thoughts. >>> >>> Best, >>> Tanner >>> >>> Tanner Nelson >>> Vapor >>> +1 (435) 773-2831 >>> >>> >>> >>> >>> >>> >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] >>> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> _______________________________________________ >> swift-evolution mailing list >> [email protected] >> https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
