<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 24, 2017, at 4:57 PM, David Hart &lt;<a href="mailto:david@hartbit.com" class="">david@hartbit.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; position: relative;" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">On 24 Feb 2017, at 20:34, Matthew Johnson via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">I didn't expect submodules to be a part of the Swift 4 discussion. &nbsp;When it came up I was pleasantly surprised. &nbsp;I have been thinking about the design of a submodule system for quite a while but was planning to wait until it was clearly in scope to draft a proposal. &nbsp;Now that the topic has been introduced I decide to write down the design I've been thinking about, along with the motivation and goals that underly it. &nbsp;I understand submodules may not be in scope for Swift 4 but wanted to contribute this design while the discussion is fresh in everyone's mind.</div><div class=""><br class=""></div><div class="">I am including the contents of the proposal below. &nbsp;You can also find it on Github:&nbsp;<a href="https://github.com/anandabits/swift-evolution/blob/scope-based-submodules/proposals/NNNN-scope-based-submodules.md" class="">https://github.com/anandabits/swift-evolution/blob/scope-based-submodules/proposals/NNNN-scope-based-submodules.md</a></div><div class=""><br class=""></div><div class="">I am very much looking forward to everyone's feedback!</div><div class=""><br class=""></div><div class="">Matthew</div><div class=""><h1 id="scope-basedsubmodules" class="" style="font-size: 37px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Scope-based submodules</h1><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;">Proposal:&nbsp;<a href="file:///Users/Matthew/Dropbox/Matthew/Development/__notes/__swift/evolution/NNNN-scope-based-submodules.md" class="" style="color: rgb(13, 110, 161); text-decoration: none; -webkit-transition: color 0.2s ease-in-out; transition: color 0.2s ease-in-out;">SE-NNNN</a></li><li class="" style="font-size: 16.5px;">Authors:&nbsp;<a href="https://github.com/anandabits" class="" style="color: rgb(13, 110, 161); text-decoration: none; -webkit-transition: color 0.2s ease-in-out; transition: color 0.2s ease-in-out;">Matthew Johnson</a></li><li class="" style="font-size: 16.5px;">Review Manager: TBD</li><li class="" style="font-size: 16.5px;">Status:&nbsp;<strong class="" style="line-height: 1;">Awaiting review</strong></li></ul><h2 id="introduction" class="" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Introduction</h2><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">This proposal describes a submodule system based on the principle of strictly nested scopes. The design strives to follow the Swift philosophy of offering good defaults while progressively disclosing very powerful tools that can be used by experts to solve complex problems.</p><h2 id="motivation" class="" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Motivation</h2><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Swift currently provides two kinds of entities that provide system boundaries without directly introducing a symbol: modules and files*.</p><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;">Modules introduce an ABI boundary, a name boundary, and a scope boundary.</li><li class="" style="font-size: 16.5px;">Files introduce a scope boundary that carries no additional semantics.</li></ul><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Swift currently lacks the ability to introduce a name and scope boundary without also introducing an ABI boundary. Such a boundary would be naturally situated halfway between in terms of strength and ceremony. The lack of such a boundary significantly limits our abiltiy to structure a large Swift program. Introducing a way to form this kind of boundary will provide a powerful tool for giving internal structure to a module.</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">*The important aspect of a file in Swift is the logical scope boundary it introduces. The physical file system representation is incidental to this. The appendix on file system independence discusses this in more detail.</p><h2 id="goals" class="" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Goals</h2><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Any discussion of submodules inevitably reveals that there are very different perspectives of what a submodule is, what problems submodules should be able to solve, etc. This section describes the design goals of this proposal in order to facilitate evaluation of both the goals themselves as well as how well the solution accomplishes those goals.</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">The primary goal of this proposal are to introduce a unit of encapsulation within a module that is larger than a file as a means of adding explicit structure to a large program. All other goals are subordinate to this goal and should be considered in light of it.&nbsp;</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Some other goals of this proposal are:</p><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;">Submodules should help us to manage and understand the internal dependencies of a large, complex system.</li><li class="" style="font-size: 16.5px;">Submodules should be able to collaborate with peer submodules without necessarily being exposed to the rest of the module.</li><li class="" style="font-size: 16.5px;">A module should not be&nbsp;<em class="" style="line-height: 1;">required</em>&nbsp;to expose its internal submodule structure to users when symbols are exported.</li><li class="" style="font-size: 16.5px;">It should be possible to extract a submodule from existing code with minimal friction. The only difficulty should be breaking any circular dependencies.</li></ul><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Some additional non-functional requirements for the solution are:</p><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;">Submodules should not negatively impact runtime performance. WMO should be able to see across submodule boundaries.</li><li class="" style="font-size: 16.5px;">Submodules should not negatively impact build performance. Ideally they will improve build performance by giving the compiler more high-level information about internal dependencies.</li></ul><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Deferred goal:</p><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;">It is not an immediate goal to support submodules in single-file scripts. The appendix discussing file system independence discusses some ideas that could be used to support single-file scripts in the future.</li></ul><h2 id="proposedsolution" class="" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Proposed solution</h2><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">There are several relatively orthogonal aspects to the design of a submodule system. A design must answer the following questions:</p><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;">How is code placed in a submodule?</li><li class="" style="font-size: 16.5px;">How are symbols in one submodule made available to another submodule or module?</li><li class="" style="font-size: 16.5px;">How do submodules interact with access control?</li></ul><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">This proposal diverages a little bit from the usual proposal format to faciliate discussion of alternatives within the context of each aspect of the chosen design. In each case an alternative could be substituted without compromising the overall design.</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;"><strong class="" style="line-height: 1;">Note:</strong>&nbsp;This proposal uses the term “top-level submodule” to distinguish the scope of code that is not explicitly placed in a submodule from the module as a whole. The top-level submodule is in most respects identical to any other parent submodule. There are two differences: 1) it is the only submodule that can export symbols outside of the module and 2) any&nbsp;<code class="" style="line-height: 1;">open</code>&nbsp;or&nbsp;<code class="" style="line-height: 1;">public</code>&nbsp;symbols it declares are automatically exported according to their access modifier.</p><h3 id="placingcodeinasubmodule" class="" style="color: rgb(17, 17, 17); margin: 21px 0px; font-size: 20px; line-height: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Placing code in a submodule</h3><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Each file is part of the top level submodule by default.</p><h5 id="asubmoduledeclarationmaybeusedatthetopofafile" data-orig-id="asubmoduledeclarationmaybeusedatthetopofafile:" class="" style="color: rgb(17, 17, 17); font-size: 1.1429em; line-height: 1.3125em; margin: 1.3125em 0px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">A&nbsp;<code class="" style="line-height: 1;">submodule</code>&nbsp;declaration may be used at the top of a file:</h5><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;">Only the first non-comment, non-whitespace line may contain a submodule declaration.</li><li class="" style="font-size: 16.5px;">The submodule decalaration looks like this:&nbsp;<code class="" style="line-height: 1;">submodule MySubmoduleName</code></li><li class="" style="font-size: 16.5px;">A submodule declaration may not be prefixed with the module name.</li></ul><h5 id="submodulenamesformahierarchicalpath" data-orig-id="submodulenamesformahierarchicalpath:" class="" style="color: rgb(17, 17, 17); font-size: 1.1429em; line-height: 1.3125em; margin: 1.3125em 0px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Submodule names form a hierarchical path:</h5><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;">The fully qualified name of the submodule specified by&nbsp;<code class="" style="line-height: 1;">Submodule.InnerSubmodule</code>&nbsp;is:&nbsp;<code class="" style="line-height: 1;">MyModuleName.Submodule.InnerSubmodule</code>.</li><li class="" style="font-size: 16.5px;">In this example,&nbsp;<code class="" style="line-height: 1;">InnerSubmodule</code>&nbsp;is a child of&nbsp;<code class="" style="line-height: 1;">Submodule</code>.</li><li class="" style="font-size: 16.5px;">A submodule may not have the same name as any of its ancestors. This follows the rule used by types.</li></ul><h5 id="submodulesmaynotbeextendedtheyformstrictlynestedscopes" data-orig-id="submodulesmaynotbeextended.theyformstrictlynestedscopes." class="" style="color: rgb(17, 17, 17); font-size: 1.1429em; line-height: 1.3125em; margin: 1.3125em 0px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Submodules may not be extended. They form strictly nested scopes.</h5><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;">The&nbsp;<em class="" style="line-height: 1;">only</em>&nbsp;way to place code in a submodule is with a&nbsp;<code class="" style="line-height: 1;">submodule</code>&nbsp;declaration at the top of a file.</li><li class="" style="font-size: 16.5px;">All code in a file exists in a single submodule.</li></ul><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">A module is made up of strictly nested scoped that look like this:</p><figure class="" style="display: inline-block; overflow: hidden; position: relative; margin: 1em 0px 2em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><span id="cid:7485F5F5-4A10-4A94-9E3C-0A6A30181825@Home" class="">&lt;scope-based-submodules.png&gt;</span><ins id="firstdiff" class="" style="display: inline-block; position: absolute; left: -8px; text-decoration: none !important; border: none !important; background-image: none !important;"></ins><figcaption class="" style="font-style: italic; text-align: center; background-color: white; color: rgb(102, 102, 102);">The hierarchy of nested scopes in scope-based submodules</figcaption></figure><span class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px; background-color: rgb(255, 255, 255);"></span><h4 id="alternatives" class="" style="color: rgb(17, 17, 17); font-size: 20px; line-height: 21px; margin-top: 21px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Alternatives</h4><h5 id="groupingmechanisms" class="" style="color: rgb(17, 17, 17); font-size: 1.1429em; line-height: 1.3125em; margin: 1.3125em 0px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Grouping mechanisms</h5><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">There are several other ways to specify which submodule the top-level scope of a file is in. All of these alternatives share a crucial problem: you can’t tell what submodule your code is in by looking at the file.&nbsp;</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">The alternatives are:</p><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;">Use a manifest file. This would be painful to maintain.</li><li class="" style="font-size: 16.5px;">Use file system paths. This is too tightly coupled to physical organization. Appendix A discusses file system independence in more detail.</li><li class="" style="font-size: 16.5px;">Leave this up to the build system. This makes it more difficult for a module to support multiple build systems.</li></ul><h5 id="requireallfilestoincludeasubmoduledeclaration" class="" style="color: rgb(17, 17, 17); font-size: 1.1429em; line-height: 1.3125em; margin: 1.3125em 0px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Require all files to include a&nbsp;<code class="" style="line-height: 1;">submodule</code>&nbsp;declaration</h5><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">We could require all files to include an explicit submodule declaration. However, that would be a breaking change and would violate the principle of progressive disclosure. Users should not need to know about submodules if they don’t use them.</p><h5 id="allowsubmodulereferencestoexplicitlystatethenameofthemodule" class="" style="color: rgb(17, 17, 17); font-size: 1.1429em; line-height: 1.3125em; margin: 1.3125em 0px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Allow submodule references to explicitly state the name of the module</h5><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">The module name is implicit throughout the scope of the entire module. Specifying it explicitly is redundant. Prohibiting explicit mention of the module name offers more flexibility for combining submodules into build products.</p><h3 id="visibilityofsubmodules" class="" style="color: rgb(17, 17, 17); margin: 21px 0px; font-size: 20px; line-height: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Visibility of submodules</h3><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">The&nbsp;<code class="" style="line-height: 1;">export</code>&nbsp;statement is used to modifiy the visibiltiy of a submodule within the module. It is also used by the top-level module to publish submodules to clients of the module.</p><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;">All submodules are implicitly exported with module-wide visibility by default (and hidden outside of the module by default*).</li></ul></div></div></div></blockquote><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;">All submodules are implicitly&nbsp;<em class="" style="line-height: 1;">available</em>&nbsp;for export outside the module.</li><li class="" style="font-size: 16.5px;">A submodule may use an explicit&nbsp;<code class="" style="line-height: 1;">export</code>&nbsp;statement to&nbsp;<em class="" style="line-height: 1;">modify</em>&nbsp;the visibility of a descendent submodule.</li></ul></div></div></div></blockquote><div class="">I don’t see the need for modifying the visibility of descendent modules. Can you give me an idea why its important enough to warrant all that extra syntax?</div></div></div></div></blockquote><div><br class=""></div><div>Thanks for taking a look at my proposal and offering feedback David.</div><div><br class=""></div><div><div>You can think of descendent submodules similarly to nested types. &nbsp;It can be useful to have nested types that are not visible outside the scope of the parent type and the same will be true of submodules.</div><div><br class=""></div><div>For example, let’s say I might have a facade submodule as the parent which delegates work to a networking submodule, a persistence submodule, etc. &nbsp;The module should only interact with this subsystem using the facade - it shouldn’t be interacting directly with the child submodules which are implementation details of the parent.</div></div><div><br class=""></div><div>I want to point out that the syntax supporting submodule hiding isn’t extra syntax. &nbsp;It uses a subset of the syntax that the top level export feature does. &nbsp;Control over top-level export has been a feature of every submodule design I have seen discussed on the list.</div><div><br class=""></div><div>The proposal is actually pretty conservative in terms of syntax extensions. &nbsp;It introduces the `submodule` declaration, the `export` statement, and parameterizes `scoped`. &nbsp;That’s it. &nbsp;There are alternatives available for each of these that don’t require any new syntax while still keeping the system as a whole intact. &nbsp;I obviously think the best tradeoffs are the ones I have proposed but there is room to make changes while still having a workable system if that is what the community and / or core team decides to do.</div><div><br class=""></div></div><div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; position: relative;" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;"><code class="" style="line-height: 1;">export</code>&nbsp;statements are only allowed at the top level of a file.</li></ul><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">*The exception to this is that&nbsp;<code class="" style="line-height: 1;">open</code>&nbsp;and&nbsp;<code class="" style="line-height: 1;">public</code>&nbsp;symbols in the top-level submodule are always exported exactly as declared.</p><h4 id="top-levelexport" class="" style="color: rgb(17, 17, 17); font-size: 20px; line-height: 21px; margin-top: 21px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Top-level export</h4><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">All export statements consist of an access modifier, the&nbsp;<code class="" style="line-height: 1;">export</code>&nbsp;keyword, and a submodule name:</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;"><code class="" style="line-height: 1;">open export ChildSubmodule</code></p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">When this export statement appears in the top-level submodule,&nbsp;<code class="" style="line-height: 1;">ChildSubmodule</code>&nbsp;becomes available for import by clients of the submodule with the fully qualified name&nbsp;<code class="" style="line-height: 1;">Module.ChildSubmodule</code>.&nbsp;<code class="" style="line-height: 1;">public</code>&nbsp;exports are also available. When&nbsp;<code class="" style="line-height: 1;">public</code>&nbsp;is used all published symbols in the exported submodule have a maximum visiblity of&nbsp;<code class="" style="line-height: 1;">public</code>regardless of how they were declared.</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Top-level&nbsp;<code class="" style="line-height: 1;">public</code>&nbsp;and&nbsp;<code class="" style="line-height: 1;">open</code>&nbsp;export statement may be modified with the following options:</p><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;">A submodule may be published under a different external name using the&nbsp;<code class="" style="line-height: 1;">export as NewName</code>&nbsp;syntax*.</li><li class="" style="font-size: 16.5px;"><code class="" style="line-height: 1;">@implicit</code>&nbsp;causes symbols from the submodule to be implicitly imported when the module is imported.</li><li class="" style="font-size: 16.5px;"><code class="" style="line-height: 1;">@inline</code>&nbsp;causes the symbols from the submodule to appear as if they had been declared directly within the top-level submodule.</li><li class="" style="font-size: 16.5px;"><code class="" style="line-height: 1;">@implicit</code>&nbsp;may be combined with renaming but&nbsp;<code class="" style="line-height: 1;">@inline</code>&nbsp;may not appear along with either of them.</li></ul><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">*When a submodule is renamed for export with the&nbsp;<code class="" style="line-height: 1;">as</code>&nbsp;clause its internal name does not change. A submodule always has the same fully qualfied name everywhere within its module.</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Here are some example export statements:</p><pre class="" style="margin-top: 21px; margin-bottom: 21px; tab-size: 4; color: rgb(17, 17, 17); font-size: 15px; background-color: rgb(248, 248, 248); height: 729px;"><code class="swift hljs" style="line-height: inherit; display: block; overflow-x: auto; padding: 0.5em; color: rgb(51, 51, 51); height: auto;"><span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// All symbols in `Child1` are available for import by clients as `Module.Foo`</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// These symbols are *not* imported automatically when a client imports the module with `import Module`</span>
<span class="hljs-keyword" style="font-weight: bold;">public</span> export <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Child1</span> <span class="hljs-keyword" style="font-weight: bold;">as</span> <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Foo</span>

