<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=""><div class="">That’s an interesting proposal. Here are the issues I see:</div><div class=""><br class=""></div><div class="">- I don’t like nesting everything within a large “module” block. I would like a top-level “@module Foo” declaration for the entire file. Also, since any sub-modules would be nested within the implicit top-level module, I’d prefer the keyword “submodule”. Otherwise, what happens if I write:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Courier" class="">module Foundation {</font></div></blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Courier" class="">// Is this a module-extension? Can I insert new types or top-level functions in to Foundation?</font></div></blockquote></blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Courier" class="">// Am I creating a new top-level module named “Foundation”?</font></div></blockquote></blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Courier" class="">}</font></div></blockquote><div class=""><br class=""></div><div class="">Looking at this thread:</div><div class=""><br class=""></div><div class="">- There are certainly issues with access control of submodules. OTOH, I don’t really like the idea that one incorrect import in one file can expose an entire submodule as part of your module’s API.</div><div class=""><br class=""></div><div class="">More generally:</div><div class=""><br class=""></div><div class="">- Access control of submodules seems like something which could benefit from a single source of truth.</div><div class="">- Can submodules have independent versions? Where would we declare them?</div><div class=""><br class=""></div><div class="">I wonder if we should have something like “module manifest” for all of a library’s public submodules, similar to SwiftPM's package manifest. So, strawman syntax…</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Courier" class="">Module(Foo, version: 1.2.2, description: “A library for foo-ing around with”, submodules: [</font></div><div class=""><font face="Courier" class="">&nbsp; &nbsp; Module(Foo.Maths, version: 1.5.0, description: “A maths library supporting Foo”),</font></div><div class=""><font face="Courier" class="">&nbsp; &nbsp; Module(Foo.Formatters, version: 1.5.0, description: “Formatters for Foo types”)</font></div><div class=""><font face="Courier" class="">])</font></div></blockquote><div class=""><br class=""></div><div class="">So, in this case we had a module Foo, then we updated FooMaths with some new APIs (say some new operations/types were added, and we updated FooFormatters accordingly). However, the API of Foo itself hasn’t changed; it’s the same as it was ages ago. Would that be possible?</div><br class=""><div><blockquote type="cite" class=""><div class="">On 21 Feb 2017, at 02:47, Robert Widmann 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="">You’ll be delighted to know, then, that I’ve been thinking about this for a few weeks now and have a draft proposal that will be submitted for discussion shortly. &nbsp;I believe this can be an additive feature and still preserve all the goodness you would expect of a real module system.<br class=""><br class="">~Robert Widmann<br class=""><br class=""><blockquote type="cite" class="">On Feb 20, 2017, at 8:36 PM, Brent Royal-Gordon via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class="">Okay, lots of people want to have some kind of submodule feature, so I'd like to sketch one out so we can hopefully agree on what submodules might look like.<br class=""><br class="">***<br class=""><br class="">Any group of Swift files can be grouped together to form a submodule. Submodules belong within a particular module, and have a dotted name: If `ModKit` is a module, it might have a submodule called `ModKit.Foo`. Submodules can be nested within one another: `ModKit.Foo.Bar` is a submodule of `ModKit.Foo`, which is a submodule of `ModKit`.<br class=""><br class="">No new access levels are necessary. `internal` APIs are only visible within the submodule they're declared in; a module cannot see its submodules' `internal` APIs, and a submodule cannot see its parent module's `internal` APIs. If a submodule wants to expose some of its APIs to its parent or sibling modules, it must mark them as `public` or `open`. Then they can import the submodule to see its APIs:<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>import ModKit.Foo<br class=""><br class="">By default, outside modules cannot import a submodule. But an import in the parent module can be decorated by an access control keyword to allow that:<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>/// Any module outside ModKit can import ModKit.Foo and access its `public` and `open` APIs.<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>open import ModKit.Foo<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>/// Any module outside ModKit can import ModKit.Foo and access its `public` and `open` APIs, <br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>/// except `open` APIs are treated as `public`.<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>public import ModKit.Foo<br class=""><br class="">Imports may also be decorated by the `@exported` attribute, which exposes the submodule's APIs as though they were parent module APIs:<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>@exported open import ModKit.Foo<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>@exported public import ModKit.Foo<br class=""><br class="">(This is sort of half-implemented already in a buggy `@_exported` attribute.)<br class=""><br class="">Finally, the standard syntax for importing individual symbols can be used to cherry-pick types to treat differently:<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>// Most ModKit.Foo APIs are not importable...<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>import ModKit.Foo<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>// ...but SomeEnum can be imported as public...<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>public import enum ModKit.Foo.SomeEnum<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>// ...SomeClass can be imported as open...<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>open import class ModKit.Foo.SomeClass<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>// And ImportantStruct will import whenever you import ModKit.<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>@exported public import struct ModKit.Foo.ImportantStruct<br class=""><br class="">(This syntax should be enhanced to allow cherry-picked importing of global functions, constants, and variables.)<br class=""><br class="">If there are several different `import`s covering the same submodule or submodule symbol, the most permissive one wins.<br class=""><br class="">(In large projects, `public`, `open`, and `@exported` imports will most likely all be put in a single Policy.swift file or something, but this is not enforced by the language.)<br class=""><br class="">A submodule may not import any direct parent module (parent, grandparent, etc.), but may import any other submodule in the same module. This list shows permitted imports for a project with four modules/submodules:<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>ModKit<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>- ModKit.Foo<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>- ModKit.Foo.Bar<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>- ModKit.Quux<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>ModKit.Foo<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>- ModKit.Foo.Bar<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>- ModKit.Quux<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>ModKit.Foo.Bar<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>- ModKit.Quux<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>ModKit.Quux<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>- ModKit.Foo<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>- ModKit.Foo.Bar<br class=""><br class="">However, submodules may not form circular dependencies through imports—if `ModKit.Quux` imports `ModKit.Foo`, then `ModKit.Foo` cannot import `ModKit.Quux`. The `#if canImport()` feature cannot be used to probe for other submodules within the same top-level module you're in.<br class=""><br class="">At the compiler driver level, a submodule is specified by giving a `-module-name` parameter with a dot in it. When a file is compiled, only the filenames of the other .swift files in the same module are specified, along with .o files for any submodules; then all the .o files within that submodule are linked into a single .o file for the whole submodule. So files in `ModKit.Foo` would be compiled with only the .swift files in `ModKit.Foo` and the .o file for `ModKit.Foo.Bar`; then all the `ModKit.Foo` .o files would be linked into one .o file for the top-level `ModKit` to use. None of `ModKit.Foo`'s .swift files would be included in the command line when compiling the top-level `ModKit` module.<br class=""><br class="">(That bit is kind of speculative—particularly the idea of linking submodule files into a single .o file—but I think something like what I'm describing could work.)<br class=""><br class="">Because the compiler driver is used to group submodules together, Xcode can specify submodules in project file metadata and calculate a submodule dependency graph, while SwiftPM can use folders and compile submodules whenever the compiler emits an error indicating that a file tried to import a nonexistent submodule. Other build systems can do whatever best suits their style.<br class=""><br class="">***<br class=""><br class="">Thoughts?<br class=""><br class="">-- <br class="">Brent Royal-Gordon<br class="">Architechies<br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></blockquote><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></div></blockquote></div><br class=""></body></html>