I am unsure if this feature is a good idea. Does someone have a real-world use 
for this which isn’t just hiding strong implementation coupling behind a 
protocol?

When I consume a protocol, it is under the assumption that the protocol is 
documented such that I would be able to work against *any* implementation of 
the protocol. With a closed protocol, I would have to assume that there are 
significant side effects, either undocumented or difficult for a third party to 
duplicate. To my experience, that sounds brittle.

Assuming you aren’t switching on the implementing type of a protocol (which 
itself can be a sign that your design isn’t properly using polymorphism), one 
could get this design by creating a struct with the interface desired, and 
passing invocations through to an internal protocol reference.

-DW

> On Feb 18, 2017, at 1:41 PM, Matthew Johnson via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> Now that we’re in phase 2 I’d like to officially propose we introduce `open` 
> protocols and require conformances to  `public` protocols be inside the 
> declaring module.  Let’s use this thread for feedback on the official 
> proposal.  After a healthy round of discussion I’ll open a PR to submit it 
> for review.
> 
> 
> # Feature name
> 
> * Proposal: [SE-NNNN](NNNN-open-public-protocols.md)
> * Authors: [Matthew Johnson](https://github.com/anandabits)
> * Review Manager: TBD
> * Status: **Awaiting review**
> 
> ## Introduction
> 
> This proposal introduces `open protocol` and changes the meaning of `public 
> protocol` to match the meaning of `public class` (in this case, conformances 
> are only allowed inside the declaring module).
> 
> The pitch thread leading up to this proposal was: [consistent public access 
> modifiers](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031653.html)
> 
> ## Motivation
> 
> A general principle the Swift community has adopted for access control is 
> that defaults should reserve maximum flexibility for a library.  The ensures 
> that any capabilities beyond mere visibility are not available unless the 
> author of the library has explicitly declared their intent that the 
> capabilities be made available.  Finally, when it is possible to switch from 
> one semantic to another without breaking clients (but not vice-versa) we 
> should prefer the more forgiving (i.e. fixable) semantic as the (soft) 
> default.
> 
> `public` is considered a "soft default" in the sense that it is the first 
> access modifier a user will reach for when exposing a declaration outside of 
> the module.  In the case of protocols the current meaning of `public` does 
> not meet the principle of preserving maximum flexibility for the author of 
> the library.  It allows users of the library to conform to the protocol.
> 
> There are good reasons a library may not wish to allow users to add 
> conformances to a protocol.  For example, it may not wish to expose the 
> conforming concrete types.  While similar behavior could be accomplished with 
> an enum if cases could be private, that requires an implementation to use 
> switch statements rather than polymorphism.
> 
> Even if all the conforming types are also public there are cases where 
> polymorphism is the preferred implementation.  For example, if the set of 
> conforming types is not expected to be fixed (despite all being inside the 
> library) the authors may not want to have to maintain switch statements every 
> time they need to add or remove a confroming type which would be necessary if 
> an enum were used instead.  Polymorphism allows us to avoid this, giving us 
> the ability to add and remove conforming types within the implementation of 
> the library without the burden of maintaining switch statements.
> 
> Aligning the access modifiers for protocols and classes allows us to specify 
> both conformable and non-conformable protocols, provides a soft default that 
> is consistent with the principle of (soft) defaults reserving maximum 
> flexibility for the library, and increases the overall consistency of the 
> language by aligning the semantics of access control for protocols and 
> classes.
> 
> The standard library currently has at least one protocol (`MirrorPath`) that 
> is documented as disallowing client conformances.  If this proposal is 
> adopted it is likely that `MirrorPath` would be declared `public protocol` 
> and not `open protocol`.
> 
> Jordan Rose has indicated that the Apple frameworks also include a number of 
> protocols documented with the intent that users do not add conformances.  
> Perhaps an importer annotation would allow the compiler to enforce these 
> semantics in Swift code as well.
> 
> ## Proposed solution
> 
> The proposed solution is to change the meaning of `public protocol` to 
> disallow conformances outside the declaring module and introduce `open 
> protocol` to allow conformances outside the decalring module (equivalent to 
> the current meaning of `public protocol`).
> 
> ## Detailed design
> 
> The detailed design is relatively straightforward but there are three 
> important wrinkles to consider.
> 
> ### User refinement of public protocols
> 
> Consider the following example:
> 
> ```swift
> // Library module:
> public protocol P {}
> public class C: P {}
> 
> // User module:
> protocol User: P {}
> extension C: User {}
> ```
> 
> The user module is allowed to add a refinement to `P` because this does not 
> have any impact on the impelementation of the library or its possible 
> evolution.  It simply allows the user to write code that is generic over a 
> subset of the conforming types provided by the library.
> 
> ### Public protocols with open conforming classes
> 
> Consider the following example:
> 
> ```swift
> public protocol P P{}
> open class C: P {}
> ```
> 
> Users of this module will be able to add subclasses of `C` that have a 
> conformance to `P`.  This is allowed becuase the client of the module did not 
> need to explicitly declare a conformance and the module has explicitly stated 
> its intent to allow subclasses of `C` with the `open` access modifier.
> 
> ### Open protocols that refine public protocols
> 
> Consider the following example:
> 
> ```swift
> // library module:
> public protocol P {}
> open protocol Q: P {}
> open protocol R: P {}
> 
> // user module:
> struct S: P {} // error `P` is not `open`
> struct T: Q {} // ok
> struct U: R {} // ok
> ```
> 
> The user module is allowed to introudce a conformance to `P`, but only 
> indirectly by also conforming to `Q`.  The meaning we have ascribed to the 
> keywords implies that this should be allowed and it offers libraries a very 
> wide design space from which to choose.  The library is able to have types 
> that conform directly to `P`, while placing additional requirements on user 
> types if necessary.
> 
> ## Source compatibility
> 
> This proposal breaks source compatibility, but in a way that allows for a 
> simple mechanical migration.  A multi-release stratgegy will be used to roll 
> out this proposal to provide maximum possible source compatibility from one 
> release to the next.
> 
> 1. In Swift 4, introduce the `open` keyword and the `@nonopen` attribute 
> (which can be applied to `public protocol` to give it the new semantics of 
> `public`).
> 2. In Swift 4 (or 4.1 if necessary) start warning for `public protocol` with 
> no annotation.
> 3. In the subsequent release `public protocol` without annotation becomes an 
> error.
> 4. In the subsequent relase `public protocol` without annotation takes on the 
> new semantics.
> 5. `@nonopen` becomes a warning, and evenutally an erro as soon as we are 
> comfortable making those changes.
> 
> ## Effect on ABI stability
> 
> I would appreciate it if others can offer input regarding this section.  I 
> believe this proposal has ABI consequences, but it's possible that it could 
> be an additivie ABI change where the ABI for conformable protocols remains 
> the same and we add ABI for non-conformable protocols later.  If that is 
> possible, the primary impact would be the ABI of any standard library 
> protocols that would prefer to be non-conformable.
> 
> ## Effect on API resilience
> 
> This proposal would may impact one or more protocols in the standard library, 
> such as `MirrorPath`, which would likely choose to remain `public` rather 
> than adopt `open`.
> 
> ## Alternatives considered
> 
> The primary alternatives are to either make no change, or to add something 
> like `closed protocol`.  The issues motivating the current proposal as a 
> better alternative than either of these options are covered in the motivation 
> section.
> 
> _______________________________________________
> 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