<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// All symbols in `Child2` are available for explicit import by clients as `Module.Child2`</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// The symbols are also automatically imported when a client imports the module with `import Module`</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// When the symbols are imported implicitly they retain the fully qualified name prefix of `Module.Child2`</span>
@implicit open export <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Child2</span>

<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// All symbols in `Child3` are available for explicit import by clients as `Module.Foo.Bar`</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// The symbols are also automatically imported when a client imports the module with `import Module`</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// When the symbols are imported implicitly they retain the fully qualified name prefix of `Module.Foo.Bar`</span>
@implicit open export <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Child3</span> <span class="hljs-keyword" style="font-weight: bold;">as</span> <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Foo</span>.<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Bar</span>

<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// All symbols in `Child4.Grandchild` appear to clients as if they had been declared</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// directly in the top-level submodule.</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// If the process of inlining the symbols produces duplicate symbols a compiler error is produced</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// at the site of one or both of the `export` statements.</span>
@inline <span class="hljs-keyword" style="font-weight: bold;">public</span> export <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Child4</span>.<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Grandchild</span>

<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// All symbols in `Child5.Grandchild` are available for explicit import by clients as `Module.Foo` </span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// along with the symbols declared in `Child`.</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// The symbols are also automatically imported when a client imports the module with `import Module`</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// When the symbols are imported implicitly they retain the fully qualified name prefix of `Module.Foo`</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// As with `@inline`, when two submodules are given the same external name a duplicate symbol error may occur.</span>
@implicit <span class="hljs-keyword" style="font-weight: bold;">public</span> export <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Child5</span>.<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Grandchild</span> <span class="hljs-keyword" style="font-weight: bold;">as</span> <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Foo</span></code></pre><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">One interesting observation is that both&nbsp;<code class="" style="line-height: 1;">Child1</code>&nbsp;and&nbsp;<code class="" style="line-height: 1;">Child5.Grandchild</code>&nbsp;are renamed to&nbsp;<code class="" style="line-height: 1;">Foo</code>. The symbols declared former is not implicitly imported by&nbsp;<code class="" style="line-height: 1;">import Module</code>&nbsp;but the latter is, despite having the same fully qualified name prefix.</p><h4 id="exportswithinthemodule" class="" style="color: rgb(17, 17, 17); font-size: 20px; line-height: 21px; margin-top: 21px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Exports within the module</h4><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">A submodule may bound the maximum visibility of any of its descendent submodules by explicitly exporting it:</p><pre class="" style="margin-top: 21px; margin-bottom: 21px; tab-size: 4; color: rgb(17, 17, 17); font-size: 15px; background-color: rgb(248, 248, 248); height: 267px;"><code class="swift hljs" style="line-height: inherit; display: block; overflow-x: auto; padding: 0.5em; color: rgb(51, 51, 51); height: auto;"><span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// `Child1.Grandchild` may be exported by the top-level module, but only with `public` visibility.</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// `Child1.Grandchild` may not be exported as `open`.</span>
<span class="hljs-keyword" style="font-weight: bold;">public</span> export <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Child1</span>.<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Grandchild</span>

