https://github.com/apple/swift
Raw File
Tip revision: d9561d92782f33373f4a83571cca1fbd8d2994e2 authored by Karoy Lorentey on 09 July 2018, 10:35:27 UTC
Merge pull request #17769 from lorentey/shorten-anyhashable-tests-4.2
Tip revision: d9561d9
Modules.rst
:orphan:

.. @raise litre.TestsAreMissing
.. default-role:: term
.. title:: Modules User Model


A `module` is the primary unit of code sharing in Swift. This document
describes the experience of using modules in Swift: what they are and what they
provide for the user.

.. warning:: This document was used in planning Swift 1.0; it has not been kept
  up to date.

.. contents:: :local:


High-Level Overview
===================

A module contains declarations
------------------------------

The primary purpose of a module is to provide declarations of types, functions,
and global variables that are present in a library. `Importing <import>` the
module gives access to these declarations and allows them to be used in your
code.

::

  import Chess
  import Foundation

You can also selectively import certain declarations from a module::

  import func Chess.createGreedyPlayer
  import class Foundation.NSRegularExpression

.. admonition:: Comparison with Other Languages

  Importing a module is much like importing a library in Ruby, Python, or Perl,
  importing a class in Java, or including a header file in a C-family language.
  However, unlike C, module files are not textually included and must be valid
  programs on their own, and may not be in a textual format at all. Unlike Java,
  declarations in a module are not visible at all until imported. And unlike the
  dynamic languages mentioned, importing a module cannot automatically cause
  any code to be run.


Imported declarations can be accessed with qualified or unqualified lookup
--------------------------------------------------------------------------


Once a module has been imported, its declarations are available for use within
the current source file. These declarations can be referred to by name, or
by `qualifying <qualified name>` them with the name of the module::

  func playChess(_ blackPlayer : Chess.Player, whitePlayer : Chess.Player) {
    var board = Board() // refers to Chess.Board
  }


Modules provide a unique context for declarations
-------------------------------------------------

A declaration in a module is unique; it is never the same as a declaration with
the same name in another module (with one caveat described below). This means
that two types ``Chess.Board`` and ``Xiangqi.Board`` can exist in the same
program, and each can be referred to as ``Board`` as long as the other is not
visible. If more than one imported module declares the same name, the full
`qualified name` can be used for disambiguation.

.. note::

  This is accomplished by including the module name in the `mangled name` of a
  declaration. Therefore, it is an ABI-breaking change to change the name of a
  module containing a public declaration.

.. warning::

  The one exception to this rule is declarations that must be compatible with
  Objective-C. Such declarations follow the usual Objective-C rules for name
  conflicts: all classes must have unique names, all protocols must have unique
  names, and all constructors, methods, and properties must have unique names
  within their class (including inherited methods and properties).


Modules may contain code
------------------------

