[swift-evolution] [Pitch] Let's talk about submodules

Jonathan Hull jhull at gbis.com
Wed Feb 22 11:28:13 CST 2017

> On Feb 22, 2017, at 12:04 AM, Brent Royal-Gordon <brent at architechies.com> wrote:
>> On Feb 21, 2017, at 11:11 PM, Jonathan Hull via swift-evolution <swift-evolution at swift.org> wrote:
>> There is one major use case which I see all of these proposals failing to handle (although that may be intentional for some designs), is where you have something internal to the type, but you still want to allow subclasses/extensions outside the framework (which need that information) to access it.  An actual example of this is UIGestureRecognizer.  This class is designed to be subclassed outside of the framework, but it hides things like setting the ‘state' from client code (without hiding it from subclasses). This is important, because if a client sets the state directly, then it results in either undefined behavior, or an infinite loop.  Other languages use ‘protected’ and ‘friend’ to accomplish this.
> Yeah, that's a use case I've thought about. I *think* that, if extensions in other submodules can add `open` methods, it can be done:
> 1. Create a submodule (or several) containing `UIGestureRecognizer`'s normal APIs.
> 2. Create a `UIKit.UIGestureRecognizerSubclass` submodule containing the subclass-only APIs in an extension.
> 3. In the top-level module, declare the main submodule `@exported open`, and declare `UIKit.UIGestureRecognizerSubclass` `open`.
> There are holes in this idea—particularly, the setter on the `state` property—but I *think* you could do something along these lines.

Yeah, there is something possible in there somewhere.

I guess you could also allow some change in visibility of submodules to set when they are importable or not (i.e. ‘public submodule’).  There are some issues there around how it would interact with the visibility of types though. 

Looking at the complexity of all this, I am back to thinking my idea of adding ‘hidden’ is the simplest way to accomplish this.  Things would have private/internal/public modifiers, just as Nevin describes, but you could also mark something hidden (e.g. ‘public hidden’), which would reduce it’s visibility to the current file... and any file with an ‘import hidden FileName’ statement (as allowed by its private/internal/public declaration).


More information about the swift-evolution mailing list