<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// `Child2` is exported with `internal` visibility.</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// Because `internal` is scoped to the submodule level *only* the parent submodule can see `Child2`.</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// No submodules except the direct parent of `Child2` (the current submodule) are allowed to `import Child2`.</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// This also implies that the `Child2` may not be exported to clients because the top-level </span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// submodule is not able to see or reference `Child2` at all.</span>
<span class="hljs-keyword" style="font-weight: bold;">internal</span> export <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Child2</span></code></pre><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;">The access modifier may specify a scope&nbsp;<code class="" style="line-height: 1;">internal</code>&nbsp;or greater.</li><li class="" style="font-size: 16.5px;">Only the&nbsp;<strong class="" style="line-height: 1;">direct</strong>&nbsp;parent of a submodule may specify the&nbsp;<code class="" style="line-height: 1;">internal</code>&nbsp;modifier. A grandparent cannot hide a grandchild from its parent.</li><li class="" style="font-size: 16.5px;">If a descendent includes an&nbsp;<code class="" style="line-height: 1;">export</code>&nbsp;statement for the same submodule, the access modifier must be&nbsp;<strong class="" style="line-height: 1;">no greater than</strong>&nbsp;the access modifier specified by the descendent. An ancestor may provide a tighter bound to visibility but may not increase visibility. An attempt to increase visibility results in an error.</li></ul><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;"><strong class="" style="line-height: 1;">Note:</strong>&nbsp;If a submodule is not visible none of its descendents is visible either.</p><h4 id="alternatives2" class="" style="color: rgb(17, 17, 17); font-size: 20px; line-height: 21px; margin-top: 21px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Alternatives</h4><h5 id="useimportaccessmodifierstoexportasubmodule" class="" style="color: rgb(17, 17, 17); font-size: 1.1429em; line-height: 1.3125em; margin: 1.3125em 0px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Use&nbsp;<code class="" style="line-height: 1;">import</code>&nbsp;access modifiers to export a submodule</h5><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">The semantics of placing a bound on the visibility of a descendent submodule is significantly different than the semantics of importing symbols from a submodule into the current lexical scope. Mixing the semantics of the two is confusing.</p><h5 id="restrictthevisibilityofasubmoduletoitsparentunlesstheparentexplicitlyexportsit" data-orig-id="restrictthevisibilityofasubmoduletoitsparentunlesstheparentexplicitlyexportsit." class="" style="color: rgb(17, 17, 17); font-size: 1.1429em; line-height: 1.3125em; margin: 1.3125em 0px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Restrict the visibility of a submodule to its parent unless the parent explicitly exports it.</h5><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Users should be able to use submodules without needing to place&nbsp;<code class="" style="line-height: 1;">export</code>&nbsp;statements in every parent submodule. Module-wide default visibility for submodules is analagous to&nbsp;<code class="" style="line-height: 1;">internal</code>&nbsp;default visibility for symbols.</p><h5 id="requireallsubmodulestobevisiblemodule-wide" data-orig-id="requireallsubmodulestobevisiblemodule-wide." class="" style="color: rgb(17, 17, 17); font-size: 1.1429em; line-height: 1.3125em; margin: 1.3125em 0px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Require all submodules to be visible module-wide.</h5><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">This removes an important tool for bounded collaboration within a complex system. A parent submodule should be allowed to have a child submodule(s) which are implementation details of the parent and not exposed to the rest of the module.</p></div></div></blockquote><div class="">IMHO, the implementation details of a submodule should live in that submodule, not in a child submodule. </div></div></div></div></blockquote><div><br class=""></div><div>Sometimes yes. &nbsp;But there are different granularities of implementation details. &nbsp;The ability to hide child submodules gives us the ability to hide a coarser-grained implementation detail which has its own internals that should not be visible to the parent it is performing work on behalf of.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; position: relative;" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="">Shouldn’t the main purpose of submodules be to help organise publicly available code into name-spaces, and not add to add scoping mechanisms for implementation?</div></div></div></div></blockquote><div><br class=""></div><div>Not at all. &nbsp;Modules and package managers are for organizing publicly available code. &nbsp;Submodules are about structuring the code within our own module.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; position: relative;" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><br class=""></div><div class="">For example, looking at C#’s System.Xml library, the namespaces clearly help to separate code, like serialisation classes from more mundane Xml reading classes, etc...</div><div class=""><br class=""></div><div class="">System.Xml<br class="">System.Xml.Linq<br class="">System.Xml.Resolvers<br class="">System.Xml.Schema<br class="">System.Xml.Serialization<br class="">System.Xml.Serialization.Advanced<br class="">System.Xml.Serialization.Configuration<br class="">System.Xml.XmlConfiguration<br class="">System.Xml.XPath<br class="">System.Xml.Xsl<br class="">System.Xml.Xsl.Runtime</div></div></div></div></blockquote><div><br class=""></div>You can do this with my proposal. &nbsp;You can have arbitrarily nested submodules with hierarchical names that look exactly like that.<br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; position: relative;" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><h5 id="allowrenamingtobeusedbyexportstatementswithinthemodule" data-orig-id="allowrenamingtobeusedbyexportstatementswithinthemodule." class="" style="color: rgb(17, 17, 17); font-size: 1.1429em; line-height: 1.3125em; margin: 1.3125em 0px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Allow renaming to be used by export statements within the module.</h5><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">A submodule should have the same fully qualified name everywhere it is used within a single module, whether that be the declaring module or a client module. The declaring module and client modules may see different names, but each sees a name that is consistent fully qualified name everywhere the submodule is referenced.</p><h5 id="allowinlinetobeusedbyexportstatementswithinthemodule" data-orig-id="allowinlinetobeusedbyexportstatementswithinthemodule." class="" style="color: rgb(17, 17, 17); font-size: 1.1429em; line-height: 1.3125em; margin: 1.3125em 0px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Allow&nbsp;<code class="" style="line-height: 1;">@inline</code>&nbsp;to be used by export statements within the module.</h5><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">As with renaming, a symbol should have a single fully qualified name everywhere within a single module.</p><h5 id="allowimplicittobeusedbyexportstatementswithinthemodule" data-orig-id="allowimplicittobeusedbyexportstatementswithinthemodule." class="" style="color: rgb(17, 17, 17); font-size: 1.1429em; line-height: 1.3125em; margin: 1.3125em 0px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Allow&nbsp;<code class="" style="line-height: 1;">@implicit</code>&nbsp;to be used by export statements within the module.</h5><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">This would reduce the visibility of internal dependencies. If we find that import-per-submodule becomes boilerplate-y this is an easy feature to add later.</p><h3 id="importingsubmodules" class="" style="color: rgb(17, 17, 17); margin: 21px 0px; font-size: 20px; line-height: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Importing submodules</h3><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Submodules are imported in exactly the same way as an external module by using an&nbsp;<code class="" style="line-height: 1;">import</code>&nbsp;statement. There are a few additional details that are not applicable for external modules:</p><ul class="" style="margin-top: 21px; margin-bottom: 21px; padding-left: 1.5em; color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; font-size: 15px;"><li class="" style="font-size: 16.5px;">Circular imports are not allowed.</li><li class="" style="font-size: 16.5px;">A submodule may not import any of its ancestors.</li><li class="" style="font-size: 16.5px;">Relative child and sibling names are allowed using the same rules that apply to nested types.</li></ul><h3 id="accesscontrol" class="" style="color: rgb(17, 17, 17); margin: 21px 0px; font-size: 20px; line-height: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Access control</h3><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">An access modifier applies an upper bound to the scope in which a symbol or submodule is visible. With the introduction of submodules,&nbsp;<code class="" style="line-height: 1;">internal</code>&nbsp;now applies at the level of a submodule: only the current submodule may see an&nbsp;<code class="" style="line-height: 1;">internal</code>&nbsp;entity. We need a new way to specify module-wide visibility.</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">This proposal builds on Option 2 in the proposal Fix Private Access Levels which reverts&nbsp;<code class="" style="line-height: 1;">private</code>&nbsp;to the Swift 2 meaning (equivalent to&nbsp;<code class="" style="line-height: 1;">fileprivate</code>) and uses&nbsp;<code class="" style="line-height: 1;">scoped</code>&nbsp;for the Swift 3 scoped access feature. It does this by allowing the&nbsp;<code class="" style="line-height: 1;">scoped</code>&nbsp;access modifier to be parameterized with a scope reference. By&nbsp;<strong class="" style="line-height: 1;">defaults</strong>&nbsp;it references the scope in which it appears, but any ancestor scope may be specified as a parameter.</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">The paremeterization of the&nbsp;<code class="" style="line-height: 1;">scoped</code>&nbsp;access modifier provides a simple yet powerful way for a submodule to bound the visibility of a descendent.</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Some examples of using&nbsp;<code class="" style="line-height: 1;">scoped</code>&nbsp;exports are:</p><pre class="" style="margin-top: 21px; margin-bottom: 21px; tab-size: 4; color: rgb(17, 17, 17); font-size: 15px; background-color: rgb(248, 248, 248); height: 225px;"><code class="swift hljs" style="line-height: inherit; display: block; overflow-x: auto; padding: 0.5em; color: rgb(51, 51, 51); height: auto;">submodule <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Parent</span>

