# Interoperability between Swift and C++

This document discusses the design and tradeoffs for bidirectional API-level
interoperability between Swift and C++.

Assumptions:

* We can make changes to the Swift language and the standard library.
  * The proposed changes must fit Swift's goals and philosophy. In other words,
    the proposed changes must have a reasonable chance to be accepted by the
    Swift community. For example, a change that requires an ABI break on Apple
    platforms is a non-starter.
  * Forking the Swift language or standard library, or creating a dialect
    without a fork (and therefore, being able to make radical changes to Swift's
    goals, philosophy, safety, or ergonomics) are not interesting options, and
    therefore, are not considered or discussed.
* We can make limited changes to the C++ code, toolchain, standard library
  implementation, and runtime environment.
  * The cost of such changes must be taken into account. Changes that require an
    ABI break for C++ might be interesting for users who control the complete
    toolchain, but are non-starters for the community at large; therefore, such
    changes can only be considered an optimization. Changes that require
    significant manual work on existing C++ code by end users can also be
    considered only as optimizations or improvements for ergonomics.

- [Goals](#goals)
- [Current state of art: importing C code into Swift](#current-state-of-art-importing-c-code-into-swift)
- [Importing C++ APIs into Swift](#importing-c-apis-into-swift)
  * [Names, identifiers and keywords](#names-identifiers-and-keywords)
  * [Functions](#functions)
    + [Non-const pointer and reference parameters](#non-const-pointer-and-reference-parameters)
    + [Const reference parameters](#const-reference-parameters)
    + [Mapping overload sets](#mapping-overload-sets)
    + [Inline functions](#inline-functions)
  * [Namespaces and modules](#namespaces-and-modules)
    + [The "std" namespace](#the-std-namespace)
  * [Structs and classes](#structs-and-classes)
    + [Mapping the type itself and its special member functions](#mapping-the-type-itself-and-its-special-member-functions)
    + [Special member functions with incorrect semantics](#special-member-functions-with-incorrect-semantics)
    + [Special member functions that throw exceptions](#special-member-functions-that-throw-exceptions)
    + [Precise destruction semantics](#precise-destruction-semantics)
    + [Member functions that return inner pointers](#member-functions-that-return-inner-pointers)
    + [Differences in move semantics between C++ and Swift](#differences-in-move-semantics-between-c-and-swift)
    + [Move-only C++ classes](#move-only-c-classes)
    + [Move-only C++ classes: mapping in Swift 5](#move-only-c-classes-mapping-in-swift-5)
    + [Move-only C++ classes: mapping to move-only Swift types (in future Swift versions)](#move-only-c-classes-mapping-to-move-only-swift-types-in-future-swift-versions)
    + [Non-destructive moves](#non-destructive-moves)
    + [Non-movable C++ classes](#non-movable-c-classes)
    + [Member functions](#member-functions)
    + [Const-qualified member functions in C++ classes](#const-qualified-member-functions-in-c-classes)
    + [Volatile-qualified member functions](#volatile-qualified-member-functions)
    + [Ref-qualified member functions](#ref-qualified-member-functions)
    + [Final functions](#final-functions)
    + [Getters and setters](#getters-and-setters)
    + [Pointers to members](#pointers-to-members)
    + [Virtual member functions](#virtual-member-functions)
    + [Inherited APIs](#inherited-apis)
    + [Conversions between derived and base classes](#conversions-between-derived-and-base-classes)
    + [Subclassing C++ classes in Swift](#subclassing-c-classes-in-swift)
    + [Making C++ classes conform to Swift protocols](#making-c-classes-conform-to-swift-protocols)
  * [Enums](#enums)
  * [Templates](#templates)
    + [Function templates](#function-templates)
    + [Function templates: import as Swift generic functions](#function-templates-import-as-swift-generic-functions)
    + [Function templates: allow to specify template arguments](#function-templates-allow-to-specify-template-arguments)
    + [Function templates: calls to specific specializations](#function-templates-calls-to-specific-specializations)
    + [Function templates: calls with generic type parameters](#function-templates-calls-with-generic-type-parameters)
    + [Function templates: importing as real generic functions](#function-templates-importing-as-real-generic-functions)
    + [Class templates](#class-templates)
    + [Class templates: importing instantiation behind typedef](#class-templates-importing-instantiation-behind-typedef)
    + [Class templates: importing specific specializations](#class-templates-importing-specific-specializations)
    + [Class templates: using with generic type parameters](#class-templates-using-with-generic-type-parameters)
    + [Class templates: using in generic code through a synthesized protocol](#class-templates-using-in-generic-code-through-a-synthesized-protocol)
    + [Class templates: importing as real generic structs](#class-templates-importing-as-real-generic-structs)
    + [Mapping SFINAE](#mapping-sfinae)
    + [Variadic templates](#variadic-templates)
    + [Non-type template parameters](#non-type-template-parameters)
    + [Template template parameters](#template-template-parameters)
  * [Overloaded operators](#overloaded-operators)
  * [`operator*`, `operator->`](#operator-star-operator-arrow)
  * [`operator[]`](#operator-square-brackets)
  * [`operator()`](#operator-parentheses)
  * [Literal operators](#literal-operators)
  * [Exceptions](#exceptions)
  * [Atomics](#atomics)
  * [Importing non-const pointer as extra return values](#importing-non-const-pointer-as-extra-return-values)
- [Enhancing C++ API mapping into Swift with bridging](#enhancing-c-api-mapping-into-swift-with-bridging)
  * [Bridging data types with different memory layout](#bridging-data-types-with-different-memory-layout)
  * [Bridging: behind the scenes](#bridging-behind-the-scenes)
  * [Bridging does not work in every context](#bridging-does-not-work-in-every-context)
  * [Bridging `std::function`](#bridging-std-function)
  * [Bridging `std::string`](#bridging-std-string)
  * [Bridging `std::vector`](#bridging-std-vector)
  * [Bridging `std::set`, `std::map`](#bridging-std-set-std-map)
  * [Bridging `std::unordered_set`, `std::unordered_map`](#bridging-std-unordered-set-std-unordered-map)
  * [Bridging `std::tuple`, `std::pair`](#bridging-std-tuple-std-pair)
  * [Bridging `std::span`](#bridging-std-span)
  * [Standard C++ containers in general](#standard-c-containers-in-general)
  * [Custom C++ containers](#custom-c-containers)
  * [Bridging `absl::flat_hash_{set,map}`, `absl::node_hash_{set,map}`](#bridging-absl-hash-set-map)
- [Enhancing C++ API mapping into Swift with annotations](#enhancing-c-api-mapping-into-swift-with-annotations)
  * [Annotation workflow](#annotation-workflow)
  * [Tooling to infer nullability annotations](#tooling-to-infer-nullability-annotations)
  * [APIs that take a pointer and count](#apis-that-take-a-pointer-and-count)
- [Current state of art: importing Swift code into C](#current-state-of-art-importing-swift-code-into-c)
- [Importing Swift APIs into C++](#importing-swift-apis-into-c)
  * [Resilient types](#resilient-types)
- [Forum discussions](#forum-discussions)

# Goals

What are the properties of a good interoperability layer? Exercising
interoperability is not in itself a goal of any Swift or C++ user. Therefore,
for API users interoperability should be maximally transparent in all aspects:
API design and ergonomics, editor integration and tooling, and performance. For
API vendors, interoperability should not be a significant extra burden, while
allowing API vendors to own and curate the imported API surface. Let's discuss
what these points mean.

**API design and ergonomics.** Ideally, users working in Swift should not feel
any difference between native Swift APIs and imported C++ APIs.

For example, while it is possible to write a custom hashtable in Swift, it is
done extremely rarely, and most code uses the vocabulary types `Set` and
`Dictionary`. Therefore, if C++ APIs that used `std::unordered_map` or
`flat_hash_map` types, when imported in Swift, would continue using those C++
map types, they would look weird and foreign in Swift. Idiomatic Swift code that
uses `Set` and `Dictionary` will have to convert the data into these foreign
hashtable types before calling imported C++ APIs.

As another example, C++ functions often receive values by const reference or by
const pointer. Semantically, the closest equivalent in Swift is `UnsafePointer`.
However, `UnsafePointer` is not as common in Swift as const references are in
C++; it is not idiomatic for Swift APIs to accept `UnsafePointer` outside of a
couple exceptional situations (for example, implementations of low-level
facilities, performance-sensitive code, etc.) Therefore, if C++ APIs, when
imported in Swift, would use `UnsafePointer` a lot, they would look weird and
foreign in Swift. Imported C APIs, when they are not operating on Objective-C
types, already use `UnsafePointer` a lot, and look non-idiomatic because of
that. Swift provides some affordances that make calling them easier.

**Editor integration and tooling** should transparently support code in both
languages. To the extent possible, all editor operations should "see through"
the interop. For example, if the user invokes the "rename function" refactoring,
it should rename all definitions, declarations, and usages across Swift and C++
code. This goal has been largely achieved for Swift/Objective-C interop, and we
are planning to rely on the same mechanisms for Swift/C++ interop.

**Performance.** C++ APIs, when used from Swift, ideally, should have
performance characteristics identical to when they are used from C++.

**Interop must not be a burden for API vendors.** Enabling Swift code to call a
certain C++ library should create minimal burden for the owners of that C++
library. Ideally, it should be possible without any involvement of the owners.

For example, requiring the API owners to create an API description file (like in
CLIF for Python), or a glue layer (like in JNI for Java) is a significant
burden. Most API owners are not going to do it without specific requests from
users, and even when such request is received, many API owners will carefully
consider if they want to take on maintenance of this extra file.

It may be possible to allow users to do the work necessary to expose a C++
library to Swift, however, that is not a great option either. A C++ library
might end up with multiple (incompatible) bindings of varying quality, covering
different parts of the API. In addition, the owner of the API loses control of
the API surface.

**Allow API vendors to own and curate the imported API surface.** While the
minimal amount of work to expose a C++ library to Swift should be ideally "none"
(it should just work), API vendors should own the Swift API surface of their C++
libraries, and should be able to adjust it where the automated interop is not
satisfactory.

**Tension and conflicts between goals.** These goals are conflicting. For
example, API ergonomics are in conflict with performance: we can provide a more
ergonomic API if we automatically bridge C++ types to corresponding Swift
vocabulary types at the API boundary, however, these type conversions will cost
CPU cycles. The solutions will be designed on a case by case basis: sometimes,
we will pick one side of the tradeoff, sometimes we will pick one side but allow
the user to override the default, and sometimes we will add multiple facilities
that pick different sides, forcing the user to choose.

# Current state of art: importing C code into Swift

Swift/C++ interoperability builds on top of the Swift/C interoperability, so it
helps to be familiar with [Swift's strategy for importing C
modules](HowSwiftImportsCAPIs.md).

# Importing C++ APIs into Swift

Now let's talk about extending existing rules to handle C++.

## Names, identifiers and keywords

C++ allows defining names that are not identifiers:

* Destructors
* Overloaded operators
* Literal operators

Member functions with non-identifier names are discussed in the section about
classes. Other constructs are discussed in their respective sections.

## Functions

### Non-const pointer and reference parameters

In C++, there are no language requirements for pointers passed as function
arguments. For example, given a function signature like this:

```c++
void increment(int *value);
```

C++ as a language poses no requirements for `value` to live long enough during
the function call, or even that `value` points to valid memory when the
function is called; `value` can be null or it can be an invalid (for example,
freed) pointer. There are also no requirements about the memory pointed to by
`value` being initialized, or valid to dereference without data races. Pointers
are also allowed to alias other memory, as long as the types are compatible.
Pointers also don't imply anything about ownership or non-ownership.

Rules in C++ about references are a bit tighter, but not much. The only
differences are that a reference can't be null, and that it must be bound to a
valid object when it is initially created.

In practice, engineers working in C++ often make the following assumptions about
third-party APIs, even though these properties are not guaranteed by the
language, and are often not explicitly documented by the API:

- All pointers passed to a function are valid to dereference.

- Almost all pointers passed to a function remain valid to dereference while the
  function is running.

- Almost all pointers passed to a function are valid to dereference without data
  races.

- Almost all pointers passed to a function point to initialized data. Passing a
  pointer to uninitialized memory and expecting the function to initialize it
  happens occasionally, but it is not common.

- Often enough, pointers passed to a function are not null.

- Often enough, pointers of different types don't alias each other's subobjects.

- Almost all `const &T` parameters are semantically equivalent to passing `T` by
  value.

In Swift, passing unsafe pointers as function arguments is not idiomatic.
Idiomatic code passes structs by value, and classes by reference. `inout`
parameters in Swift allow functions to read and modify storage specified by the
caller.  The argument for the `inout` parameter must be a storage reference
expression.

```swift
func increment(_ value: inout Int) {
  value += 1
}

struct TwoInts {
  var x: Int = 0
  var y: Int = 0
}

func caller() {
  var ints = TwoInts()
  increment(&ints.x)
  // ints.x is 1
  // ints.y is 0
}
```

To understand the constraints that Swift puts on `inout` parameters, let's take
a look at the mental model for introduced in the [Ownership
manifesto](OwnershipManifesto.md) and in [SE-0176 Enforce Exclusive Access to
Memory](https://github.com/apple/swift-evolution/blob/main/proposals/0176-enforce-exclusive-access-to-memory.md).
When the caller binds a storage reference to an `inout` parameter, it starts a
non-instantaneous access to the whole value that occupies the storage. This
access ends when the callee returns.  Overlapping accesses are not allowed, and
therefore, while an `inout` parameter is live, original value may not be
accessed.

(Note that before the ownership manifesto, `inout` parameters were explained in
terms of a different model that might be easier to understand. Nevertheless,
both models are equivalent. The old model stated that on function entry, the
value is moved from the caller-specified storage reference into the `inout`
parameter, and moved from the `inout` parameter back into the original storage
on function exit.  During the execution of the function, the original storage
remains uninitialized, and therefore, the whole value that occupied that storage
remains inaccessible until the function returns.)

In practice, `inout` parameters are implemented as passing a pointer to the
storage that should be mutated, while maintaining behavior identical to the
models explained above. As a consequence of these models, `inout` parameters
provide the following guarantees:

- the memory backing an `inout` parameter is valid to access throughout the
  execution of a function.

- since `inout` parameters are not pointers, there is no such thing as "null
  `inout` parameter".

- `inout` parameters are valid to read and modify throughout the execution of
  a function without data races, unless the function itself has shared the
  parameter with multiple threads.

- `inout` are backed by initialized memory on function entry and function exit
  (an implication of the copy-in/copy-out semantics). Destroying the object in
  `inout` requires using unsafe constructs. Therefore, in safe Swift `inout`
  parameters are backed by initialized memory throughout function execution.

- `inout` parameters don't alias each other or any other values that program is
  allowed to access at that point. Remember that the original value that is
  bound to an `inout` parameter is inaccessible for the duration of the `inout`
  binding.

In practice, non-const pointers and references in function parameters are most
often used for the same purpose as Swift's `inout`, so it is desirable to map
them to each other.

```c++
// C++ header.

void incrementBoth(int *value1, int *value2);
```

```swift
// C++ header imported in Swift (possible mapping).

func incrementBoth(_ value1: inout Int, _ value2: inout Int)
```

The `incrementBoth` function imported like this has more restrictions in Swift
than in C++ (for example, arguments may not alias). Calling this C++ function
from Swift does not create a new kind of safety issues in Swift, because a
language with more restrictions calls a language with fewer restrictions. From
the API point of view, it should not be a problem either, unless the caller
needs to pass arguments that alias (Swift's enforcement of exclusivity will
prevent that).

Based on the comparison above, it looks like Swift's `inout` provides strictly
more guarantees than C++'s non-const pointers and references. Therefore, it is
not safe to map them to each other in all cases.  For example, we can't apply
this mapping when Swift is implementing a function exposed to C++, for example:

```c++
// C++ header.

class Incrementer {
public:
  virtual void incrementBoth(int *value1, int *value2) = 0;
};
```

```swift
// C++ header imported in Swift (possible mapping).

protocol Incrementer {
  func incrementBoth(_ value1: inout Int, _ value2: inout Int)
}

struct MyIncrementer: Incrementer {
  func incrementBoth(_ value1: inout Int, _ value2: inout Int) {
    // The language requires that `value1` and `value2` don't alias.
  }
}
```

It would be unsafe to expose an Swift implementation of
`Incrementer.incrementBoth` through the C++ signature, unless the C++ function
already has Swift-like preconditions for pointer arguments. For true inout
parameters in C++, those preconditions should in fact hold, even if the C++
function does not formally document them.

### Const reference parameters

In C++, const references in function arguments are most often used to avoid
copying objects passed to functions. Swift solves this problem in two ways:

- by providing language features that allow the engineer to introduce
  indirections (for example, reference types, existential types, indirect enum
  cases, tools for defining copy-on-write types),

- by automatically passing large arguments indirectly without copying them,
  where possible.

It is not feasible to automatically map C++ const references to Swift-specific
indirections like class types, because that would require changing the memory
layout through non-trivial bridging.

**Option 1: Import `const T&` as `UnsafePointer<T>`.**

We can easily map C++ const references in function parameters to
`UnsafePointer<T>` in Swift, however, the resulting APIs will not look
idiomatic. They will be usable from Swift, because Swift code can make an unsafe
pointer with the `&` operator, however, it can only be applied to mutable
storage locations. Therefore, more variables will be mutable in Swift than
necessary. Furthermore, to make some values mutable, the code will need to
make a copy that will be stored in a mutable variable -- defeating the point of
the C++ API taking a const reference.

```c++
void printInt(const int &value);
```

```swift
// C++ header imported in Swift.

func printInt(_ value: UnsafePointer<Int>)
```

```swift
// Usage example.

func caller() {
  var x = 42
  printInt(&x) // OK

  let y = 42
  printInt(y) // error: type mismatch: `Int` is not an `UnsafePointer<Int>`
  printInt(&y) // error: can't apply `&` to an immutable value
}
```

**Improvement for option 1: Allow using `&` on immutable values.**

To eliminate the extra copies that the code would have to perform to make some
values mutable, we could extend the Swift language to allow applying `&` to
immutable values, producing an `UnsafePointer<T>`.

```swift
// Usage example.

void caller() {
  let x = 42
  printInt(&x) // OK
}
```

**Option 2: Import `const T&` as `T`.**

A more ergonomic approach would be to import C++ const references to value types
as values, but still use a by-reference calling convention behind the scenes.

```c++
void printInt(const int &value);
```

```swift
// C++ header imported in Swift.

func printInt(_ value: Int)
```

```swift
// Usage example.

func caller() {
  let x = 42
  printInt(y) // OK
}
```

The imported `printInt` function that takes an `Int` by value would be a thunk
that calls the actual C++ entry point that takes an `Int` by a const reference.
A mandatory optimization pass would inline that thunk into its callers, and
eliminate the copies that now became unnecessary.

It is important to understand that this approach only works in cases where the
compiler can insert a thunk. Here's an example where the compiler can't
transparently wrap a function pointer into a thunk, and therefore can't import
`const int&` as `Int32`:

```c++
struct Example {
  void (*printInt)(const int &);
};
```

This approach is much more ergonomic. However, it has a few disadvantages.

One disadvantage is that this approach provides less control: the caller can't
specify or predict the exact address that is passed to the C++ function (because
Swift can make copies of values or move them around in memory). Most functions
receiving `const T&` parameters should not care about the exact address, but
some might.

Another disadvantage of this approach is that it is safe in many cases in
practice, but users can construct unsafe cases. Specifically, if the C++ code
being called persists the reference that was passed by Swift beyond the duration
of the function call, that reference can become invalid (because Swift code
could pass an address of a temporary, implicitly materialized by the compiler).
The nature of unsafety is identical between option 1, option 2, and existing
Swift/C interop, however, in option 2, where we import C++ references as Swift
values, it is not visible to the Swift programmer that the function being called
accepts an address.

### Mapping overload sets

C++ has complex overload resolution rules, in part to support certain API design
patterns. Some API design patterns appeared as a consequence of overload
resolution rules. Therefore, in C++ an "API atom" is an an overload set, not an
individual function ([CppCon 2018: Titus Winters "Modern C++ Design (part 1 of
2)"](https://www.youtube.com/watch?v=xTdeZ4MxbKo)). The same is also the case in
Swift, so, fundamentally, there is no impedance mismatch here.

However, C and Objective-C interoperability imports each function and method
separately. For C++ interoperability, we should recognize design patterns that
use overload sets, and map them appropriately to Swift.

One such C++ pattern is providing two overloads: one that takes a `const T&` and
another that takes a `T&&`. If we attempt to naively map them to Swift, they
would map to the same signature. If we import just one of them and ignore the
other, we would be leaving performance on the table.

The easiest way to map such overload sets is to import the `T&&` overload as a
function that takes the argument by value, and ignore the `const T&` overload.
This approach does create a small amount of performance overhead (an extra
move), but does not require changing the Swift language or type checker to
recognize the concept of temporaries. The SIL optimizer seems like the
appropriate place to opportunistically reclaim that performance, by removing
unnecessary moves of temporaries where possible, and replacing calls to the
thunk with calls to the most appropriate C++ entry point.

```c++
// C++ header.

struct Tensor { ... };

void processTensor(const Tensor&);
void processTensor(Tensor&&);
```

```swift
// C++ header imported in Swift.

struct Tensor { ... }

func processTensor(_: Tensor) {
  // call `void processTensor(Tensor&&)`
}
```

```swift
// Usage example.

func useTensor() {
  var x = Tensor()
  processTensor(x)
  processTensor(x)
}
```

```swift
// Equivalent of SIL code after optimizations.

// void processTensor(const Tensor&);
func processTensorByConstRef(_: UnsafePointer<Tensor>)

// void processTensor(Tensor&&);
func processTensorByRvalueRef(_: UnsafeMutablePointer<Tensor>)

func useTensor() {
  var x = Tensor()
  processTensorByConstRef(x)
  processTensorByRvalueRef(x) // Automatically move the value because it is obviously not used anymore.
}
```

Once move-only types are added to Swift, the same mapping technique becomes
applicable to C++ move-only value types as well, with the only difference that
argument of the imported function would be marked as being consumed.

### Inline functions

Inline functions (both free and member functions) are used in C++ a lot more
than inline functions in C. For inline functions in C++, Swift should use the
same strategy as it uses currently for C: use Clang's CodeGen libraries to
emit definitions of inline functions into one LLVM module together with Swift
code.

## Namespaces and modules

Namespaces and modules in C++ are orthogonal concepts. Namespaces in C++ can
span multiple modules; C++ namespaces can also be nested. In Swift, modules are
namespaces.

**Option 1: Map C++ namespaces to empty enums in Swift.**

There are precedents for using empty enums as namespaces in Swift (for example,
`CommandLine`, `Unicode`, `Unicode.UTF8` in the standard library).
However, empty enums are not a perfect substitute for C++ namespaces:

- Swift has no `using`-like construct that allows code to avoid qualifying names
  nested in an enum (in other words, names nested within an enum must be always
  qualified with the name of that enum when used).

- C++ namespaces can span multiple modules. We don't want every imported C++
  module to define its own empty enum, as that will lead to name collisions,
  which will require even more qualification from users.

```c++
// C++ header in module `CppButton`.

namespace widgets {
class Button {};
}
```

```c++
// C++ header in module `CppTextbox`.

namespace widgets {
class Textbox {};
}
```

```swift
// C++ module `CppButton` imported to Swift.

enum widgets {
  struct Button {}
}
```

```swift
// C++ module `CppTextbox` imported to Swift.

enum widgets {
  struct Textbox {}
}
```

```swift
// Usage example: everything works well when we import only `CppButton`.

import CppButton

func makeButton() {
  var b1 = Button() // error: no such type
  var b2 = widgets.Button() // OK
}
```

```swift
// Usage example: ambiguities when we import both `CppButton` and `CppTextbox`.

import CppButton
import CppTextbox

func makeButton() {
  var b1 = Button() // error: no such type
  var b2 = widgets.Button() // error: name `widgets` is ambiguous, did you mean `CppButton.widgets` or `CppTextbox.widgets`?
  var b3 = CppButton.widgets.Button()
}
```

**Improvement for option 1: Move all empty enums to one synthetic module.**

We could fix the ambiguity between same-named namespace enums defined by
multiple C++ modules by synthesizing an extra Swift module that will contain
only the enums that make up the namespace structure, and then making all other
C++ modules define extensions for those enums.

```swift
// Swift module `CppNamespaces` synthesized by the C++ importer.

enum widgets {}
```

```swift
// C++ module `CppButton` imported to Swift.

import CppNamespaces

extension widgets {
  struct Button {}
}
```

```swift
// C++ module `CppTextbox` imported to Swift.

import CppNamespaces

extension widgets {
  struct Textbox {}
}
```

```swift
// Usage example.

import CppButton
import CppTextbox
// Implicitly injected: import CppNamespaces

func makeButton() {
  var b1 = Button() // error: no such type
  var b2 = widgets.Button() // OK
}
```

An incidental readability advantage of using enum extensions is that the
pretty-printed module interface for C++ modules will use the keyword `extension`
for namespaces instead of `enum`, reducing the confusion potential.

**Improvement for option 1: Add a `using`-like construct to Swift.**

Some C++ libraries define namespaces with long names, or deeply nested
namespaces. C++ users of such libraries often prefer to avoid typing and seeing
such namespace qualifiers in their code. To help use these libraries in Swift,
we could add a construct similar to C++ `using`, that would expand the name
lookup into the given empty enum.

```swift
// Usage example.

import CppButton
import CppTextbox
// Implicitly injected: import CppNamespaces
import CppNamespaces.widgets

func makeButton() {
  var b1 = Button() // OK
}
```

We could limit this construct to only work with enums in the `CppNamespaces`
module, if such feature is not deemed to be appropriate for APIs defined in
Swift.

**Option 2: Introduce namespaces into Swift as a C++ interoperability feature.**

From the implementation point of view, option 1 feels like a pile of hacks and
tricks. We could add C++-style namespaces to Swift, and only allow the C++
importer to define them, clearly designating namespaces as a C++
interoperability feature. From the point of view of users, there will be very
few, if any, differences between option 1 and option 2.

**Option 3: Introduce namespaces into Swift.**

We could add C++-like namespaces to Swift as a generally available language
feature, and then use it to import C++ into Swift.

### The "std" namespace

An interesting question is how to import the `std` namespace in Swift.
Continuing to call it `std` might invoke incorrect associations, because APIs in
`std` are not a part of the Swift standard library. We could rename `std` to
something that suggests that it is the C++ standard library, like `cxx_std`.

## Structs and classes

### Mapping the type itself and its special member functions

For the purposes of this discussion, we will consider C++ classes only.  There
are no important technical differences between C++ structs and classes, both
have exactly the same capabilities. In C++, structs and classes differ in how
they are typically used, however, it is not enforced by the compiler.  Different
style guides have different rules about when to define a struct or a class, and
these rules are often not toolable in principle.  Therefore, struct/class
distinction in C++ can be used at best as a hint to guide the API importer.

Swift's structs and classes are two completely different concepts. Structs are
the building block for value types, and classes are the building block for
reference types. References to Swift class instances are similar to
`std::shared_ptr<T>` in C++ (but are more efficient, because they use an
intrusive refcount), and therefore are not suitable for mapping an arbitrary C++
class type.

As far as value/reference semantics go, C++ classes are similar to structs in
Swift: both inherit value/reference semantics from constituent parts (if you
compose value types in a C++ class or a Swift struct, you get a value type; if
you embed a reference type in a C++ class or in a Swift struct, the composite
type behaves like a reference type). They are also similar in their memory
allocation strategy: both are allocated inline (local variables are allocated on
the stack, member variables are allocated in the containing object without an
indirection).

C++ classes allow the API owner to separately control whether the value is
copyable, movable, copy-assignable, move-assignable, and destructible. Moreover,
behavior for those operations can be customized. User-defined structs in Swift
can't customize such operations. User-defined Swift classes can only customize
the `deinit`, which corresponds to the destructor in C++. Nevertheless, this
limitation only applies to user-defined Swift structs and classes. There are
more mechanisms in the Swift object model, compiler, and runtime, that are not
exposed as language features, but exist as hooks for future extension (e.g.,
some were added specifically for potential C++ interop), or exist to support
Swift language features like resilience.

Let's take a look at what types look like in the compiler and runtime, and what
sorts of customization hooks are available.

The compiler classifies types as loadable or address-only (either one or the
other). Address-only types are always manipulated through a pointer. Loadable
types can be loaded from memory into SIL and LLVM IR values, and then
reconstructed back in memory.

The compiler uses different strategies to access and manage values depending on
the classification of the type.  For example, trivial loadable types can be
freely copied, destroyed, and moved around in memory without running any
user-defined code. Structs imported from C are considered loadable in Swift. C
structs are only composed of C primitives, and therefore are considered trivial
-- can be initialized, assigned, and moved around with `memcpy`.

Resilient Swift types are on the complete opposite end of the spectrum.
Resilient types are types provided by a third-party library that does not want
to commit to a particular ABI for that type. Resilient types are opaque values
that must be manipulated through a value witness table -- a table of function
pointers that defines the following operations:

| Swift Value Witness Operation | C++ equivalent                                                           |
| ----------------------------- | ------------------------------------------------------------------------ |
| `initializeWithCopy`          | copy constructor                                                         |
| `assignWithCopy`              | copy assignment operator                                                 |
| `initializeWithTake`          | move constructor, followed by a call to destructor on the source         |
| `assignWithTake`              | move assignment operator, followed by a call to destructor on the source |
| `destroy`                     | destructor                                                               |
| `size`                        | `sizeof(T)` minus trailing padding                                       |
| `stride`                      | `sizeof(T)`                                                              |
| `flags`                       | among other information, contains alignment, i.e., `alignof(T)`          |

Value witness tables also contain composite operations that can be derived from
the operations above.

We can map an arbitrary copyable C++ class type to a Swift struct type whose
value witnesses call the corresponding special member function of the C++ class.

We can map certain C++ classes to a more optimizable representation in Swift.
For example, C++ classes that contain only primitives and have trivial special
member functions (i.e., POD types) can be mapped to trivial loadable Swift
structs, just like C structs are today.

Can we map more complex C++ classes to loadable Swift structs? Someone with a
more thorough knowledge of runtime and SIL should answer, but here's what the
author of the document could find.

From `swift/docs/SIL.rst`:


> Loadable types are types with a fully exposed concrete representation:
>
> * Reference types
> * Builtin value types
> * Fragile struct types in which all element types are loadable
> * Tuple types in which all element types are loadable
> * Class protocol types
> * Archetypes constrained by a class protocol

"Fully exposed concrete representation" looks like a definition of a loadable
type, however, other comments say slightly different things, and it is not clear
what "fully exposed" actually means.

From `swift/include/swift/SIL/TypeLowering.h`:

```c++
/// Is a lowered SIL type address-only?  That is, is the current context
/// required to keep the value in memory for some reason?
///
/// A type might be address-only because:
///
///   - it is not fixed-size (e.g. because it is a resilient type) and
///     therefore cannot be loaded into a statically-boundable set of
///     registers; or
///
///   - it is semantically bound to memory, either because its storage
///     address is used by the language runtime to implement its semantics
///     (as with a weak reference) or because its representation is somehow
///     address-dependent (as with something like a relative pointer).
///
/// An address-only type can be fixed-layout and/or trivial.
/// A non-fixed-layout type is always address-only.
enum IsAddressOnly_t : bool {
  IsNotAddressOnly = false,
  IsAddressOnly = true
};
```

C++ classes are fixed-size, so we don't care about the first bullet point. The
second bullet point is more interesting -- a type must be address-only if an
instance of that type cares about which address it is stored at.

From [Slava Pestov's blog post "How to talk to your kids about SIL type
use"](https://medium.com/@slavapestov/how-to-talk-to-your-kids-about-sil-type-use-6b45f7595f43):

> If you define a C++ class describing a smart pointer to a reference-counted
> object, the presence of a custom copy constructor and destructor force the
> value to be materialized in memory all of the time, because the compiler
> doesn't know what the hell you're doing inside the custom constructor; maybe
> you're taking the address of ‘this' and storing it somewhere.
>
> If C++ had loadable types, they would involve some kind of special annotation
> that told the compiler that the move constructor can just trivially do a
> memcpy() of the value, even if there is a custom copy constructor or
> destructor. At this point, your smart pointer could be loaded into a register
> and passed around without issues.

This example says that a C++ smart pointer, with a custom copy constructor, copy
assignment operator, and destructor, can be loadable, as long as all move
special member functions are trivial. This explanation aligns well with the
previous one.

A C++ class is loadable in Swift as long as moving it is trivial. If we ignore
C++ classes with inconsistent copy and move semantics, a trivial move implies
that copy constructor and copy assignment don't care about the specific address,
which matches Swift's requirements.

### Special member functions with incorrect semantics

C++ classes can define special member functions with incorrect or inconsistent
semantics. It can be done intentionally; for example, the copy constructor of
`auto_ptr` actually moves the value. It can also be done unintentionally: it is
common to define only the special member functions that the C++ code happens to
use right now -- for example, only define the copy constructor but not the copy
assignment.

Therefore, we need to decide whether the Swift/C++ interoperability layer should
trust special member functions of C++ classes to have expected semantics, or
whether some verification is necessary.

Non-user-provided special member functions have correct semantics by
construction if the C++ class is composed of well-behaved types. Given the
current state of the art in static analysis, it does not seem like the
interoperability layer even remotely has a chance of proving that user-provided
special member functions have correct semantics. There are two practical
options: either trust the user in this regard and allow them to adjust the
inference done by the interop layer with annotations, or don't make any
assumptions about the semantics and demand that the user annotates types as
value types, move-only, or non-movable.

### Special member functions that throw exceptions

If C++ classes are imported in Swift as structs, there seems to be no reasonable
way to map exceptions thrown from special member functions to an error that can
be handled in Swift.

While it is possible to [propagate C++ exceptions](#exceptions) thrown by normal
member functions to Swift code, special member functions are different as they
used used to implement value witnesses, which are called by the compiler
implicitly. Therefore, either such exceptions have to be mapped to fatal errors
(as we do for other unhandled C++ exceptions), or calls to such special member
functions must be prevented statically.

Preventing such calls statically seems difficult. Also, in practice, special
member functions throw mostly due to out-of-memory conditions, which is
considered unrecoverable in Swift. Therefore, the practical solution is to
map exceptions from special member functions to fatal errors.

If the user must use a C++ class with throwing special member functions from
Swift, a reasonable workaround would be to write a wrapper that exposes these
operations as regular APIs. Wrappers can even be synthesized by the importer, if
such classes are found to be common.

```c++
// Can't be imported in Swift.
class MyThrowingType {
public:
  MyThrowingType() { if(...) throw ...; }
  ~MyThrowingType() { if(...) throw ...; }
  void method();
};

// Can be imported in Swift.
class MyThrowingTypeWrapper {
private:
  std::unique_ptr<MyThrowingType> value_;
public:
  MyThrowingTypeWrapper(): value_(nullptr) {}
  void init() /* can throw */ { value_ = std::make_unique<MyThrowingType>(); }
  void deinit() /* can throw */ { value_ = nullptr; }
  void method() { value_.method(); }
};
```

### Precise destruction semantics

C++ language specifies the exact point in program execution at which destructors
should run, while Swift does not. Some C++ APIs rely on these guarantees to work
properly (for example, RAII types like mutex locks).

```c++
// A pure C++ program.

class PickyCxxClass {
public:
  ~PickyCxxClass() { ... }
};

void test1() {
  PickyClass c;
  printf("Hello");
  // `c`'s destructor is guaranteed to be called exactly here.
}
```

```swift
// A pure Swift program, similar to the C++ program above.

struct SwiftStruct { ... }

func test1() {
  var s = SwiftStruct()
  // `s` can be deallocated here.
  print("Hello")
  // `s` can also be deallocated here.
}
```

But how commonly do C++ APIs rely on precise destruction? A gut feeling is that
it happens pretty often, but it is not always intentional and acknowledged by
the API vendor. *All* C++ types get a precise destruction point, and therefore,
it is very easy to start inadvertently relying on it in API design.

There are multiple ways to deal with this impedance mismatch.

**Ignore the differences, and apply Swift destruction semantics to C++
classes.** This approach will work for most C++ classes. However, C++ classes
that rely on C++ destruction semantics won't work well in Swift.

**Force the user to always pick a destruction point for values of C++ types.**
Too much burden on the user, and the code won't look like normal Swift.

**Allow the user to pick a destruction point, otherwise let the compiler pick.**
This approach will work, but it trusts the user to do the right thing every
time a certain C++ class is used. Often, whether precise destruction point is
required or not depends on the type.

**Define a destruction point for C++ classes.** This can't be done universally
in all Swift code, but it is feasible for local variables of concrete types.

An example where it is not possible to maintain precise destruction semantics
for C++ classes is in a generic Swift function that is called with a C++ class
as a type parameter. In this case, we must be able to compile one definition of
a Swift function, which must work regardless of the nature of the type (be it a
Swift type or a C++ class). This limitation does not seem too bad, because RAII
types are not often passed as type parameters to templates in C++, which creates
a reason to believe it will not be common in Swift either.

**Allow the API owner to annotate the C++ class as requiring a precise
destruction point.** An improvement upon the previous approach where unusual
semantics are only applied to C++ classes that need them, for example, RAII
types like mutex locks.

The pragmatic choice is to implement one of the last two options.

If a precise destruction point is defined for annotated C++ classes, here's an
example of behavior that we get:

```c++
// C++ header.

[[swift::requires_precise_destruction]]
class PickyCxxClass {
public:
  ~PickyClass() { ... }
};
```

```swift
// C++ header imported in Swift.

struct PickyCxxClass {
  // The destructor is not imported as a declaration into Swift, however,
  // it is mapped to a value witness function, and it is called when the
  // lifetime of the object ends, like in C++.
}
```

```swift
func testConcreteType() {
  var c = PickyCxxClass()
  print("Hello")
  // `c` will be deallocated here.
}

func testTypeParameter<T>(_ t: T.self) {
  var c = T()
  // `c` can be deallocated here, even if `c` is a `PickyCxxClass`.
  print("Hello")
  // `c` can also be deallocated here.
}

testTypeParameter(PickyCxxClass.self)
```

### Member functions that return inner pointers

When a member function in a C++ class returns a pointer (or a reference), most
commonly the lifetime of that pointer is limited to the lifetime of the object
itself. C++ code often relies on precise destruction semantics to ensure that
the object that owns the memory lives long enough. Another problem is that the
Swift compiler can move the object around in memory whenever it wants,
invalidating those outstanding inner pointers.

```c++
// C++ header.
class Employee {
private:
  std::string company_;
public:
  std::string *mutable_company() { return &company_; }
};
```

```swift
// C++ header imported in Swift.

struct Employee {
  func mutable_company() -> UnsafeMutablePointer<std.string>
}
```

```swift
func test() {
  var employee: Employee = ...
  var company = employee.mutable_company()

  // HAZARD: `employee` could have been moved to a different location in memory
  // by now, invalidating the `company` pointer.
  company.pointee = "A"

  print(employee)

  // HAZARD: `employee` can be deallocated here, however, `company` is still
  // accessible.
  company.pointee = "B"
}
```

To fix the problem of values being moved around in memory, we need to tell the
Swift compiler about the connection between pointers and objects that own the
memory.

```c++
// C++ header.

class Employee {
private:
  std::string company_;
public:
  [[swift::returns_inner_pointer]]
  std::string *mutable_company() const { return &_company; }
};
```

The `returns_inner_pointer` attribute can be added manually to the C++ headers,
or it can be safely inferred on all member functions that return a pointer or
reference, to reduce annotation burden.  Inferring this annotation on functions
that don't actually need it is harmless (does not change semantics, and does not
create unsafety), but may prevent some optimizations.

To fix the lifetime problem, the lifetime of a local variable can be extended
until the end of the scope if the current scope called a method that returns an
inner pointer.

```swift
func test() {
  var employee: Employee = ...
  var company = employee.mutable_company()

  // ... any amount of code...

  // `employee` is destroyed at the end of the scope because of the `mutable_company` call.
}
```

This technique will not work for temporaries (instead, they need to be extended
to the end of the full expression). It is also not very useful to call methods
that return inner pointers on temporaries.

### Differences in move semantics between C++ and Swift

Swift's "move" operation will leave the source value uninitialized (see
[ownership manifesto](OwnershipManifesto.md)); this operation is called a
"destructive move". C++ has "non-destructive moves" that leave the source value
initialized, but in an indeterminate state.

The following sections address various aspects of this impedance mismatch
between the two languages.

### Move-only C++ classes

For the purposes of this document, we will call C++ classes that can be moved
but don't have a public copy constructor and a public copy assignment operator
"move-only C++ classes".

Swift does not have move-only types at the time this document was written
(January 2020). There is a desire to add them, and a lot of design work has been
done (see the [Ownership Manifesto](OwnershipManifesto.md)), however, this
design has not been proposed yet.

Therefore, we will first discuss mapping move-only C++ classes to Swift before
move-only types are implemented. In this situation there's clearly no good
direct mapping. There are some non-ergonomic options though.

Second, we will discuss mapping move-only C++ classes to move-only types in
future Swift versions.

### Move-only C++ classes: mapping in Swift 5

**Import move-only C++ classes as Swift structs, and statically ensure that
copies are never needed.**

This seems doable, although the usability and predictability of the language
feature will depend on the compiler stage where the checks are done. It is easy
to perform such checks at the SIL level, however, the language might not behave
predictably. It is a more difficult to do such checks on the AST, but the
language will be more predictable from the user's point of view. Also, AST-based
checks might reject more programs than people expect.

Since value witness tables require a valid copy witness, it will be also
necessary to prohibit passing such pseudo-move-only types into generic code as
type parameters, or force full specialization of generic functions, and perform
the checks on fully-specialized SIL.

Here's a sketch of rules for move-only types that are reasonably simple to check
at compile-time and provide good diagnostics, at the expense of the resulting
code being non-ergonomic. Move-only C++ classes can be imported in Swift as
structs as usual, however, such structs can't be used as values. The compiler
would only allow `UnsafePointers` to them, and would allow calling methods on
`UnsafePointer.pointee`. When move-only types are used as C++ class members,
Swift can import them as opaque blobs, and expose a `withUnsafePointer`-style
API to get an `UnsafePointer` to the data member.

```c++
// C++ header.

// `File` is a move-only C++ class.
class File {
private:
  int file_descriptor_;
public:
  File(std::string_view filename);
  File(const File &) = delete;
  File(File &&) = default;
  ~File();

  File& operator=(const File &) = delete;
  File& operator=(File &&) = default;

  std::string ReadAll();
};

// `TwoFiles` is move-only because it is composed of move-only parts.
struct TwoFiles {
  File firstFile;
  File secondFile;
};
```

```swift
// C++ header imported in Swift.

struct File {
  public init(_ filename: std.string_view)
  public func ReadAll() -> std.string
}

struct TwoFiles {
  private var _firstFile: <unspecified-opaque-storage>
  private var _secondFile: <unspecified-opaque-storage>

  func withUnsafePointerToFirstFile<Result>(
    _ body: (UnsafePointer<File>)->Result
  ) -> Result {
    body(&_firstFile)
    _fixLifetime(self)
  }

  func withUnsafePointerToSecondFile<Result>(
    _ body: (UnsafePointer<File>)->Result
  ) -> Result {
    body(&_secondFile)
    _fixLifetime(self)
  }
}
```

```swift
// Usage example.

func useOneFile(_ f: UnsafeMutablePointer<File>) {
  // var f2 = f.pointee // compile-time error: can only call a method on 'pointee'.
  print(f.pointee.ReadAll()) // OK

  // Move `f` to a different memory location.
  var f2 = UnsafeMutablePointer<File>.allocate(capacity: 1)
  f2.moveInitialize(from: f, count: 1)
  // `f` is left uninitialized now.

  print(f2.pointee.ReadAll()) // OK
  f2.deallocate() // OK
  // The file is closed now.
}

func useTwoFiles(_ files: UnsafeMutablePointer<TwoFiles>) {
  // Like `print(files.first.ReadAll())`, if it was possible to compile it:
  files.pointee.withUnsafePointerToFirst { print($0.ReadAll()) }
}
```

If we add support for [marking APIs as returning inner
pointers](#member-functions-that-return-inner-pointers), we could make the
imported API nicer:

```swift
// C++ header imported in Swift.

struct TwoFiles {
  private var _firstFile: <unspecified-opaque-storage>
  private var _secondFile: <unspecified-opaque-storage>

  @_returnsInnerPointer
  var firstFile: UnsafePointer<File> { get }

  @_returnsInnerPointer
  var secondFile: UnsafePointer<File> { get }
}
```

### Move-only C++ classes: mapping to move-only Swift types (in future Swift versions)

This section is based on the design for move-only Swift types that has not been
officially proposed yet. See [ownership manifesto](OwnershipManifesto.md) for
the design for ownership and move only types that we assume in this section.

Move-only C++ classes correspond to `moveonly` structs in Swift. Semantic
analysis ensures that they are never copied.

Moves that destroy the source are spelled `move(x)` in Swift. Swift does not
have a concept of non-destructive move; a section below discusses possible
design options.

```c++
// C++ header.

class File {
private:
  int file_descriptor_;
public:
  File(std::string_view filename);
  File(const File &) = delete;
  File(File &&) = default;
  ~File();

  File& operator=(const File &) = delete;
  File& operator=(File &&) = default;

  std::string ReadAll();
};
```

```swift
// C++ header imported in Swift.

moveonly struct File {
  public init(_ filename: std.string_view)
  public deinit

  public func ReadAll() -> std.string
}

moveonly struct TwoFiles {
  var first: File
  var second: File
}
```

```swift
// Usage example.

func useOneFile(_ f: File) {
  print(f.ReadAll()) // OK

  // Move `f` to a different memory location.
  var f2 = move(f)

  // print(f.ReadAll()) // compile-time error: can't access `f`, its value was moved

  print(f2.ReadAll()) // OK
  endScope(f2) // OK
  // The file is closed now.
}

func useTwoFiles(_ files: TwoFiles) {
  print(files.first.ReadAll()) // OK
}
```

### Non-destructive moves

Generally, Swift code that uses values of C++ class types should use Swift's
destructive moves in most cases where C++ code would have used a non-destructive
move. However, certain C++ APIs are designed to be used with non-destructive
moves, therefore, non-destructive moves should be made available in Swift.
Adding non-destructive moves to Swift as a native language feature is a
non-starter.

Consider the following C++ code:

```c++
// Example of C++ API design that requires users to perform non-destructive
// moves.

class Example { /* move-only */ };

std::optional<Example> getExample();
void processExample(Example e);

void test() {
  std::optional<Example> e = getExample();
  processExample(std::move(e.value()));
}
```

Equivalent Swift code would look like this:

```swift
// Equivalent Swift code.

func test() {
  var e: cxx_std.optional<Example> = getExample();

  processExample(move(e.value()));
  // If we assume that the previous line compiled, we have a problem:
  // `cxx_std.optional` does not know that the value was destructively moved
  // and will try to delete it again.
}
```

Of course, one could argue that the interoperability layer could provide special
support for `std::optional`, and make it work with destructive moves better.
While that is true, the point still stands: there will be C++ APIs that expect
users to perform non-destructive moves, and should ensure that they are usable
from Swift without overlays or special compiler support.

**Option 1: Non-destructive moves in Swift are swaps with an arbitrary valid
value.**

It is easy to model a non-destructive move in Swift as a swap with a
default-initialized value.

```swift
// Swift standard library, C++ support module.

public protocol DefaultInitializable {
  init()
}

public moveonly func cxxMove<T: DefaultInitializable>(_ value: inout T) -> T {
  var result = T()
  swap(&value, &result)
  return result
}

public moveonly func cxxMove(_ value: inout T, replacingWith newValue: T) -> T {
  var result = newValue
  swap(&value, &result)
  return result
}
```

```swift
// Usage example.

// This function takes a `File` by value, consuming it.
func consumeFile(_ f: File) { ... }

func useArrayOfFiles() {
  var files: [File] = ...
  // consumeFile(files[0]) // compile-time error: can't copy a `File`

  // Swift's move does not help.
  // consumeFile(move(file[0]))
  // compile-time error: moving one element of an array will cause a
  // double-destruction of `File` when the array is destroyed.

  consumeFile(cxxMove(&file[0])) // OK, replaced `file[0]` with a `File()`.

  consumeFile(cxxMove(&file[1], replacingWith: File("/tmp/example.txt")))
  // OK, replaced `file[1]` with a newly-opened file.
}
```

The advantage of this approach is that we avoid creating "valid but
indeterminate" values, which can be hazardous. However, such values can be
passed from C++ to Swift at any time, even if Swift code can't create them
directly. It is also awkward to require the user to come up with a dummy valid
value when the type is not default-constructible.

**Option 2: Non-destructive moves in Swift invoke the C++ move constructor.**

So, we want to perform a real C++ move and leave a "valid but indeterminate"
value in the source. For that, we must enable the Swift to call the C++ move
constructor.

If `class File` has a move constructor in C++, the imported Swift struct defines
a corresponding initializer:

```c++
// C++ header imported in Swift.

public moveonly struct File {
  // File(File &&);
  public init(cxxMovingFrom: inout File)
}
```

```swift
// Usage example.

func useArrayOfFiles() {
  var files: [File] = ...
  consumeFile(File(cxxMovingFrom: &files[0]))
}
```

The move syntax, `File(cxxMovingFrom: &files[0])`, is quite verbose and requires
repeating the name of the type, whereas the corresponding C++ construct,
`std::move(x)`, does not. When type context is available, the expression can be
abbreviated to `.init(cxxMovingFrom: &files[0])`. We can make it more concise by
synthesizing a helper method in movable types:

```swift
// C++ header imported in Swift.

public moveonly struct File {
  // File(File &&);
  public init(cxxMovingFrom: inout File)

  public mutating func cxxMove() -> File {
    return File(cxxMovingFrom: &self)
  }
}
```

```swift
// Usage example.

func useArrayOfFiles() {
  var files: [File] = ...
  consumeFile(files[0].cxxMove())
}
```

Although methods are more in line with Swift API design than free functions,
injecting names into C++ types can backfire due to naming collisions.

Alternatively, we could model non-destructive moves with a free function,
imitating the C++ syntax. To do this we need a protocol for non-destructively
movable types, and a free function that calls the move constructor:

```swift
// Swift standard library, C++ support module.

public protocol NonDestructivelyMovable {
  public init(cxxMovingFrom: inout Self)
}

public moveonly func cxxMove<T: NonDestructivelyMovable>(_ value: inout T) -> T {
  return T(cxxMovingFrom: &value)
}
```

```swift
// C++ header imported in Swift.

public moveonly struct File: NonDestructivelyMovable {
  public init(cxxMovingFrom: inout File)
}
```

```swift
// Usage example.

func useArrayOfFiles() {
  var files: [File] = ...
  consumeFile(cxxMove(&files[0]))
}
```

It is also useful to expose the move assignment operation in Swift. Even though
move assignment is not necessary to implement `cxxMove()`, it can be used for
optimization.

```swift
// C++ header imported in Swift.

public moveonly struct File {
  // File(File &&);
  public init(cxxMovingFrom: inout File)

  // File& operator=(File &&);
  public func moveAssignFrom(_ value: inout File)
}
```

The compiler could perform a high-level optimization replacing `x = cxxMove(&y)`
(which creates a temporary, and calls the move constructor twice) with
`x.moveAssignFrom(&y)` (which does not create a temporary and calls move
assignment only once).

### Non-movable C++ classes

By non-movable C++ classes we mean C++ classes that don't have a copy
constructor or a move constructor.

Swift does not have any struct-like equivalent to non-movable C++ classes, and
there's nothing planned in that area. Therefore, we have to either creatively
reuse one of existing Swift's features, or add some new features to Swift.

**Option 1: Map non-movable C++ classes to Swift structs.**

If we want to map all C++ classes to structs in Swift, one approach to make
non-movable C++ classes work is only importing pointers to non-movable types;
this approach is described in detail in the section about [importing move-only
types in Swift 5](#move-only-c-classes-mapping-in-swift-5). Non-movable classes
in C++ are often used as polymorphic base classes. Allowing to only use pointers
to such types is not a bad limitation. The primary disadvantage of this approach
is ergonomics.

**Option 2: Map non-movable C++ classes to Swift classes.**

While Swift structs are a bad match for non-movable C++ classes, Swift classes
match semantics better. For example, instances of Swift classes, once allocated,
stay at the same address until `deinit`. Instances of Swift clasess are always
worked with indirectly, eliminating the need to move them around in memory.

Although user-defined Swift classes have a certain memory layout determined by
the Swift compiler (for example, the memory block should start with an object
header that contains a metadata pointer and a refcount), that exact memory
layout is not necessary for a type to successfully masquerade as a Swift class.
For example, Swift already imports CoreFoundation types as "foreign classes";
from the user's point of view they look like ordinary classes.

The biggest semantic impedance mismatch between C++ classes and Swift classes is
that Swift classes are reference-counted. It is certainly possible to import a
C++ class as a Swift class if it is intrusively reference counted, or wrapped in
a `shared_ptr`.

But what about non-movable C++ classes that are not reference counted? This
issue could be worked around by making retain and release operations on C++
classes be a no-op, and introducing an explicit "delete" operation, effectively
making C++ class references in Swift equivalent to `UnsafeMutablePointer`.

```c++
// C++ header.

class NonMovable {
public:
  NonMovable(const NonMovable &) = delete;
  NonMovable(NonMovable &&) = delete;
  ~NonMovable();

  NonMovable &operator=(const NonMovable &) = delete;
  NonMovable &operator=(NonMovable &&) = delete;

  void debugPrint() const;
};
```

```swift
// C++ header imported in Swift.

class NonMovable {
  // Runs `delete this`.
  func delete()

  func debugPrint()
}
```

```swift
func useNonMovable(nm: NonMovable) {
  var nm2 = nm
  // `nm2` now points to the same object as `nm`. No reference-counting.

  nm.debugPrint() // OK
  nm2.debugPrint() // OK

  nm2.delete() // OK
  // The object is deallocated now. From this point, using `nm` or `nm2`
  // is undefined behavior.
}
```

Everything seems to work really well, except that we broke Swift's safety
guarantees about classes. Swift manages lifetime of regular user-defined classes
automatically; in safe Swift code it is not possible to get a dangling class
reference; it is also weird that users would have to manually deallocate class
instances. Therefore, classes imported from C++ would behave very differently
from user-defined Swift classes; most importantly, they are unsafe. This issue
seems incompatible with Swift's design and philosophy. Otherwise, importing C++
classes as Swift classes looks like a viable implementation strategy.

The unsafety issue could be mitigated by adding the word "unsafe" somewhere in
the source code. For example, importing a non-movable C++ class `Example` as a
Swift class `UnsafeExample`, or requiring the user to write the keyword "unsafe"
before the type name:

```swift
func useNonMovable(nm: unsafe NonMovable) { ... }
```

### Member functions

Member functions of C++ classes are most naturally mapped to methods in Swift
structs. C++ allows to add various qualifiers to member functions, which we
discuss in the following sections.

### Const-qualified member functions in C++ classes

Member functions of C++ classes can be marked with a `const` qualifier; however,
this qualifier does not provide any semantic guarantees. Const-qualified methods
can change the state of the object through a variety of mechanisms.

`const_cast` is the first language feature that comes to mind when one thinks
about modifying a const object. As long as an object was originally allocated as
non-const, its const-qualified methods can cast const away and mutate the
object. Detecting potential `const_cast`s is quite difficult, since it requires
examining everything that a const member function can call, transitively.
However, in practice, `const_cast`s are rare, and given the more pervasive
issues described below, `const_cast`s can be ignored.

```c++
class SneakyMutation {
private:
  int value = 0;
public:
  void mutateSneakily() const { opaqueMutator(this); }
  void setValue(int newValue) { value = newValue; }
};

// in a different file:
void opaqueMutator(const SneakyMutation* sm) {
  const_cast<SneakyMutation*>(sm)->setValue(42);
}
```

Another C++ feature that allows const-qualified member functions to mutate the
object is "mutable" data members. Mutable data members are a lot more common
than `const_cast`s, but fortunately they are trivial to detect statically.

```c++
class SneakyMutation {
private:
  mutable int value = 0;
public:
  void mutateSneakily() const { value = 42; }
};
```

Yet another C++ feature that allows const-qualified methods to mutate the object
is aliasing. A const member function can obtain a pointer to the same object
through some other means, and change the pointed-to data.

```c++
class SneakyMutation {
private:
  int value = 0;
public:
  void mutateSneakily(SneakyMutation *other) const {
    other->value = this->value + 1;
    // What if `other` happens to be equal to `this`? In that case, a const
    // member function has mutated `this`!
  }
};

void test() {
  SneakyMutation sm;

  // A const method mutates the object that it is invoked on:
  sm.mutateSneakily(&sm);
}
```

Note that `mutateSneakily()` can obtain the alternative `this` pointer through a
variety of ways, not necessarily as a function argument. The method can find
another non-const pointer equal to `this` in a global variable or in a data
structure accessible from `this` itself. It also need not mutate `other` so
obviously: it can pass `other` to another function which will mutate it. It is
difficult to estimate how common such mutation is, however, it is not an element
of a common design pattern.

Swift's replacement for C++ const member functions are non-`mutating` functions:

```swift
struct Example {
  private var value: Int = 0
  mutating func mutatingFunction() { value = 42 }
  func nonMutatingFunction() {
    // value = 42 // would not compile
    print(value) // OK
  }
}
```

The biggest difference from C++ is that non-`mutating` functions in Swift are
really not allowed to mutate `self`; there are no backdoors. Some equivalents of
C++'s mutation backdoors are disallowed statically, some are disallowed
dynamically, some are undefined behavior.

The backdoors are disallowed by the exclusivity rule (from [SE-0176 Enforce
Exclusive Access to
Memory](https://github.com/apple/swift-evolution/blob/main/proposals/0176-enforce-exclusive-access-to-memory.md)):

> two accesses to the same variable are not allowed to overlap unless both
> accesses are reads

If we map C++ classes to Swift structs, how do we map C++'s `const` qualifier on
member functions? There are a couple of options.

* Ignore `const`, and mark all Swift struct functions as `mutating`. Allow API
  owners to manually annotate functions as non-`mutating`. This is a
  conservative and correct-by-default approach, but it is not ergonomic.

* Map `const` to non-`mutating` in Swift. This approach is very desirable from
  the point of view of ergonomics, however it is not safe in the general case.
  Nevertheless, in many cases such inference will be correct.

How can we make the second, ergonomic, approach safer? First of all, we should
allow C++ API owners to override the inferred `mutating`/non-`mutating` with an
annotation. API owners must have control over what their APIs look like in
Swift.

In addition, the compiler could do a lightweight static analysis to recognize
common problematic patterns, like `mutable` members and obvious `const_cast`s.
If the compiler finds anything alarming, it should refuse to perform inference
and require the user to manually annotate methods in C++ as `mutating` or
non-`mutating`.

### Volatile-qualified member functions

Volatile-qualified member functions are so rare that there's not enough value in
spending non-trivial engineering effort for them in the interop layer ensuring
that they map nicely. There are two easy ways to handle them:

* don't import volatile-qualified member functions,

* map member functions as if the `volatile` qualifier was not present.

### Ref-qualified member functions

TODO

### Final functions

TODO

### Getters and setters

Getters and setters in C++ classes most directly correspond to properties in
Swift. While it is certainly possible to map getters and setters to regular
methods, properties would be more ergonomic.

First of all, we need to find getter/setter pairs in a C++ class. We would need
to use name-based heuristics for that, while allowing the API owner to override
the inference with annotations (specifically, with the `swift_name` attribute).
There are a variety of naming styles for getters and setters in C++, but we only
need to cover the most common ones.

Getters take no arguments, return a `T` or a `const T`. Typical naming patterns
are: `AaaBbb()`, `GetAaaBbb()`, `aaaBbb()`, `getAaaBbb()`, `aaa_bbb()`,
`get_aaa_bbb()`

Setters take a `T`, a `const T&`, or a `T&&`, and return `void`. Typical naming
patterns are: `SetAaaBbb()`, `setAaaBbb()`, `set_aaa_bbb()`

Mutable accessors take no arguments and return a `T&` or a `T*`. Typical naming
patterns are: `MutableAaaBbb()`, `mutableAaaBbb()`, `mutable_aaa_bbb()`.

The C++ importer can synthesize a Swift property from a getter, from a
getter/setter pair, or from a getter and a mutable accessor. Swift does not have
set-only properties, so unpaired setters and mutable accessors will be imported
as regular methods.

```c++
// C++ header.

class Employee {
public:
  const std::string &getName() const;
  void setName(std::string newName);
};
```

```swift
// C++ header imported in Swift.

struct Employee {
  public var name: std.string { get set }
}
```

```swift
// Implementation details of the imported API.

struct Employee {
  // const std::string &getName();
  private func _getName() -> UnsafePointer<std.string>

  // void setName(std::string newName);
  private mutating func _setName(_ newName: std.string)

  // Swifty API.
  public var name: std.string {
    _read {
      yield _getName().pointee
    }
    set {
      _setName(newValue)
    }
  }
}
```

Sometimes the type returned by the getter will not match the type taken by the
setter. For example, the getter can return a `std::string_view`, while a setter
takes a `std::string`. `std::string_view` is like a `const std::string&`, so it
makes sense from the API perspective in C++. Swift, however, requires the getter
and setter to use the same type exactly.

We could teach the C++ importer about the most widely used type pairs, and
insert the appropriate type conversions in the synthesized property accessors.
However, these type conversions will carry a performance penalty, and the
resulting Swift API will be less performant than the original C++ API. For
example, consider a C++ class where a getter returns a `std::string_view`, and
the setter takes a `std::string`. If we synthesize a `std::string_view` property
in Swift, its setter would always copy the character data, even though in C++
the setter would move the `std::string`. If we synthesize a `std::string`
property in Swift, its getter would have to materialize a `std::string` from a
`std::string_view`.

Therefore, it seems like the best approach is to teach the C++ importer about
handling such mismatched types, but only perform property synthesis on demand,
triggered by an annotation in C++ code.

```c++
// C++ header.

// New attribute.
#define SWIFT_PROPERTY(type, name) __attribute__((swift_property(#type, #name)))

class Manager {
public:
  std::string_view getName() const SWIFT_PROPERTY(std::string, name);
  void setName(std::string newName) SWIFT_PROPERTY(std::string, name);

  std::span<const Employee> getReports() const;
  void setReports(std::vector<Employee> newReports);
};
```

```swift
// C++ header imported in Swift.

struct Manager {
  // Property is synthesized as requested by the annotation.
  public var name: std.string { get set }

  // Property is not synthesized because getter and setter operate on
  // different types.
  public func getReports() -> std.span<const<Employee>>
  public func setReports(_ newReports: std.vector<Employee>)
};
```

### Pointers to members

Pointers to members are quite rare in C++, so not importing them at all, at
least initially, would not be a big loss. Nevertheless, importing them is
possible.

Pointers to data members best correspond to keypaths in Swift. (TODO: need an
example.)

Pointers to member functions could be ergonomically mapped to curried functions,
just like struct and class methods in Swift can be converted to curried
functions.

```swift
// Inspiration from Swift: methods can be converted to curried functions.

// A normal user-defined struct.
struct Point {
  var x: Double
  var y: Double

  func distanceTo(_ line: Line) -> Double { ... }
}

var distanceToFunc: (Point) -> (Line) -> Double = Point.distanceTo
```

The only difference is that C++ member function pointers use a different memory
layout than Swift closures. Therefore, they would need to be imported with a
special calling convention, let's call it `@convention(cxx_method)`. Here's an
example:

```c++
// C++ header.

class Point {
public:
  double distanceTo(Line line) const;
};

void CallMemberFunctionPointer(Point p, double (Point::*ptr)(Line));
```

```swift
// C++ header imported in Swift.

public struct Point {
  public func distanceTo(_ line: Line) -> Double { ... }
}

func CallMemberFunctionPointer(
  _ p: Point,
  _ ptr: @convention(cxx_method) (Point) -> (Line) -> Double
)
```

### Virtual member functions

If we map C++ classes to Swift structs, it makes the most sense to map virtual
member functions to struct methods in Swift. However, Swift structs don't
support inheritance. So, while we can map virtual functions to methods and
execute C++ dynamic dispatch correctly, we can't express the fact that the
struct is subclassable, and that the method is overridable in Swift.

TODO: design how to map inheritance.

### Inherited APIs

Swift structs don't allow inheritance. If we map C++ classes as Swift structs,
we could replicate APIs from all base classes in every derived class.

```c++
// C++ header.

class Base {
public:
  void doBaseStuff();
};

class Derived : public Base {
public:
  void doDerivedStuff();
};
```

```swift
// C++ header imported in Swift.

public struct Base {
  public func doBaseStuff()
}

public struct Derived {
  public func doBaseStuff()
  public func doDerivedStuff()
}
```

### Conversions between derived and base classes

Swift structs don't allow inheritance, so it is not possible to directly express
the is-a relationship between derived classes and base classes. The is-a
relationship is not very important for non-polymorphic C++ classes, where
inheritance is typically used as an implementation technique, rather than an
intentional part of the API. In polymorphic classes the is-a relationship is
quite important and is an intentional part of the API.

So how to represent conversions between derived and base classes? There are two
cases to consider: converting values and converting pointers.

Converting values of derived type to values of base type is known as "object
slicing" in C++. It is well-known to be error-prone, but since some C++ APIs
might rely on it, we should try to expose it in Swift.

Object slicing is possible without any language extensions:

```swift
var derived: Derived = ...
var base: Base = UnsafeRawPointer(&derived).load(as: Base.self)
```

It is not very ergonomic, but not too bad for an operation that is known to be
error-prone. APIs that intentionally rely on object slicing could add helper
methods to types that intentionally participate in slicing:

```swift
// Manually written overlay for a C++ API.

extension Base {
  public init(_ other: Derived) {
    self = UnsafeRawPointer(&other).load(as: Base.self)
  }
  public init(_ other: UnsafePointer<Derived>) {
    self =  UnsafeRawPointer(other).load(as: Base.self)
  }
}
```

Now let's talk about conversions between pointers to derived type and pointers
to base type. These operations need to be ergonomic only for polymorphic
classes.

First of all, let's reject extending Swift's type casting operators `as` and
`as?` to handle casts between pointers to C++ objects. We need to convert
between `UnsafePointer<Base>` and `UnsafePointer<Derived>`, which are not
connected with a subtyping relationship in Swift. Implementing a conversion in
type casting operators (`as` and `as?`) that does not reflect a subtyping
relationship is not a good idea. Swift already has a couple of such conversions,
and they cause a lot of complexity in the compiler and the runtime. Moreover,
sometimes such casting behavior can be unexpected by users. Therefore, we are
going to explore API-based approaches to express upcasts and downcasts for C++
objects.

It is important to realize that interleaved accesses to an `UnsafePointer<Base>`
that aliases an `UnsafePointer<Derived>` violate Swift's type-based aliasing
rules. These rules could be relaxed for types imported from C++.

To prevent the user from accidentally violating type-based aliasing rules, Swift
intentionally does not provide an easy way to freely convert between pointers of
unrelated types. Swift allows to temporarily create an aliasing pointer;
however, that pointer has a scoped lifetime, and during that scope accessing the
original pointer is not allowed.

```swift
// Pointer conversion example in existing Swift language.

var basePtr: UnsafePointer<Base> = ...
basePtr.withMemoryRebound(to: Derived.self) {
  // In this closure, `$0` has type `UnsafePointer<Derived>` and
  // aliases `basePtr`.
  $0.doBaseStuff()
  $0.doDerivedStuff()
}
```

Type conversions are usually expressed as initializers in Swift. However, adding
an initializer to `UnsafePointer` for base/derived C++ class pair is going to
create a big overload set, which will negatively impact compilation performance.
Therefore, we should try to distribute the conversion APIs among the imported
types themselves. The importer could synthesize conversion APIs on base and
derived classes:

```swift
// C++ header imported in Swift.

public struct Derived {
  @returnsInnerPointer
  public var asBase: UnsafePointer<Base> { get }

  public static func downcast(from basePointer: UnsafePointer<Base>) -> UnsafePointer<Derived>?
}

public struct Base {
  public static func upcast(from basePointer: UnsafePointer<Derived>) -> UnsafePointer<Base>
}
```

```swift
// Usage example.

func useBasePtr(_ basePtr: UnsafePointer<Base>) { ... }
func useDerivedPtr(_ derivedPtr: UnsafePointer<Derived>) { ... }

func testDowncast() {
  var d = Derived()
  useBasePtr(d.asBase)

  // or:
  useBasePtr(Base.upcast(from: &d))
}

func testUpcast(_ basePtr: UnsafePointer<Base>) {
  if let derivedPtr: UnsafePointer<Derived> = Derived.downcast(from: basePtr) {
    useDerivedPtr(derivedPtr)
  }
}
```

The `asBase` property operates on a value, so it will need a way to pin the
original value in memory while the aliasing pointer is live. If we ignore that
API, the "type-upcast-from-value" and "type-downcast-from-value" syntax in other
APIs doesn't read well, because the order looks reversed.

Let's see what an API based on free functions would look like. We have to
separate the upcast and downcast APIs because they must return different types:
upcasts can't fail, while downcasts can.

```swift
// C++ support module in the Swift standard library.

public func cxxUpcast<Source, Destination>(
  _ source: UnsafePointer<Source>,
  to type: Destination.Type
) -> UnsafePointer<Destination>

public func cxxDowncast<Source, Destination>(
  _ source: UnsafePointer<Source>,
  to type: Destination.Type
) -> UnsafePointer<Destination>

public func cxxDynamicDowncast<Source, Destination>(
  _ source: UnsafePointer<Source>,
  to type: Destination.Type
) -> UnsafePointer<Destination>?
```

The Swift type checker would have special knowledge about these functions, and
only allow calling them when `Source` and `Destination` are fully concrete types
that belong to the same class hierarchy in C++.

These functions will know the concrete source and destination types, so they
will be able to perform any necessary pointer adjustments, therefore multiple
inheritance and virtual base classes wouldn't be a problem.

### Subclassing C++ classes in Swift

TODO

### Making C++ classes conform to Swift protocols

TODO

## Enums

In Swift 5, C enums that are not annotated (with either of `enum_extensibility`,
`NS_ENUM`, or `NS_OPTIONS`) are imported into Swift as structs, and enumerators
are imported as computed global variables. This might have been the right call
for importing Objective-C code, where enums not declared with `NS_ENUM` are
highly likely to have a "non-enum nature": they are either a bitfield, or just
a bag of constants. C++ has more ways, and more flexible ways to declare
constants, so using enums in C++ to declare constants is not very idiomatic.
Bitfield enums are used in C++ though, however, compared to overall enum usage,
bitfield enums are still rare. Therefore, current strategy of importing
non-annotated enums as Swift structs is the wrong default for C++.

There are multiple strategies we could take to import C++ enums into Swift.

**(1) Adopt the strategy used for C enums in C++**: unannotated C++ enums are
imported as Swift structs, C++ enums annotated as open/closed are imported as
Swift enums.

Pros:

* Conservatively correct. This strategy does not trust enums to have the "enum
  nature" unless they are annotated otherwise.

* Simpler design: identical rules across C, Objective-C, and C++.

Cons:

* Non-ergonomic. In idiomatic C++ codebases most enums have enum nature, so
  users would need to add lots of annotations.

**(2) Assume non-annotated C++ enums have "enum nature" and import them
as non-frozen Swift enums**; (optionally) implement an annotation for C++ enums
with "non-enum nature" and import such enums as Swift structs.

Pros:

* Correct default. In an idiomatic C++ codebase, the vast majority of enums do
  have enum nature.

* Maintaining source compatibility by not changing how C enums are imported.

Cons:

* Non-annotated enums of non-enum nature would be imported incorrectly from the
  API point of view (however, there is no undefined behavior hazard).

* No clear strategy to tell apart C and C++ enums. In an ideal world, `extern
  "C"` should allow to detect C declarations in C++, but not all C code is
  wrapped in `extern "C"`. For example, most Objective-C headers are not wrapped
  in `extern "C"` because most Objective-C constructs have a compatible ABI
  between Objective-C and Objective-C++.

**(3) Apply strategy #2 in C, Objective-C, and C++.** Doing so will change the
mapping strategy for non-annotated enums coming from Objective-C code, breaking
source stability to some extent.

Pros:

* Correct default in C++.

* Likely correct default in C.

* Simpler design: same rules in C and C++.

* Obvious how to implement, because there is no need to distinguish between
  different header kinds.

Cons:

* Likely not correct default in Objective-C. In idiomatic Objective-C code enums
  with "enum nature" are declared with `NS_ENUM`, and bitfields are declared
  with `NS_OPTIONS`, which leaves plain enums to cover the unusual cases.

* Breaking source compatibility by changing how C enums are imported. There are
  ways to mitigate this issue, for example, continue importing enumerators as
  computed global variables, marking them deprecated.

Strategy #3 is best for C++ code, but it is unclear if consequences for
Objective-C would be acceptable. We should gather data about usage of plain
enums in idiomatic C++ code and in Apple's SDKs and evaluate the absolute amount
of source breakage.

## Templates

From 10,000 feet, C++ templates are similar to Swift generics. However, there
are multiple semantic gaps between them.

C++ templates perform a syntactic substitution. Any type that supports the
syntax invoked in the template is a valid template argument. However, we don't
know exactly what syntax a type is required to support until we try to
substitute that type into a template. Generics in Swift are constraint-based and
require modular type checking.

C++ templates require instantiation at compile time. It is not possible to
compile a template without substituting concrete types in. It is not specified
whether Swift generics are instantiated or not, the compiler can make either
choice and the user can't tell the difference.

C++ templates support specialization. Swift generics don't allow specialization;
they provide a different mechanism (protocol requirements) to make one generic
function behave differently for different types.

C++ class templates support specialization, which allows defining completely
different APIs across specializations of the same class. All instantiations of a
generic type in Swift have the API described in the generic declaration (with
type parameters substituted), plus applicable conditional extensions.

C++ templates support non-type template parameters, template template
parameters, and parameter packs (variadic generics), all of which are not
supported in Swift.

### Function templates

Since C++ uses an instantiation-based model for templates, the most obvious way
to import C++ function templates in Swift is to only import full specializations
as regular functions. However, it would be most ergonomic to import function
templates as Swift generic functions. Let's explore both options and see how far
we can go.

### Function templates: import as Swift generic functions

Let's take explicit specializations out of the picture for the purposes of
presenting the API in Swift. Since overload resolution in C++ ignores
specializations of function templates, we can ignore them, too, when importing a
function template into Swift.

```c++
// C++ header.

template<typename T>
void functionTemplate(T t) { ... }

// Any number of explicit specializations may follow.
template<>
void functionTemplate(int x) { ... }
```

```swift
// C++ header imported in Swift.

func functionTemplate<T>(_ t: T)

// No need to import explicit specializations as separate APIs.
```

Of course, when Swift code calls `functionTemplate` with an `Int32`, it should
call the correct explicit specialization, `functionTemplate<int>`, even though
it is not shown in the imported Swift API.

### Function templates: allow to specify template arguments

Calls to Swift generic functions always deduce generic arguments from the call.
C++ allows the caller to either deduce the arguments, or specify them
explicitly. Sometimes it is important to invoke C++ function templates with
specific template arguments, so it would make sense to expose this capability in
Swift.

We suggest to allow Swift code to use the angle bracket syntax to explicitly
specify function template arguments at the callsite. If template arguments are
not specified, we should run template argument deduction. (TODO: explain in more
detail how template argument deduction will work starting from Swift types.)

```swift
// Usage example in Swift.

functionTemplate<Int>(42)
```

How to specify C++ types that map ambiguously into Swift, for example, `int &`
or `int *`, both of which map to `UnsafePointer<Int>`? The C++ support module in
the Swift standard library could provide Swift typealiases that would map
unambiguously to C++.

```swift
// C++ support module in the Swift standard library.

typealias CxxPointer<T> = UnsafeMutablePointer<T>      // T*
typealias CxxConstPointer<T> = UnsafePointer<T>        // const T*

typealias CxxRef<T> = UnsafeMutablePointer<T>          // T&
typealias CxxConstRef<T> = UnsafePointer<T>            // const T&

typealias CxxRvalueRef<T> = UnsafeMutablePointer<T>    // T&&
typealias CxxConstRvalueRef<T> = UnsafePointer<T>      // const T&&
```

```swift
// Usage example in Swift.

var x = 42

// Calls `functionTemplate<int>`.
functionTemplate<Int>(x)

// Calls `functionTemplate<const int *>`.
functionTemplate<CxxConstPointer<Int>>(&x)

// Calls `functionTemplate<int &>`.
functionTemplate<CxxRef<Int>>(&x)
```

Although it is desirable to map rvalue references to Swift's `inout`, it is not
possible to do so when importing a C++ function template as a C++ generic
function; "inout"-ness of an argument can't change across instantiations of a
generic function in Swift.

### Function templates: calls to specific specializations

From an implementation point of view, it is easy to compile Swift code that
calls C++ function templates if template arguments are concrete types that are
obvious at the callsite (either deduced or specified explicitly). In other
words, it is easy to compile the call if Swift compiler can easily deduce which
specialization of the C++ function template to call. The imported API could
still look like a Swift generic function:

```swift
// C++ header imported in Swift.

func functionTemplate<T>(_ t: T)

// No need to import explicit specializations as separate APIs.
```

```swift
// Usage example in Swift, works.

func callFunctionTemplate() {
  functionTemplate(0) // OK: calls the `functionTemplate<int>` specialization.
}
```

If we stop here, `functionTemplate` would look like a generic function in Swift,
but it would not be callable from generic code. This option might be good enough
for the most basic mapping of function templates in Swift. But can we allow
calling C++ function templates from Swift generics?

### Function templates: calls with generic type parameters

The primary implementation difficulty in allowing generic Swift code to call C++
function templates is that the C++ compiler can only compile full
specializations, but Swift generics can run unspecialized.

```swift
// Usage example in Swift.

func myGenericFunction<T>(_ t: T) {
  functionTemplate(0) // OK: calls the `functionTemplate<int>` specialization.

  functionTemplate(t) // compilation error: can't call a C++ function template, because we don't know what `T` is, and therefore, can't select which specialization to call.
}
```

We could force Swift generics to be instantiated if they use a C++ template.
Fully generic entry points will be still emitted to fulfill ABI expectations,
but they would trap.

```swift
// C++ header imported in Swift.

@_must_specialize
func functionTemplate<T>(_ t: T)
```

```swift
// Usage example in Swift.

@_must_specialize
func genericFunction<T>(_ t: T) {
  functionTemplate<T>(t) // OK!
}

struct GenericStruct<T> {
  init GenericStruct(_ t: T) { self.t = t }
  var t: T

  @_must_specialize
  func callGenericFunction() {
    genericFunction(t) // OK!
  }
}

func example() {
  GenericStruct(42).callGenericFunction()
}
```

We introduce a `@_must_specialize` attribute for generic functions that must be
instantiated in order to be called. The importer marks all Swift generic
functions that are backed by a C++ template as `@_must_specialize`, and from
there the Swift compiler infers the attribute for all users.

This analysis relies on over-approximating the dynamic callgraph with the static
callgraph. The static callgraph is feasible to compute in most cases, since
Swift has very limited ways to abstract over an unspecialized generic function.
Speicifically, Swift does not have generic closures. Swift does allow protocols
to have requirements for generic functions though.

### Function templates: importing as real generic functions

If we know the complete set of allowed type arguments to a C++ function
template, we could import it as an actual Swift generic function that performs
dynamic dispatch.

```c++
// C++ header.

template<typename T>
void functionTemplate(T t) { ... }

// Any number of explicit specializations may follow.
template<>
void functionTemplate(int x) { ... }
```

Let's say it is known that `functionTemplate` can only take `Int` and `UInt`.

```swift
// C++ header imported in Swift.

func _cxx_functionTemplate<T>(_ t: T) // Imported as explained before.

func functionTemplate<T>(_ t: T) {
  if T == Int.self {
    return _cxx_functionTemplate(t as! Int)
  }
  if T == UInt.self {
    return _cxx_functionTemplate(t as! UInt)
  }
  fatalError()
}
```

The user can write this code themselves (in an overlay, for example), or if we
can communicate the allowed list of types to the importer, it can synthesize the
function for us. Either way, the result is that we get a true generic Swift
function.

### Class templates

Class templates pose the same challenges as function templates regarding
separate compilation. In addition to that, we can't ignore explicit
specializations of class templates when importing the API to Swift.
We could ignore explicit specializations of function templates, because they
don't affect the API. Explicit specializations of class templates can
dramatically change the API of the type.

### Class templates: Importing full class template instantiations

A class template instantiation could be imported as a struct named
`__CxxTemplateInst` plus Itanium mangled type of the instantiation (see the
`type` production in the Itanium specification). Note that Itanium mangling is
used on all platforms, regardless of the ABI of the C++ toolchain, to ensure
that the mangled name is a valid Swift type name (this is not the case for MSVC
mangled names). A prefix with a double underscore (to ensure we have a reserved
C++ identifier) is added to limit the possibility for conflicts with names of
user-defined structs. The struct is notionally defined in the `__C` module,
similarly to regular C and C++ structs and classes. Consider the following C++
module:

```c++
// C++ header.

template<class T>
struct MagicWrapper {
  T t;
};
struct MagicNumber {};

typedef MagicWrapper<MagicNumber> WrappedMagicNumber;
```

`WrappedMagicNumber` will be imported as a typealias for a struct
`__CxxTemplateInst12MagicWrapperI11MagicNumberE`. Interface of the imported
module will look as follows:

```swift
// C++ header imported to Swift.

struct __CxxTemplateInst12MagicWrapperI11MagicNumberE {
    var t: MagicNumber
}
struct MagicNumber {}
typealias WrappedMagicNumber = __CxxTemplateInst12MagicWrapperI11MagicNumberE
```

### Class templates: importing specific specializations

Just like with calls to C++ function templates, it is easy to compile a use of a
C++ class templates if the usage in Swift code unambiguously specifies which
specialization should be used.

```c++
// C++ header.

template<typename T>
class ClassTemplate {};
```

```swift
// C++ header imported to Swift.

struct ClassTemplate<T> {}
```

```swift
// Usage example.

func useClassTemplate() {
  var x = ClassTemplate<Int32>() // OK, uses `ClassTemplate<int>`.
}
```

If the class template provides specializations with completely different APIs,
we don't have an issue, because we only need to import specific
specializations into Swift.

```c++
// C++ header.

template<typename T>
class ClassTemplate {
  void func1();
};

template<>
class ClassTemplate<int> {
  void func2();
};

template<typename T>
class ClassTemplate<std::vector<T>> {
  void func3();
};
```

```swift
// C++ header imported to Swift.

// A shell of a generic struct only used for name lookup.
struct ClassTemplate<T> {}
```

```swift
// Usage example.

func useClassTemplate() {
  var x1 = ClassTemplate<Int8>() // OK
  var x2 = ClassTemplate<Int32>() // OK
  var x3 = ClassTemplate<cxx_std.vector<Int32>> // OK
}
```

When the Swift compiler sees `ClassTemplate<Int8>`, it translates the type to
C++, that is, `ClassTemplate<char>`. Then Swift compiler asks the Clang importer
to import that specialization. Clang importer instantiates the primary template
with `T=char` and imports the resulting `ClassTemplate<char>`. Same for all
other rereferences to `ClassTemplate`. At the end, we get:

```c++
// C++ header imported to Swift, as needed for the program above.

// A shell of a generic struct only used for name lookup.
struct ClassTemplate<T> {}

struct ClassTemplate<Int8> {
  func func1()
}

struct ClassTemplate<Int32> {
  func func2()
}

struct ClassTemplate<cxx_std.vector<Int32>> {
  func func3()
}
```

Effectively, `ClassTemplate<Int8>`, `ClassTemplate<Int32>`, and
`ClassTemplate<cxx_std.vector<Int32>>` are completely unrelated types; they just
have angle brackets in their name. (By the way, the same is the case in C++.)

Advantages of this approach:

* Relatively straightforward to implement.

* Simple model, few or no corner cases.

Disadvantages of this approach:

* Users can only use complete specializations. In other words, users can't use a
  C++ template from Swift generic and pass a generic type parameter to the C++
  template.

### Class templates: using with generic type parameters

Many class templates don't define specializations that dramatically change the
API, or use features like non-type template parameters that don't exist in Swift
generics. It is desirable to import such templates as Swift generics directly.
With a lightweight static analysis, or with annotations in the C++ header, the
compiler would recognize such a type and import the API shared by all
instantiations into Swift.

Similarly to our treatment of function templates described above, we can
annotate the transitive closure of generic Swift code that uses C++ class
templates with `@_must_specialize`.

### Class templates: using in generic code through a synthesized protocol

Class templates that have a uniform API across all specializations could be made
to conform to a Swift protocol, which would facilitate passing them to generic
code.

```c++
// C++ header.

template<typename T>
class MyClassTemplate {
  void func1(T t);
};
```

```swift
// C++ header imported in Swift.

protocol MyClassTemplateProtocol {
  associatedtype T
  func func1(_ t: T)
}

struct MyClassTemplate<T> : MyClassTemplateProtocol {}
```

In this model, the Swift compiler can still import only specific specializations
of `MyClassTemplate`. The new part is that the Swift compiler will synthesize a
protocol, `MyClassTemplateProtocol`, that contains APIs shared by all
specializations. The Swift compiler will also make every imported specialization
of `MyClassTemplate` conform to `MyClassTemplateProtocol`.

This way, we solved the issue of specializations being unrelated types: now they
all conform to a common protocol, and therefore, generic code can operate
transparently on any specialization.

```swift
// Usage example.

// Use a C++ class template from a Swift generic function without naming a
// specific specialization.
func useGeneric<SomeSpecialization>(_ classTemplate: SomeSpecialization, _ t: SomeSpecialization.T)
  where SomeSpecialization: MyClassTemplateProtocol
{
  classTemplate.func1(t)
}

func useConcrete() {
  var classTemplate = MyClassTemplate<Int32>()
  classTemplate.func1(0)
  useGeneric(classTemplate, 0)
}
```

### Class templates: importing as real generic structs

If we know the complete set of allowed type arguments to a C++ struct
template, we could import it as an actual Swift generic struct. Every method of
that struct will perform dynamic dispatch based on type parameters. See
the section about function templates for more details.

### Mapping SFINAE

We can map SFINAE to generic constraints and to conditional extensions.

TODO

### Variadic templates

TODO

### Non-type template parameters

TODO

### Template template parameters

TODO

## Overloaded operators

TODO: Mapping C++'s operators to Equatable, Comparable, Hashable.


## <a name="operator-star-operator-arrow"></a> `operator*`, `operator->`

TODO

## <a name="operator-square-brackets"></a> `operator[]`

`operator[]` semantically maps well to Swift's `subscript`.

```c++
// C++ header.

class MyCxxContainer {
public:
  const double& operator[](int i) const;
  double& operator[](int i);
};
```

```swift
// C++ header imported in Swift.

struct MyCxxContainer {
  public subscript(_ i: Int) -> Double { get set }
}
```

The synthesized `subscript` uses the `_read` and `_modify` generalized accessors
to forward the memory address to the caller.

```swift
// Implementation details of the imported API.

struct MyCxxCollection {
  // const double& operator[](int i) const;
  private func _operatorBracketsConst(_ i: Int) -> UnsafePointer<Double>

  // double& operator[](int i);
  private func _operatorBrackets(_: Int) -> UnsafeMutablePointer<Double>

  // Swifty API.
  public subscript(_ i: Int) -> Double {
    _read {
      yield _operatorBracketsConst(i).pointee
    }
    _modify {
      yield &_operatorBrackets(i).pointee
    }
  }
}
```

## <a name="operator-parentheses"></a> `operator()`

Swift has an equivalent for C++'s `operator()`: `callAsFunction` (introduced in
[SE-0253: Callable values of user-defined nominal
types](https://github.com/apple/swift-evolution/blob/main/proposals/0253-callable.md)).

```c++
// C++ header.

class MultiplyIntDouble {
public:
  double operator()(int x, double y);
};
```

```c++
// C++ header imported in Swift.

struct MultiplyIntDouble {
  public func callAsFunction(_ x: Int, _ y: Double) -> Double { ... }
}
```

This mapping rule would handle the call operator of `std::function`,
`function_ref` and similar types.

## Literal operators

TODO

## Exceptions

### Background

C++ unfortunately has the opposite default to Swift where exception throwing is
concerned. Any C++ function that is not explicitly marked `noexcept` must be
assumed to be potentially throwing, even though many such functions don't throw
in practice.

If we imported all of these functions into Swift as `throws` functions, the code
calling them would be littered with `try!`s. Requiring all imported functions (and
everything they call transitively) to be marked `noexcept` also seems excessively
burdensome and is not idiomatic C++.

### Baseline functionality: Import functions as non-throwing, terminate on uncaught C++ exceptions

In the first iteration of C++ interop, we will import all C++ functions as
non-throwing Swift functions. If a C++ function called from Swift throws an
exception that is not caught within the C++ code, the program will terminate.

This approach is similar to that taken by the [Python interop
library](https://github.com/pvieito/PythonKit/blob/main/PythonKit/Python.swift),
which also terminates the program by default if a Python exception is raised and
not caught within the Python code.

If exceptions thrown in C++ need to be handled in Swift, this can be done by
writing a C++ wrapper that catches the exception and returns a corresponding
error object.

### Extended functionality: Optionally propagate exceptions to Swift

If we find that developers routinely need to handle C++ exceptions in Swift,
writing C++ wrappers as described above will obviously not be a satisfactory
solution. In this case, we will add an option to propagate C++ exceptions as
Swift exceptions; this will be backward compatible with the baseline approach
described above.

We again take inspiration from Python interop. There, appending `.throwing` to
the function name calls a variant of the function that propagates the Python
exception to Swift.

It isn't really practical to do something exactly analogous in C++ interop. We
could import each function twice and identify the throwing version by a name
suffix or a dummy parameter. However, this solution would bloat the interface of
imported classes, and it would not be universal: Name suffixes can't be used
with constructors or operators; a dummy parameter could be used with most
constructors, but still doesn't work for default constructors or operators.

Instead, we propose extending Swift with a `throws!` marker. A function marked
with `throws!` can potentially throw exceptions, but the function does not need
to be called with `try`. If the function _is_ called with `try`, exceptions are
handled as they would be for a normal throwing function. If the function is not
called with `try` and the function raises an exception, the program is
terminated. These semantics are close to C++ exception handling semantics.

All C++ functions that are not marked `noexcept` would be imported as `throws!`
functions; `noexcept` functions would be imported as non-throwing functions.

This brief sketch obviously leaves many questions unanswered on the detailed
semantics that a `throws!` feature would have, for example whether user-written
Swift code should be allowed to use `throws!` -- see also [this forum
discussion](https://forums.swift.org/t/handling-c-exceptions/34823). Before we
take any steps towards implementing C++ exception proagation, we will submit a
formal Swift Evolution proposal for the `throws!` feature.

The other question to answer is how we would map the C++ exception to a
corresponding Swift object implementing `Error`. In theory, C++ allows
objects of any copy-initializable type to be thrown. In practice, most
user-defined C++ exceptions derive from `std::exception`, so it would be natural
to propagate C++ exceptions as the Swift-imported equivalent of
`std::exception` and make that type implement `Error`. We could add a separate
fallback error type (e.g. `CxxUnknownException`) for the case where the
exception does not derive from `std::exception`.

As `std::exception` is a polymorphic type, the details of how `std::exception`
will be represented in Swift will need to wait until we have finalized how
polymorphism is handled (see also the section on [virtual member
functions](#virtual-member-functions)).

### Implementation

Many common C++ ABIs allow the default behavior (terminate the program if a
C++ exception is thrown) to be implemented at zero cost. In particular, it is not
necessary to wrap every C++ function in a synthesized try-catch block.

For example, the Itanium C++ ABI defines a so-called personality routine that is
called for each stack frame as the stack is being unwound. The idea is that
different languages can have different personality routines, so that different
languages can co-exist on the stack and can each define their own stack frame
cleanup logic.

The stack unwinding infrastructure finds the correct personality routine by
consulting a so-called unwind table, which maps program counter ranges to
personality routines.

We would define unwind table entries covering all Swift code that does not
attempt to handle C++ exceptions and have these entries map to a personality
routine that simply terminates the program.

If exception support is turned off in the C++ compiler by passing `-Xcc
-fno-exceptions` to `swiftc`, we assume that the C++ code never throws
exceptions and will not emit any unwind table entries for Swift code.

## Atomics

TODO

## Importing non-const pointer as extra return values

TODO

# Enhancing C++ API mapping into Swift with bridging

## Bridging data types with different memory layout

When we import a C++ `T` into Swift as a type `U`, in the general case we must
ensure that `T` and `U` have identical memory layout. For example, Swift's `Int8`
and C++'s `int8_t` have identical memory layout, and therefore, we can import
`int8_t` as `Int8` everywhere.

If `T` and `U` have even slightly different memory layouts, we must invoke a
bridging function at the interop boundary. Further sections in this document
provide many examples of such type pairs, but to give an example, consider
`std::vector<T>` in C++, which is semantically similar to `Array<T>` in Swift,
but has a completely different memory layout. If we want to map them to one
another, but must keep the memory layout of both types unchanged, we must
convert the `std::vector<T>` value into an `Array<T>` value when the program
execution crosses the language boundary.

For example:

```c++
// C++ header.

std::vector<int> IncrementVectorValues(std::vector<int> v);
```

```swift
// C++ header imported in Swift.

// Note: no C++ vectors!
func IncrementVectorValues(_ v: [CInt]) -> [CInt]
```

```swift
// Using the imported C++ API in Swift.

func callIncrementVectorValues() -> CInt {
  var xs: [CInt] = IncrementVectorValues([10, 20, 30])
  return xs[0] // = 11.
}
```

## Bridging: behind the scenes

Here's a simplified description of how Swift implements bridging. Behind the
scenes, the function `IncrementVectorValues` is imported as is, with C++ data
types:

```c++
// C header imported in Swift, behind the scenes:

func _cxx_IncrementVectorValues(std.vector<CInt> v) -> std.vector<CInt>
```

C++ bridging support code provides a function that converts a `std::vector` to a
Swift `Array` and vice versa:

```swift
// Swift standard library, C++ support module.

func StdVectorToArray<T>(_ vector: std.vector<T>) -> [T]
func ArrayToStdVector<T>(_ array: [T]) -> std.vector<T>
```

Each caller is transformed to call the bridging function:

```
// Using the imported C++ API in Swift: code written by the user.

func callIncrementVectorValues() -> CInt {
  var xs: [CInt] = IncrementVectorValues([10, 20, 30])
  return xs[0] // = 11.
}
```

```swift
// Using the imported C++ API in Swift: code rewritten by the type checker.

func callGetVector() -> CInt {
  var xs: [CInt] =
    StdVectorToArray(_cxx_IncrementVectorValues(ArrayToStdVector([10, 20, 30])))
  return xs[0] // = 11.
}
```

A naive implementation of `StdVectorToArray` and `ArrayToStdVector` would have
to copy the container's elements.  However, with enough cooperation between the
C++ standard library and the Swift standard library, Swift `Array` could take
ownership of `std::vector`'s storage and vice versa in O(1), avoiding making a
copy.  Such cooperation would likely require changing the ABI of at least one of
the types, so it would not be feasible to implement in all environments.

## Bridging does not work in every context

Bridging between types with different memory layouts does not work universally.
For example, just because a C++ type `T` can be bridged to a Swift type `U`, it
does not follow that we can bridge a `T*` to an `UnsafeMutablePointer<U>`.

```c++
// C++ header.

const std::vector<int> *GetPtrToVector();
```

```swift
// C++ header imported in Swift.

// We can't bridge types like in the example below, it is not implementable.
// The underlying C++ function returns a vector with unclear ownership semantics,
// but we need to return a pointer to a Swift Array.
// If the bridging code allocates the Swift Array on the heap, what would own it?
// If the bridging code does not allocate a new Array, where does it get the
// storage from?
func GetPtrToVector() -> UnsafePointer<[CInt]>

// OK.
func GetPtrToVector() -> UnsafePointer<std.vector<CInt>>
```

Therefore, we can perform non-trivial bridging only in a limited number of
contexts. In all remaining places C++ types must be imported according to the
general rules.

As a consequence, every non-trivial bridging solution needs a fallback that does
not require adjusting the memory layout.

## <a name="bridging-std-function"></a> Bridging `std::function`

`std::function` in C++ is similar to closures in Swift. The primary difference
is that `std::function` has an empty state, similarly to function pointers,
while Swift closures don't.

Due to allowing an empty state, `std::function` must be mapped to an optional
Swift closure, unless annotated as non-nullable.

To convert a non-empty `std::function` value to a Swift closure, we need to
define a thunk and allocate a closure context on the heap. The new closure
context will point to a copy of the `std::function` value. The thunk will use a
Swift calling convention, and it will forward the arguments to
`std::function::operator()()` using the C++ calling convention.

A thunk like this will not cost much in terms of code size. The primary cost of
the thunk will come from dynamic dispatch. We will have double dynamic dispatch:
first one at the callsite that calls the Swift closure and ends up calling the
thunk, and second one from the thunk to the C++ code wrapped in `std::function`.
Another issue is branch predictor pollution: there will be a single thunk
backing all closures with the same signature. Indirect branches from thunk will
be difficult to predict for the branch predictor.

There is additional cost contributed by reference counting: closures in Swift
are reference counted, while `std::function` isn't.

Finally, allocating a new closure context on the heap is a cost to be paid on
every conversion from a C++ `std::function` to a Swift closure.

## <a name="bridging-std-string"></a> Bridging `std::string`

Ergonomically, the best mapping of C++'s `std::string` is Swift's `String`. Both
types support nul bytes (the conversion has to take them into account and cannot
assume nul-terminated strings). However, there's a semantic gap: Swift strings
require text to be valid UTF-8.

We have a couple of options to address the UTF-8 issue:

* Trust C++ code to only store UTF-8 text in strings, and map them to Swift's
  `String` where possible. Perform a runtime check for UTF-8 validity during the
  conversion. Allow to annotate `std::string`s that store binary data, and map
  those as either Swift's `Array` or `std::string`.

* Assume `std::string`s store binary data, and map them to according to the
  regular interop rules to `cxx_std.string`. Allow users to annotate UTF-8
  strings as such, and map them to Swift's `String`.

The annotations could be inferred with a dynamic analysis tool that would track
which `std::string`s contain binary data.

Here's an example of API mapping if we decide to trust `std::string`s to store
UTF-8 data.

```c++
// C++ header.

class Employee {
public:
  std::string DebugDescription() const;
  [[swift::import_as_std_string]] std::string SerializedAsProtobuf() const;
};
```

```swift
// C++ header imported in Swift.

struct Employee {
  func DebugDescription() -> String
  func SerializedAsProtobuf() -> std.string
}
```

To avoid copying data unnecessarily, we need the C++ and Swift standard
libraries to cooperate, so that Swift's `String` can take ownership of
`std::string`'s heap allocation, and vice versa.

Character data in `Swift.String` is stored in a reference-counted object.
`Swift.String` can take ownership of `std::string` by transferring ownership of
`std::string` to a newly-allocated reference-counted object. Swift/Objective-C
bridging of `NSString` already works exactly this way.

On non-Objective-C platforms, `Swift.String` assumes that the character data is
tail-allocated in the reference-counted object; this assumption will have to be
replaced with a branch. Therefore, adding this sort of bridging on
non-Objective-C platforms will create a certain (small) performance penalty. It
is important to note that this performance penalty has been always affecting
Objective-C platforms and it is considered acceptable.

We could eliminate the branch on non-Objective-C platforms by changing
`Swift.String` there to always use a reference-counted object with an
`std::string` in it as the backing storage. The disadvantage of such memory
layout is that `Swift.String` would need to dereference two levels of
indirection to access to character data, instead of one like we have today.

`std::string` can't take ownership of `Swift.String`'s reference-counted object,
because `std::string` has no branches in its code that retrieves the pointer to
the character data and in its deallocation code. Adding branches there is
certainly possible, but will likely lead to regressions for many C++
applications, including ones that don't use Swift. Therefore, this approach
looks like a non-starter.

Therefore, the only viable approach for O(1) bidirectional bridging is having
`Swift.String` use `std::string` as its backing storage, and taking the penalty
of a double-indirection to access character data.

If one-way C++-to-Swift bridging is sufficient, it can be implemented with a
branch in the `Swift.String` code that retrieves a pointer to character data.

We can implement one-way O(1) Swift-to-C++ bridging by embedding a fake
`std::string` in the `Swift.String` buffer. Such a `std::string` instance would
not be full-fledged, and would be only good for reading from it; its destructor
can never be called.

## <a name="bridging-std-vector"></a> Bridging `std::vector`

Ergonomically, the best mapping of C++'s `std::vector` is Swift's `Array`.

Except for the case of `std::vector<bool>`, the constraints for `Swift.Array`
taking ownership of `std::vector`'s element buffer and vice versa are identical
to string bridging.

## <a name="bridging-std-set-std-map"></a> Bridging `std::set`, `std::map`

Swift standard library does not provide collections with semantics similar to
`std::set` and `std::map`, so they can't be meaningfully bridged to any Swift
vocabulary type. Therefore, they will be imported as `std.set` and `std.map`.

It would be useful to provide ergonomic ways to convert `std.set` and `std.map`
to `Swift.Set` and `Swift.Dictionary`, since `std::set` and `std::map` are
sometimes used in C++ APIs (especially older ones) when the element order
doesn't matter.

## <a name="bridging-std-unordered-set-std-unordered-map"></a> Bridging `std::unordered_set`, `std::unordered_map`

The most ergonomic mapping of `std::unordered_set` and `std::unordered_map` are
`Swift.Set` and `Swift.Dictionary`.

The constraints for these Swift types taking ownership of C++'s storage buffers
and vice versa are quite similar to string bridging. An interesting new point to
highlight is that the `Swift.Set` and `Swift.Dictionary` types would need to use
the hash function defined in C++ for C++ types. It should be possible to expose
the C++ hash function in Swift as a conformance to the `Hashable` protocol, or
as a conformance to a new C++-specific protocol for hashing.

## <a name="bridging-std-tuple-std-pair"></a> Bridging `std::tuple`, `std::pair`

Ergonomically, the best mapping of C++'s `std::tuple` and `std::pair` are
Swift's tuples.

Tuple and pair elements have to be copied to implement non-trivial bridging. It
is unreasonable to introduce a dual representation and require a branch to
access tuple elements either in C++ or Swift.

However, there are only so many different ways to lay out a `std::pair` in
memory. In fact, it is almost certainly a struct with exactly two data members,
`first` and `second`, in that order. When `std::pair<T, U>` and Swift's tuple
`(T, U)` happen to use the same layout, we could bridge them trivially, without
copying the data.

```c++
// C++ header.

std::pair<int, int> *GetPairPtr();
```

```swift
// C++ header imported in Swift.

UnsafeMutablePointer<(Int, Int)> GetPairPtr()
```

`std::tuple` is more complex and has more viable implementation options compared
to `std::pair`. For example, `std::tuple` is laid out in forward order by
libc++, and in backward order by libstdc++. Therefore, if libc++ is used,
there's a good chance that the memory layout of `std::tuple` matches the memory
layout of the corresponding Swift tuple, and we could bridge them trivially.

The disadvantage of the techniques described above is that they depend on
implementation details of the standard library, and as those change (or if the
user switches to a different standard library altogether), the API in Swift
might change as well.

## <a name="bridging-std-span"></a> Bridging `std::span`

The difficulty with `std::span<T>` is that it has a different API in Swift
depending on whether `T` is `const` or not.

```c++
// C++ standard library.

template<typename T>
class span {
public:
  constexpr T& front() const noexcept;
};
```

```c++
// C++ standard library imported in Swift.

// When T is non-const.
struct span<T> {
  public func front() -> UnsafeMutablePointer<T>
}

// When T is const.
struct span<T> {
  public func front() -> UnsafePointer<T>
}

// Need to choose one way to import, can't have both!
```

The easiest way to deal with this is to only import `std::span<T>` as full
specialization (the fallback way to import templates). However, that would not
be very ergonomic, and would prevent other templates that use `std::span` from
being imported as generics in Swift.

A more ergonomic way would be to import `std::span` as two generic structs in
Swift, selecting the appropriate one depending on constness.

```swift
// C++ standard library imported in Swift.

struct mutable_span<T> {
  public func front() -> UnsafeMutablePointer<T>
}

struct const_span<T> {
  public func front() -> UnsafePointer<T>
}
```

```c++
// C++ header.

std::span<int> GetMutableIntSpan();
std::span<const int> GetConstIntSpan();
```

```swift
// C++ header imported in Swift.

func GetMutableIntSpan() -> std.mutable_span<Int>
func GetConstIntSpan() -> std.const_span<Int>
```

## Standard C++ containers in general

It seems appropriate to provide an overlay that adds `Swift.Collection`
conformances to C++ container types.

## Custom C++ containers

The importer could try to recognize custom C++ containers and synthesize
`Swift.Collection` conformances, however, that seems fragile: custom containers
often don't implement the complete container API as required by the standard, or
deviate from it in subtle ways.

It seems best to add `Swift.Collection` conformances in overlays.

## <a name="bridging-absl-hash-set-map"></a> Bridging `absl::flat_hash_{set,map}`, `absl::node_hash_{set,map}`

Projects that use Abseil often use Abseil hash tables a lot more than standard
containers. However the same is also true about other libraries, like Boost or
Qt. Therefore, privileging a third-party library in C++/Swift interop seems
inappropriate. Abseil, Boost, and Qt should be treated just like user-written
code. Library vendors can provide annotations and Swift overlays to improve the
API in Swift.

# Enhancing C++ API mapping into Swift with annotations

## Annotation workflow

Annotations in C headers are employed by the Swift / C interop today (for
example, nullability annotations). However, these annotations must be added to
headers manually. How could tools infer annotations?

**Online inference at compile-time.** The Swift compiler could infer annotations
from information available in the headers. For example:

```c++
// example.h

class Example {
public:
  int *get_mutable_value() { return &value; }
  // The Swift compiler infers that the return type is `int * _Nonnull` because
  // the function never returns nullptr.
};
```

The problem with this approach is that it is making API decisions based on API
implementation details, without letting the API owner to intervene. It is going
to be fragile in the long run: no-op changes to implementation details of C++
APIs can tip annotation inference one way or the other, and unintentionally
change the Swift API. Imagine that the example above is refactored to:

```c++
// example.h

class Example {
public:
  int *get_mutable_value() { return get_mutable_value_impl(); }
private:
  int *get_mutable_value_impl(); // defined in example.cc
};

// The Swift compiler does not know whether `get_mutable_value_impl()`
// can return nullptr or not, therefore its return type is
// `int * _Null_unspecified`. Therefore, the return type of
// `get_mutable_value()` is now changed to `int * _Null_unspecified` as well.
```

API declarations should be the source of truth for API information; this also
aligns with expectations of C++ API owners.

**Offline inference.** The concerns about inspecting implementation details for
inference would be alleviated if inference tooling produced a source code patch
that would be reviewed by a human and adjusted if necessary before being
committed.

The ideal option is to add annotations directly to the header, to make the API
contract obvious to all readers and API owners. However, sometimes API owners
don't want to change the header, or can't be reached. In those cases,
annotations can be added to a sidecar file, removing the need to change the
header.

A sidecar annotation file allows to add arbitrary attributes to declarations
parsed from a header file. You can find examples of such files in the [apinotes
directory](../apinotes). APINotes files
are handled by the [APINotes library in
Clang](https://github.com/apple/llvm-project/tree/apple/main/clang/lib/APINotes).
Clang reads an APINotes file alongside the header file; Clang injects attributes
specified by APINotes into the AST parsed from the header.

## Tooling to infer nullability annotations

Nullability annotations in C++ headers are useful not only for Swift / C++
interop; they also document the intended API contract to C++ API users.
Nullability annotations can be validated by static and dynamic analysis tooling
in C++ (e.g., UBSan can be extended to detect assignments of `nullptr` to
`_Nonnull` pointers).

To infer nullability annotations we can use a combination of static and dynamic
analysis. Static analysis could infer nullability in more obvious cases -- along
with some confidence score, while dynamic analysis could provide insight into
arbitrarily complex APIs and data structures, with the usual caveat that the
inference results are only as good as the test cases.

There is a lot of existing research about detecting nullability issues in C and
C++ with static analysis, so we are not discussing the design of potential
static analysis tooling here. However, we are not aware of existing dynamic
analysis tooling that infers nullability.

Nullability inference based on dynamic analysis will use compile-time
instrumentation that is similar to UBSan for references, but instead of
producing a fatal error upon a nullptr store, we will record this fact and
continue. For each source-level pointer variable and class member declaration,
the compiler will allocate a global boolean flag that tracks nullability, and a
usage counter, which will be used to gauge confidence. The nullability flags are
initialized to "false" at program startup, usage counters are initialized to
zero. Each store into the pointer variables is instrumented, and when a nullptr
is stored, the corresponding flag is set to "true". Either way, the usage
counter is incremented. At program shutdown (or when signalled somehow), the
inferred nullability flags and usage counters are saved to disk.

## APIs that take a pointer and count

Many C and C++ APIs take a pointer and count. It would be nice if we could
import them as a buffer pointer in Swift, given appropriate annotations:

```c++
// C++ header.

void example(int *xs, int count);
// TODO: figure out what annotations might look like.
```

```swift
// C++ header imported in Swift.

func example(_ xs: UnsafeMutableBufferPointer<CInt>)
```

# Current state of art: importing Swift code into C

The Swift compiler generates a header that C code can use.

TODO: add details.

# Importing Swift APIs into C++

TODO

## Resilient types

The semantic gap here is related to resilient types -- their size is unknown at
compile time. `std::vector<T>` needs to know `sizeof(T)` at compile time. This
is a common problem in Swift-to-C++ bridging in general, and it would be solved
with boxing. Boxes for resilient Swift types would have a fixed size.

# Forum discussions

The topic of Swift/C++ interoperability has been discussed on Swift forums
before:

* [C++ Interop](https://forums.swift.org/t/c-interop/25567)
* [C++ / Objective-C++ Interop](https://forums.swift.org/t/c-objective-c-interop/9989)
* [C++ support in Swift](https://forums.swift.org/t/c-support-in-swift/13313)