In addition to declarations, modules may contain implementations of the
functions they define. The compiler may choose to use this information when
optimizing a user's program, usually by inlining the module code into a caller.
In some cases [#]_, the compiler may even use a module's function
implementations to produce more effective diagnostics.

Modules can also contain `autolinking` information, which the compiler passes
on to the linker. This can be used to specify which library implements the
declarations in the module.

.. [#] Specifically, code marked with the ``@_transparent`` attribute is
   required to be "transparent" to the compiler: it *must* be inlined and
   will affect diagnostics.


Modules can "re-export" other modules
-------------------------------------

.. warning:: This feature is likely to be modified in the future.

Like any other body of code, a module may depend on other modules in its
implementation. The module implementer may also choose to `re-export` these
modules, meaning that anyone who imports the first module will also have access
to the declarations in the re-exported modules. ::

  @exported import AmericanCheckers

As an example, the "Cocoa" `framework` on OS X exists only to re-export three
other frameworks: AppKit, Foundation, and CoreData.

Just as certain declarations can be selectively imported from a module, so too
can they be selectively re-exported, using the same syntax::

  @exported import class AmericanCheckers.Board


.. _module-naming:

Modules are uniquely identified by their name
---------------------------------------------

Module names exist in a global namespace and must be unique. Like type names,
module names are conventionally capitalized.

.. admonition:: TODO

  While this matches the general convention for Clang, there are advantages to
  being able to rename a module for lookup purposes, even if the ABI name stays
  the same. It would also be nice to avoid having people stick prefixes on their
  module names the way they currently do for Objective-C classes.

.. note::

  Because access into a module and access into a type look the same, it is bad
  style to declare a type with the same name as a top-level module used in your
  program::

    // Example 1:
    import Foundation
    import struct BuildingConstruction.Foundation

    var firstSupport = Foundation.SupportType() // from the struct or from the module?


    // Example 2:
    import Foundation
    import BuildingConstruction

    Foundation.SupportType() // from the class or from the module?

  In both cases, the type takes priority over the module, but this should still
  be avoided.

  .. admonition:: TODO

    Can we enforce this in the compiler? It seems like there's no way around
    Example 2, and indeed Example 2 is probably doing the wrong thing.


``import``
==========

As shown above, a module is imported using the ``import`` keyword, followed by
the name of the module::

  import AppKit

To import only a certain declaration from the module, you use the appropriate
declaration keyword::

  import class AppKit.NSWindow
  import func AppKit.NSApplicationMain
  import var AppKit.NSAppKitVersionNumber
  import typealias AppKit.NSApplicationPresentationOptions

- ``import typealias`` has slightly special behavior: it will match any type
  other than a protocol, regardless of how the type is declared in the imported
  module.
- ``import class``, ``struct``, and ``enum`` will succeed even if the
  name given is a typealias for a type of the appropriate kind.
- ``import func`` will bring in all overloads of the named function.
- Using a keyword that doesn't match the named declaration is an error.

.. admonition:: TODO

  There is currently no way to selectively import extensions or operators.


.. _implicit-visibility:

Multiple source files
---------------------

Most programs are broken up into multiple source files, and these files may
depend on each other. To facilitate this design, declarations in *all* source
files in a module (including the "main module" for an executable) are implicitly
visible in each file's context. It is almost as if all these files had been
loaded with ``import``, but with a few important differences:

- The declarations in other files belong to the module being built, just like
  those in the current file. Therefore, if you need to refer to them by
  qualified name, you need to use the name of the module being built.
- A module is a fully-contained entity: it may depend on other modules, but
  those other modules can't depend on it. Source files within a module may
  have mutual dependencies.

.. admonition:: FIXME

  This wouldn't belong in the user model at all except for the implicit
  visibility thing. Is there a better way to talk about this?


Ambiguity
---------

Because two different modules can declare the same name, it is sometimes
necessary to use a `qualified name` to refer to a particular declaration::

  import Chess
  import Xiangqi

  if userGame == "chess" {
    Chess.playGame()
  } else if userGame == "xiangqi" {
    Xiangqi.playGame()
  }

Here, both modules declare a function named ``playGame`` that takes no
arguments, so we have to disambiguate by "qualifying" the function name with
the appropriate module.

These are the rules for resolving name lookup ambiguities:

1. Declarations in the current source file are best.
2. Declarations from other files in the same module are better than
   declarations from imports.
3. Declarations from selective imports are better than declarations from
   non-selective imports. (This may be used to give priority to a particular
   module for a given name.)
4. Every source file implicitly imports the core standard library as a
   non-selective import.
5. If the name refers to a function, normal overload resolution may resolve
   ambiguities.

.. _submodules:

Submodules
----------

.. warning:: This feature was never implemented, or even fully designed.

For large projects, it is usually desirable to break a single application or
framework into subsystems, which Swift calls "submodules". A submodule is a
development-time construct used for grouping within a module. By default,
declarations within a submodule are considered "submodule-private", which
means they are only visible within that submodule (rather than across the
entire module). These declarations will not conflict with declarations in other
submodules that may have the same name.

Declarations explicitly marked "whole-module" or "API" are still visible
across the entire module (even if declared within a submodule), and must have a
unique name within that space.

The `qualified name` of a declaration within a submodule consists of the
top-level module name, followed by the submodule name, followed by the
declaration.

.. note::

  Submodules are an opportunity feature for Swift 1.0.

.. admonition:: TODO

  We need to decide once and for all whether implicit visibility applies across
  submodule boundaries, i.e. "can I access the public Swift.AST.Module from
  Swift.Sema without an import, or do I have to say ``import Swift.AST``?"

  Advantages of module-wide implicit visibility:

  - Better name conflict checking. (The alternative is a linker error, or worse
    *no* linker error if the names have different manglings.)
  - Less work if things move around.
  - Build time performance is consistent whether or not you use this feature.

  Advantages of submodule-only implicit visibility:

  - Code completion will include names of public things you don't care about.
  - We haven't actually tested the build time performance of any large Swift
    projects, so we don't know if we can actually handle targets that contain
    hundreds of files.
  - Could be considered desirable to force declaring your internal dependencies
    explicitly.
  - In this mode, we could allow two "whole-module" declarations to have the
    same name, since they won't. (We could allow this in the other mode too
    but then the qualified name would always be required.)

  Both cases still use "submodule-only" as the default access control, so this
  only affects the implicit visibility of whole-module and public declarations.


Import Search Paths
-------------------

.. admonition:: FIXME

  Write this section. Can source files be self-contained modules? How does -i
  mode work? Can the "wrong" module be found when looking for a dependency
  (i.e. can I substitute my own Foundation and expect AppKit to work)?
  How are modules stored on disk? How do hierarchical module names work?


Interoperability with Objective-C via Clang
===========================================

The compiler has the ability to interoperate with C and Objective-C by
importing `Clang modules <Clang module>`. This feature of the Clang compiler
was developed to provide a "semantic import" extension to the C family of
languages. The Swift compiler uses this to expose declarations from C and
Objective-C as if they used native Swift types.

In all the examples above, ``import AppKit`` has been using this mechanism:
the module found with the name "AppKit" is generated from the Objective-C
AppKit framework.


Clang Submodules
----------------

Clang also has a concept of "submodules", which are essentially hierarchically-
named modules. Unlike Swift's :ref:`submodules`, Clang submodules are visible
from outside the module. It is conventional for a top-level Clang module to
re-export all of its submodules, but sometimes certain submodules are specified
to require an explicit import::

  import OpenGL.GL3


Module Overlays
---------------

.. warning:: This feature has mostly been removed from Swift; it's only in use
  in the "overlay" libraries bundled with Swift itself.

If a source file in module A includes ``import A``, this indicates that the
source file is providing a replacement or overlay for an external module.
In most cases, the source file will `re-export` the underlying module, but
add some convenience APIs to make the existing interface more Swift-friendly.

This replacement syntax (using the current module name in an import) cannot
be used to overlay a Swift module, because :ref:`module-naming`.


Multiple source files, part 2
-----------------------------

In migrating from Objective-C to Swift, it is expected that a single program
will contain a mix of sources. The compiler therefore allows importing a single
Objective-C header, exposing its declarations to the main source file by
constructing a sort of "ad hoc" module. These can then be used like any
other declarations imported from C or Objective-C.

.. note:: This is describing the feature that eventually became "bridging
  headers" for app targets.


Accessing Swift declarations from Objective-C
---------------------------------------------

.. warning:: This never actually happened; instead, we went with "generated
  headers" output by the Swift compiler.

Using the new ``@import`` syntax, Objective-C translation units can import
Swift modules as well. Swift declarations will be mirrored into Objective-C
and can be called natively, just as Objective-C declarations are mirrored into
Swift for `Clang modules <Clang module>`. In this case, only the declarations
compatible with Objective-C will be visible.

.. admonition:: TODO

  We need to actually do this, but it requires working on a branch of Clang, so
  we're pushing it back in the schedule as far as possible. The workaround is
  to manually write header files for imported Swift classes.

.. admonition:: TODO

  Importing Swift sources from within the same target is a goal, but there are
  many difficulties. How do you name a file to be imported? What if the file
  itself depends on another Objective-C header? What if there's a mutual
  dependency across the language boundary? (That's a problem in both directions,
  since both Clang modules and Swift modules are only supposed to be exposed
  once they've been type-checked.)


Glossary
========

.. glossary::

  autolinking
    A technique where linking information is included in compiled object files,
    so that external dependencies can be recorded without having to explicitly
    specify them at link time.

  Clang module
    A module whose contents are generated from a C-family header or set of
    headers. See Clang's Modules__ documentation for more information.

    __ http://clang.llvm.org/docs/Modules.html

  framework
    A mechanism for library distribution on OS X. Traditionally contains header
    files describing the library's API, a binary file containing the
    implementation, and a directory containing any resources the library may
    need.

    Frameworks are also used on iOS, but as of iOS 7 custom frameworks cannot
    be created by users.

  import
    To locate and read a module, then make its declarations available in the
    current context.

  library
    Abstractly, a collection of APIs for a programmer to use, usually with a
    common theme. Concretely, the file containing the implementation of these
    APIs.

  mangled name
    A unique, internal name for a type or value. The term is most commonly used
    in C++; see Wikipedia__ for some examples. Swift's name mangling scheme is
    not the same as C++'s but serves a similar purpose.

    __ https://en.wikipedia.org/wiki/Name_mangling#C.2B.2B

  module
    An entity containing the API for a library, to be `imported <import>` into
    a source file.

  qualified name
    A multi-piece name like ``Foundation.NSWindow``, which names an entity
    within a particular context. This document is concerned with the case where
    the context is the name of an imported module.

  re-export
    To directly expose the API of one module through another module. Including
    the latter module in a source file will behave as if the user had also
    included the former module.

  serialized module
    A particular encoding of a module that contains declarations that have
    already been processed by the compiler. It may also contain implementations
    of some function declarations in `SIL` form.

  SIL
    "Swift Intermediate Language", a stable IR for the distribution of
    inlineable code.


  target
    A dynamic library, framework, plug-in, or application to be built.
    A natural LTO boundary, and roughly the same as what Xcode requires
    separate targets to build.
back to top