<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// `Grandparent` and all of its descendents can see `Child1` (fully qualified: `Grandparent.Parent.Child1`)</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// This reads: `Child1` is scoped to `Grandparent`.</span>
scoped(<span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Grandparent</span>) export <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Child1</span>

<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// `Child2` is visible throughout the module but may not be exported for use by clients.</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// This reads: `Child2` is scoped to the module.</span>
scoped(module) export <span class="hljs-type" style="color: rgb(68, 85, 136); font-weight: bold;">Child2</span></code></pre><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">With parameterization,&nbsp;<code class="" style="line-height: 1;">scoped</code>&nbsp;has the power to specify&nbsp;<strong class="" style="line-height: 1;">all</strong>&nbsp;access levels that Swift has today:</p><pre class="" style="margin-top: 21px; margin-bottom: 21px; tab-size: 4; color: rgb(17, 17, 17); font-size: 15px; background-color: rgb(248, 248, 248); height: 141px;"><code class="(null) clean hljs" style="line-height: inherit; display: block; overflow-x: auto; padding: 0.5em; color: rgb(51, 51, 51); height: auto;">`scoped`                                      == `private` (Swift <span class="hljs-number" style="color: rgb(0, 128, 128);">3</span>)
`scoped(file)`                                == `private` (Swift <span class="hljs-number" style="color: rgb(0, 128, 128);">2</span> &amp; <span class="hljs-number" style="color: rgb(0, 128, 128);">4</span>?) == `fileprivate` (Swift <span class="hljs-number" style="color: rgb(0, 128, 128);">3</span>)
`scoped(submodule)`                           == `internal`
`scoped(public) scoped(internal, inherit)`*   == `public`
`scoped(public)`                              == `open`</code></pre><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">This design is a direct generalization of the principle underlying Swift’s existing access control system. It unifies the semantics of the system under the single elegant mechanism of ancestor scope references.&nbsp;</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">While it is&nbsp;<em class="" style="line-height: 1;">possible</em>&nbsp;to specify all access levels using&nbsp;<code class="" style="line-height: 1;">scoped</code>&nbsp;that is not recommended. The aliases&nbsp;<code class="" style="line-height: 1;">public</code>,&nbsp;<code class="" style="line-height: 1;">private</code>(Swift 2) and&nbsp;<code class="" style="line-height: 1;">internal</code>&nbsp;provide excellent default access levels that don’t require a user to think about scope hierarchies. Using the default access levels when possible calls extra attention to cases where a different choice was made.</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">*This is a conceptual model. This proposal does not introduce the&nbsp;<code class="" style="line-height: 1;">inherit</code>&nbsp;or&nbsp;<code class="" style="line-height: 1;">override</code>&nbsp;parameter to access modifiers. It could be added in the future as a way to bound inheritance within a module. It would work similarly to&nbsp;<code class="" style="line-height: 1;">private(set)</code>&nbsp;does in Swift today.</p></div></div></blockquote><div class="">Like we’ve had time to discuss, I’m really not sold on this solution as it adds a fair amount of complexity, and complexity is exactly what people have been complaining about in the current model. </div></div></div></div></blockquote><div><br class=""></div><div>It introduces complexity in one sense, but reduces it in another by providing a consistent semantic for access modifiers. &nbsp;I really think the biggest mistake was that `private` was a bad “soft default”. &nbsp;This caused lots of confusion around when to use `private` and when to use `fileprivate`. &nbsp;If we had left `private` alone and introduced `scoped` last year I don’t think we would have seen nearly so much grumbling. &nbsp;People who didn’t want to use it just wouldn’t. &nbsp;But instead, they were “forced” to use `fileprivate` and didn’t like that.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; position: relative;" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="">The complexity I’m not sure we need:</div><div class=""><br class=""></div><div class=""><ul class="MailOutline"><li class="">new keyword</li></ul></div></div></div></div></blockquote><div><br class=""></div><div>No, we have the same number of keywords because `fileprivate` goes away.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; position: relative;" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><ul class="MailOutline"><li class="">more than 1 way to express the same semantics</li></ul></div></div></div></div></blockquote><div><br class=""></div><div>We have syntactic sugar and shorthand for many things in the language. &nbsp;I don’t think this is that different. &nbsp;I would not object to banning the `scoped` spellings that have a shorthand equivalent if people felt strongly about that. &nbsp;They could still be taught in the context of scoped access.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; position: relative;" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><ul class="MailOutline"><li class="">the parametrisation of the keyword</li></ul></div></div></div></div></blockquote><div><br class=""></div><div>We already have parameterized keywords, including parameterized access modifiers - `private(set)` is an example. &nbsp;Parameterization of a keyword is not any more conceptually complex than a function call, which are pervasive in the language.</div><div><br class=""></div><div>The most important thing about the design I have proposed is that it stays out of your way until you decide you need to use the tools available. &nbsp;Every aspect is progressively disclosed when it becomes necessary to solve a problem and not before.</div><div><br class=""></div><div>That said, I definitely don’t want to see people get hung up on the access control section of this proposal. &nbsp;The big picture works fine with a more limited access control system, it just isn’t as flexible.</div><div><br class=""></div><div>Let’s start with the goals section. &nbsp;Do you think that’s in the right ballpark? &nbsp;If so, then we should discuss the alternatives for each aspect of the proposal. &nbsp;If not we should focus on where we have different opinions about the goals.</div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; position: relative;" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;"><span class="" style="font-size: 1.1429em;">Aside</span></p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">The parameterization of&nbsp;<code class="" style="line-height: 1;">scoped</code>&nbsp;also allows us to reference other scopes that we cannot in today’s system, specifically extensions:&nbsp;<code class="" style="line-height: 1;">scoped(extension)</code>&nbsp;and outer types:&nbsp;<code class="" style="line-height: 1;">scoped(TypeName)</code>.</p><h4 id="alternatives3" class="" style="color: rgb(17, 17, 17); font-size: 20px; line-height: 21px; margin-top: 21px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Alternatives</h4><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">If we don’t adopt the approach of parameterizing&nbsp;<code class="" style="line-height: 1;">scoped</code>&nbsp;our options for access control include:</p><h5 id="submodulesareonlyallowedtoseepublicandopensymbolsfromothersubmodules" class="" style="color: rgb(17, 17, 17); font-size: 1.1429em; line-height: 1.3125em; margin: 1.3125em 0px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Submodules are only allowed to see&nbsp;<code class="" style="line-height: 1;">public</code>&nbsp;and&nbsp;<code class="" style="line-height: 1;">open</code>&nbsp;symbols from other submodules</h5><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">A module-wide scope is highly desirable. People might avoid using submodules if this is not available.</p><div class=""><br class=""></div><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">This approach also creates a lot more friction when refactoring. A possible workaround to the lack of a module-wide scope in this system is to place code in a non-exported submodule and declare symbols&nbsp;<code class="" style="line-height: 1;">public</code>. Even with the workaround, extracting a submodule may not always be possible or desirable and the&nbsp;<code class="" style="line-height: 1;">public</code>&nbsp;access modifiers required would be misleading. It would be much better to be able to state our intent directly.</p><h5 id="useinternaltocoverthewholemoduleandprivatetocoverasubmodule" class="" style="color: rgb(17, 17, 17); font-size: 1.1429em; line-height: 1.3125em; margin: 1.3125em 0px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Use&nbsp;<code class="" style="line-height: 1;">internal to cover the whole module and</code>&nbsp;<code class="" style="line-height: 1;">private</code>&nbsp;to cover a submodule</h5><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">One suggestion that has appeared is the idea of removing&nbsp;<code class="" style="line-height: 1;">fileprivate</code>&nbsp;and making&nbsp;<code class="" style="line-height: 1;">private</code>&nbsp;be submodule-wide.&nbsp;<code class="" style="line-height: 1;">internal</code>&nbsp;would remain module-wide. This is too coarse -&nbsp;<em class="" style="line-height: 1;">many</em>&nbsp;people want a file-level scope.</p></div></div></blockquote></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">I agree that this is a bad idea.<br class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;"><code class="" style="font-size: 1.1429em; line-height: 1;">internal</code><span class="" style="font-size: 1.1429em;">&nbsp;is Swift’s default access modifier. A symbol with default access modifier should not be able to cross a submodule boundary implicitly.</span></p><h5 id="addthemoduleinternalaccessmodifier" class="" style="color: rgb(17, 17, 17); font-size: 1.1429em; line-height: 1.3125em; margin: 1.3125em 0px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Add the&nbsp;<code class="" style="line-height: 1;">moduleinternal</code>&nbsp;access modifier</h5><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">This is about as ugly as&nbsp;<code class="" style="line-height: 1;">fileprivate</code>.</p></div></div></blockquote>What about the alternative of not having a submodule scope at all? Submodules would see all internal access in all submodules, as long as it’s imported at the top of the file.</div></div></div></blockquote><div><br class=""></div><div>That’s certainly an option. &nbsp;It’s certainly not one I would choose, but as I said earlier, this proposal will work with whatever access modifiers we want. &nbsp;Changing that part of the proposal only changes what you have the ability to express.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; position: relative;" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">I think the divide comes from the fact that I ant “namespaces” as a name grouping mechanism and you want “submodules” as a scope grouping mechanism.<br class=""></div></div></div></blockquote><div><br class=""></div><div>Yes, these are at odds with each other and clearly there are two camps. &nbsp;I elaborate on why I don’t want namespaces in the second appendix.</div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; position: relative;" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;"><span class="" style="font-size: 27px;">Detailed design</span></p><h3 id="exporterrors" class="" style="color: rgb(17, 17, 17); margin: 21px 0px; font-size: 20px; line-height: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Export errors</h3><h4 id="multipleexportsofthesamesubmodule" class="" style="color: rgb(17, 17, 17); font-size: 20px; line-height: 21px; margin-top: 21px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Multiple exports of the same submodule</h4><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">If a submodule exports the same descendent more than once and the semantics of the declarations are not identical an error is produced.</p><h4 id="symbolflattening" class="" style="color: rgb(17, 17, 17); font-size: 20px; line-height: 21px; margin-top: 21px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Symbol flattening</h4><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">When a submodule is exported by the top-level module using the&nbsp;<code class="" style="line-height: 1;">@inline</code>&nbsp;attribute it is possible that there will be conflicting symbol definitions in the child and the top-level submodule (or other inlined submodules). This results in a compiler error at the site of the conflicing&nbsp;<code class="" style="line-height: 1;">@inline export</code>&nbsp;statements.</p><h4 id="overlappingrenames" class="" style="color: rgb(17, 17, 17); font-size: 20px; line-height: 21px; margin-top: 21px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Overlapping renames</h4><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">As with flattening, when two or more submodules are given the same external name symbol conflicts are possible. This also results in a compiler error at the site of the conflicting&nbsp;<code class="" style="line-height: 1;">export as</code>&nbsp;statements.</p><h4 id="accesserrorsduringexportifthespecifiedaccessmodifierexceedsmaximum" class="" style="color: rgb(17, 17, 17); font-size: 20px; line-height: 21px; margin-top: 21px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Access errors during export if the specified access modifier exceeds maximum</h4><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">An error is produced when an export statement includes an access modifier greater than the bound provided for the exported submodule by a descendent of the exporting submodule.</p><h2 id="sourcecompatibility" class="" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Source compatibility</h2><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">This proposal is purely additive. That said, it would be a breaking change for the standard library to move existing API into an externally visible submodule.</p><h2 id="effectonabistability" class="" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Effect on ABI stability</h2><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">This proposal is purely additive. That said, it would be a breaking change for the standard library to move existing API into an externally visible submodule.</p><h2 id="effectonapiresilience" class="" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Effect on API resilience</h2><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">This proposal is purely additive.</p><h2 id="futuredirections" class="" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Future directions</h2><h3 id="selectiveexportandimport" class="" style="color: rgb(17, 17, 17); margin: 21px 0px; font-size: 20px; line-height: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Selective export and import</h3><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">The ability to import and export individual symbols would be a very nice to have.</p><h3 id="scopedimport" class="" style="color: rgb(17, 17, 17); margin: 21px 0px; font-size: 20px; line-height: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Scoped import</h3><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">The ability to import modules, submodules, and symbols into any lexical scope would be nice to have.</p><h3 id="boundedinheritance" class="" style="color: rgb(17, 17, 17); margin: 21px 0px; font-size: 20px; line-height: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Bounded inheritance</h3><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">It could be useful to have the ability to bound inheritance within a module. This could be accomplished by inroducing&nbsp;<code class="" style="line-height: 1;">inherit</code>&nbsp;and&nbsp;<code class="" style="line-height: 1;">override</code>&nbsp;parameters for access modifiers (which would work similarly to the existing&nbsp;<code class="" style="line-height: 1;">set</code>&nbsp;parameter).</p><h2 id="appendixafilesystemindependence" data-orig-id="appendixa:filesystemindependence" class="" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Appendix A: file system independence</h2><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">The submodule design specified by this proposal is file system independent. The only relationship it has with the physical file system is that a file introduces an anonymous scope boundary which is referenced by&nbsp;<code class="" style="line-height: 1;">scoped(file)</code>&nbsp;or&nbsp;<code class="" style="line-height: 1;">fileprivate</code>&nbsp;(Swift 3) or&nbsp;<code class="" style="line-height: 1;">private</code>&nbsp;(Swift 2 and 4?).</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">The logical role of a “file” in this design is to provide a boundary of encapsulation that is even lighter weight than a submodule: it doesn’t hide names. All declarations are implicitly available not only&nbsp;<em class="" style="line-height: 1;">within</em>&nbsp;the file but also&nbsp;<em class="" style="line-height: 1;">across</em>&nbsp;the file boundary (modulo access control). Files are to submodules as submodules are to modules.</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">If a future version of Swift were to eliminate files in favor of some kind of code browser it would still be very useful to have the ability to form a pure scope boundary (with no additional semantics). A&nbsp;<code class="" style="line-height: 1;">scope</code>&nbsp;declaration could be used to do this. Scope declarations could have an optional (or required) name and could even be nested. In this system&nbsp;<code class="" style="line-height: 1;">private</code>would reference the nearest anonymous ancestor scope declaration (or would be removed if we don’t allow anonymous scopes).</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">The logical structure of this design can be directly translated into a grammar that could be represented directly with syntax. Such a grammer could be used to support scripts with submodules. An example follows:</p><pre class="" style="margin-top: 21px; margin-bottom: 21px; tab-size: 4; color: rgb(17, 17, 17); font-size: 15px; background-color: rgb(248, 248, 248); height: 960px;"><code class="(null) dts hljs" style="line-height: inherit; display: block; overflow-x: auto; padding: 0.5em; color: rgb(51, 51, 51); height: auto;"><span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// A module contans a single implicit, anonymous submodule.</span>
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// submodule {</span>
  <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// A submodule may contain `scope` declarations (i.e. files) as well as other submodules.</span>
  <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// An anonymous scope is equivalent to a file in current Swift.</span>
  <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// If we introduce lexical scopes we would probably require them to be named explicitly.</span>
  <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// This example uses the anonymous scope in order to most closely match the role files play in the current system.</span>
  <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// Because `scope` does not provide a name boundary all names declared in one scope</span>
  <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// are visible in other scopes (modulo access control)</span>
  <span class="hljs-class">scope </span>{
      <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// Top-level declarations go here.</span>
      <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// This is equivalent to the top level of a file in Swift today.</span>
      <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// It is also equivalent to the top level of a file that does not contain </span>
      <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// a `submodule` declaration in this proposal.</span>
      
      <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// It would be possible to allow nested, named scopes.</span>
      <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// A scope name participates in the scope and name hierachies.</span>
      <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// However, it does not form a name boundary like a submodule does.</span>
      scope <span class="hljs-class">Named </span>{
        <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// This declares the static variable `Named.foo`</span>
        <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// `scoped(file)` references the nearest anonymous ancestor scope.</span>
        <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// It is used in this example for specificity.</span>
        <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// Real code would use the alias `private` or `fileprivate`</span>
        <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// If we introduce explicit scope syntax we would probably want a better name to refer</span>
        <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// to the nearest anonymous scope than `file` or we may just require all scopes to have a name.</span>
        scoped(file) var foo: String
      }
      <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// `Named.foo` is visible here</span>
  }
  <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// `Named.foo` is not visible here.</span>
  
  submodule <span class="hljs-class">Foo </span>{}
  submodule <span class="hljs-class">Baz </span>{}
  submodule <span class="hljs-class">Buzz </span>{
    <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// Equivalient to a file in current Swift.</span>
    <span class="hljs-class">scope </span>{
      <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// submodule declarations go here.</span>
      <span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">// This is equivalent to the top level scope of a file that contains the `submodule Foo` declaration.</span>
    }
    <span class="hljs-class">scope </span>{}
    submodule <span class="hljs-class">Baz </span>{}
  }
