[swift-evolution] [Proposal][Discussion] Qualified Imports

Pyry Jahkola pyry.jahkola at iki.fi
Thu Jul 21 03:43:15 CDT 2016

Back to the pre-proposal itself,

I support taking it forward and it being accepted in some form. However, I remain unconvinced that we'd ever want `hiding` imports in Swift.

Here are a few specific comments on the text (8 in total):
> Motivation
> The existing syntax for qualified imports from modules is needlessly explicit, does not compose, and has a default semantics that dilutes the intended meaning of the very operation itself. Today, a qualified import looks something like this
> import class Foundation.Date
> This means that clients of Foundation that wish to see only Date must know the exact kind of declaration that identifier is.

1. Given this motivation, isn't it sufficient being able to import without knowing the exact kind of declaration? In other words, I agree we want `using` imports, but what motivates `hiding` imports really?

As it was pointed out by Félix, the use of `hiding` imports moves away the focus of what is imported into what is not imported, and while name conflict problems usually arise when importing another module on top of already working code, I think it's better to fix them at the import statement which brings in the winning name declaration, i.e. the `using` import.

>  <https://gist.github.com/CodaFi/42e5e5e94d857547abc381d9a9d0afd6#proposed-solution>Proposed solution
> The grammar and semantics of qualified imports will change completely with the addition of import qualifiers and import directives. We also introduce two new contextual keywords: using and hiding, to facilitate fine-grained usage of module contents.

2. Is there a typo above? The proposal does not mention import qualifiers anywhere else. I guess those are part of what got postponed into later proposals.

> Detailed design
> 1) using: The using directive is followed by a list of identifiers for non-member nominal declarations within the imported module that should be exposed to this file. 
> // The only visible parts of Foundation in this file are 
> // Foundation.Date, Foundation.DateFormatter, and Foundation.DateComponents
> //
> // Previously, this was
> // import class Foundation.Date
> // import class Foundation.DateFormatter
> // import class Foundation.DateComponents
> import Foundation using (Date, DateFormatter, DateComponents)
3. I support the idea of `using` imports. That's something we do need, and its introduction is sufficient to cover the existing use cases of the old selective import syntax about to be deprecated here.

> 2) hiding: The hiding directive is followed by a list of identifiers for non-member nominal declarations within the imported module that should be hidden from this file.
> // Imports all of Foundation except `Date`
> import Foundation hiding (Date)
> As today, all hidden identifiers do not hide the type, they merely hide that type’s members and its declaration. For example, this means values of hidden types are still allowed. Unlike the existing implementation, using their members is forbidden.
4. Hmm, the above design detail is easily missed when reading the proposal. So what you're proposing is that the hiding of Date essentially turns Date into a type that the code will know almost nothing about, except it's something we can pass to other types' methods that expect a Date, am I right?

What's the benefit in that? Do you anticipate it will make importing lighter somehow, possibly improving compilation or library loading speed? You mentioned something along those lines in the Motivation, but I'm not sure if I got it right here.

> Import directives chain to one another and can be used to create a fine-grained module import:
> // This imports Swift.Int, Swift.Double, and Swift.String but hides Swift.String.UTF8View
> import Swift using (String, Int, Double) 
>              hiding (String.UTF8View)
> Directive chaining occurs left-to-right:
> // This says to 1) Use Int 2) Hide String 3) rename Double to Triple.  It is invalid
> // because 1) Int is available 2) String is not, error.
> import Swift using (Int) hiding (String)
> // Valid.  This will be merged as `using (Int)`
> import Swift using () using (Int)
> // Valid.  This will be merged as `hiding (String, Double)`
> import Swift hiding (String) hiding (Double) hiding ()
> // Valid (if redundant). This will be merged as `using ()`
> import Swift using (String) hiding (String)
5. These chaining rules do fit on the back of a napkin, but I'm not sure if we need them at all. I'm not convinced we need `hiding` imports, and without hiding imports, we need no rules for the order of imports.

> Because import directives are file-local, they will never be exported along with the module that declares them.
6. +1 on imports being file-local, that's essentially what we have today.

What I will keep suggesting is that `using` imports actually take up the name in the file-local scope such that nothing else in the same file's scope — be it another `import ... using (...)`, a local type declaration, function, or value — can declare the same name with a different meaning. That way, a plain

    import Foo

can import everything from Foo, while another

    import Foo using (Bar)

can be used to explicitly choose the Bar the code is about to use.

7. (Off-topic to this proposal.) Given that you briefly expressed the interest in turning imports `public` or `internal` — some of which would indeed be useful in a better module system —, I think it's curious in that design that the default visibility level of imports would likely be `fileprivate`, which is different from the rest of Swift. That said, I think it's absolutely right for imports to remain file-local by default, because explicit tends to be better than implicit.

> Impact on existing code
> Existing code that is using qualified module import syntax (import {func|class|typealias|class|struct|enum|protocol} <qualified-name>) will be deprecated and should be removed or migrated. 
8. +1 on deprecating the old selective import syntax.

Thank you for driving this forward!

— Pyry

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160721/344a3516/attachment.html>

More information about the swift-evolution mailing list