<span class="hljs-comment" style="color: rgb(153, 153, 136); font-style: italic;">//}</span></code></pre><h2 id="appendixbnamespacestylesubmodules" data-orig-id="appendixb:namespacestylesubmodules" class="" style="color: rgb(17, 17, 17); font-size: 27px; line-height: 42px; margin-top: 42px; margin-bottom: 21px; font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif;">Appendix B: namespace style submodules</h2><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">It is possible to design a system that allows a name boundary to be formed without also forming a scope boundary. A natural consequence of this is that symbols may be placed into a namespace-style submodule in many (unlimited) scopes via extension (even extension outside the module is theoretically possible). Allowing this runs contray to both of the two primary goals of this proposal (encapsulation and structure).</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Allowing a submodule to be extended in multiple scopes precludes the possibility of submodule internal visibility. A submodule internal access modifier could still be defined but it would not provide the guarantee it purports to. The submodule can be opened by extension anywhere within the module. If a lazy developer wants to access a submodule internal symbol from a distant subsytem all they need to do is add an extension and wrap the submodule internal symbol with a new symbol offering higher visibility*. In such a system there is the same wide gap between file scope and module scope that exists today.</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Allowing a submodule to be extended in multiple scopes precludes the ability to introduce real structure to a module. We are able to introduce structure to the&nbsp;<em class="" style="line-height: 1;">names</em>&nbsp;but not the module itself. The structure of a submodule in such a system may be widely dispersed throughout the module. It is not part of a strictly hierarchical structure of scopes which each having a single designated location within the larger structure.</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">What you&nbsp;<em class="" style="line-height: 1;">do</em>&nbsp;get from name boundaries that do not also form a scope boundary is a soft form of symbol hiding (soft because&nbsp;<em class="" style="line-height: 1;">all</em>&nbsp;submodules are available for import or extension anywhere within the program). This does provide some value, but not nearly as much value as is provided by a name boundary that is accompanied by a scope boundary.</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Another downside to namespace-style submodules that are open to extension is that they are much less likely to facilitate improved build performance because they don’t add any physical structure to the system.</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">Finally, lexical submodules have the potential to be confusing. If submodules form a name boundary (even a soft one) an import statement is required to access the symbols declared inside a submodule. Is code that surrounds a lexical submodule declaration able to see the symbols it declares without importing them? Most developers will expect the symbols to be available. It is probably necessary to make an exception to name boundary for the surrounding lexical context. However, if an exception is made then this system relies heavily on a file to provide a bound to the implicit symbol import.</p><p class="" style="color: rgb(17, 17, 17); font-family: 'Helvetica Neue', Helvetica, Arial, Verdana, sans-serif; word-wrap: break-word; margin: 1.3125em 0px; font-size: 1.1429em; line-height: 1.3125em;">*It is worth observing that the ability to violate encapsulation via extension (or subclassing) is one of the primary reasons Swift does not offer type-based access modifiers such as&nbsp;<code class="" style="line-height: 1;">typeprivate</code>&nbsp;or&nbsp;<code class="" style="line-height: 1;">protected</code>. The do not offer true encapsulation at all. They are a statement of intent that cannot really be verified in the way that is desired. They form a permeable rather than a hard boundary.</p></div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></blockquote></div></div></div></blockquote></div><br class=""></body></html>