:orphan:

Summary
=======

Pointer arguments are a fact of life in C and Cocoa, and there's no way we're
going to realistically annotate or wrap every API safely. However, there are
plenty of well-behaved APIs that use pointer arguments in well-behaved ways
that map naturally to Swift argument conventions, and we should interact with
those APIs in a natural, Swift-ish way. To do so, I propose adding language
and library facilities that enable the following uses of pointer
arguments:

- Const pointer arguments ``const int *``, including const pointers to ObjC
  classes ``NSFoo * const *``, can be used as "in" array arguments,
  as ``inout`` scalar arguments, or as ``UnsafeMutablePointer`` arguments.
- Non-const pointer arguments to C types, ``int *``, can be used as ``inout``
  array or scalar arguments, or as ``UnsafeMutablePointer`` arguments.
- Non-const pointer arguments to ObjC class types, ``NSFoo **``, can be used as
  ``inout`` scalar arguments or passed ``nil``. (They cannot be used as
  array arguments or as ``UnsafeMutablePointer`` arguments.)
- ``const void *`` and ``void *`` pointers can be used in the same ways as
  pointers to any C type (but not ObjC types).

This model intentionally doesn't try to provide a mapping to every possible
use case for pointers in C.  It also intentionally avoids addressing special
cases we could potentially provide higher-level support for. Some particular
issues this proposal specifically does not address:

- Pointer return values
- Special handling of ``char*`` and/or ``const char*`` arguments
- Special handling of Core Foundation types
- Special handling of ``NSError**`` arguments
- Precise lifetime of values (beyond the minimal lifetime extension to the
  duration of a call)
- Overriding of ObjC methods that take pointer arguments with subclass methods
  that take non-pointer arguments

Design Considerations
=====================

Const Pointer Arguments
-----------------------

Arrays
~~~~~~

Const pointer arguments are frequently used in both C and Objective-C to take
an array of arguments effectively by value. To support this use case, we should
support passing a Swift ``Array`` value to a const pointer argument. An
example from Core Foundation is ``CGColorCreate``, which takes a
``CGFloat`` array of color space-specific components::

  let rgb = CGColorSpaceCreateCalibratedRGB()
  let cyan = CGColorCreate(rgb, [0, 1, 1])

We are willing to assume that the API is well-behaved and does not mutate the
pointed-to array, so we can safely pass an interior pointer to the array storage
without worrying about mutation. We only guarantee the lifetime of the
array for the duration of the call, so it could potentially be promoted to a
stack allocation.

"In" Arguments
~~~~~~~~~~~~~~

Const pointer arguments are also used in many cases where a value is unmodified,
but its identity is important. Somewhat more rarely, const pointer arguments
are used as pure "in" value arguments with no regard for identity; this is
particularly prevalent on platforms like Win32 where there has historically
been no standard ABI for passing structs by value, but pure "in" pointer
parameters are rare on our platforms.  The potential consequences of
disregarding value identity with C APIs are too high to allow scalar arguments
to implicitly be used as pointer arguments::

  // From C: void foo(const pthread_mutex_t *);
  import Foo

  let mutex = pthread_mutex_create()
  // This would pass a different temporary buffer on each call--not what you
  // want for a mutex!
  foo(mutex)
  foo(mutex)
  foo(mutex)

Although const pointers should never be used for actual mutation, we propose
that only ``inout`` scalar arguments be accepted for const pointer parameters.
Although our semantics normally do not guarantee value identity, ``inout``
parameters that refer to stored variables or stored properties of C-derived
types are in practice never subjected to implicit writebacks except in limited
circumstances such as capture of ``inout`` references in closures that could be
diagnosed. Requiring ``inout`` also prevents the use of rvalues or ``let``
bindings that never have well-defined addresses as pointer arguments. This
more clearly communicates the intent for the callee to receive the same
variable on every call::

  // From C: void foo(const pthread_mutex_t *);
  import Foo

  var mutex = pthread_mutex_create()
  foo(&mutex)
  foo(&mutex)
  foo(&mutex)

If using an rvalue as a pointer argument is desired, it can easily be wrapped
in an array. This communicates that the value *is* being copied into the
temporary array, so it's more obvious that identity would not be maintained::

  // an immutable scalar we might want to pass into a "const double*".
  let grayLevel = 0.5
  let monochrome = CGColorSpaceCreateGrayscale()

  // error, can't pass Double into second argument.
  let c1 = CGColorCreate(monochrome, grayval)
  // error, can't take the address of a 'let' (would be ok for a 'var')
  let c2 = CGColorCreate(monochrome, &grayval)
  // OK, we're explicitly forming an array
  let c3 = CGColorCreate(monochrome, [grayval])

Non-Const Pointer Arguments
---------------------------

C Types
~~~~~~~

Non-const arguments of C type can be used as "out" or "inout" parameters,
either of scalars or of arrays, and so should accept ``inout`` parameters of
array or scalar type. Although a C API may expect a pure "out" parameter and
not require initialization of its arguments, it is safer to assume the argument
is ``inout`` and always require initialization::

  var s, c: Double
  // error, 's' and 'c' aren't initialized
  sincos(0.5, &s, &c)

  var s1 = 0.0, c1 = 0.0
  // OK
  sincos(0.5, &s1, &c1)

For array parameters, the exact point of mutation inside the callee cannot be
known, so a copy-on-write array buffer must be eagerly uniqued prior to the
address of the array being taken::

  func loadFloatsFromData(_ data: NSData) {
    var a: [Float] = [0.0, 0.0, 0.0, 0.0]
    var b = a

    // Should only mutate 'b' without affecting 'a', so its backing store
    // must be uniqued
    data.getBytes(&b, sizeof(Float.self) * b.count)
  }

ObjC Types
~~~~~~~~~~

ARC semantics treat an ``NSFoo**`` type as a pointer to an ``__autoreleasing``
``NSFoo*``. Although in theory these interfaces could receive arrays of object
pointers in Objective-C, that use case doesn't come up in Cocoa, and we can't
reliably bridge such APIs into Swift. We only need to bridge ObjC mutable pointer
types to accept a scalar ``inout`` object reference or ``nil``.

Pointer Return Values
---------------------

This proposal does not address the handling of return values, which should still
be imported into Swift as ``UnsafeMutablePointer`` values.


Library Features
================

The necessary conversions can be represented entirely in the standard library
with the help of some new language features, inout address conversion, inout
writeback conversion, and interior pointer conversion, described below. There
are three categories of argument behavior needed, and thus three new types.
These types should have no user-accessible operations of their own other than
their implicit conversions. The necessary types are as follows:

- ``CConstPointer<T>`` is the imported representation of a ``const T *``
  argument. It is implicitly convertible from ``inout T`` by inout address
  conversion and from ``Array<T>`` by immutable interior pointer
  conversion. It is also implicitly convertible to and from ``UnsafeMutablePointer<T>``
  by normal conversion.
- ``CMutablePointer<T>`` is the imported representation of a ``T *``
  argument for a POD C type ``T``. It is implicitly convertible from
  ``inout T`` by inout address conversion and from ``inout Array<T>`` by mutating
  interior pointer conversion. It is also implicitly convertible to and from
  ``UnsafeMutablePointer<T>`` by normal conversion.
- ``ObjCInOut<T>`` is the imported representation of a ``T **``
  argument for an ObjC class type ``T``. It is implicitly convertible from
  ``inout T`` by inout writeback conversion and is implicitly convertible
  from ``nil``. It cannot be converted from an array or to ``UnsafeMutablePointer``.

New Language Features
=====================

To support the necessary semantics for argument passing, some new conversion
forms need to be supported by the language with special-cased lifetime behavior.

Interior Pointer Conversions
----------------------------

To be able to pass a pointer to array data as an argument, we need to be able
to guarantee the lifetime of the array buffer for the duration of the call.
If mutation can potentially occur through the pointer, then copy-on-write
buffers must also be uniqued prior to taking the address. A new form of
conversion, ``@unsafe_interior_pointer_conversion``, can be applied to an
instance method of a type, to allow that type to return both a converted
pointer and an owning reference that guarantees the validity of the pointer.
Such methods can be either ``mutating`` or non-mutating; only non-mutating
conversions are considered for non- ``inout`` parameters, and only ``mutating``
conversions are considered for ``inout`` parameters::

  extension Array {
    @unsafe_interior_pointer_conversion
    func convertToConstPointer()
    -> (CConstPointer<T>, ArrayBuffer<T>) {
      return (CConstPointer(self.base), self.owner)
    }

    @unsafe_interior_pointer_conversion
    mutating func convertToMutablePointer()
    -> (CMutablePointer<T>, ArrayBuffer<T>) {
      // Make the backing buffer unique before handing out a mutable pointer.
      self.makeUnique()
      return (CMutablePointer(self.base), self.owner)
    }
  }

``@unsafe_interior_pointer_conversion`` conversions are only considered in
argument contexts. If such a conversion is found, the first element of the
return tuple is used as the argument, and a strong reference to the second
element is held for the duration of the callee that receives the converted
argument.

Inout Address Conversion
------------------------

To pass an ``inout`` as a pointer argument, we need to be able to lock an
address for the ``inout`` for the duration of the call, which is not normally
possible. This functionality only needs to be available to the standard library,
so can be expressed in terms of builtins. A type can conform to the
``_BuiltinInOutAddressConvertible`` protocol to be convertible from an
inout reference. The protocol is defined as follows::

  protocol _BuiltinInOutAddressConvertible {
    /// The type from which inout conversions are allowed to the conforming
    /// type.
    typealias InOutType

    /// Create a value of the conforming type using the address of an inout
    /// argument.
    class func _convertFromInOutAddress(_ p: Builtin.RawPointer) -> Self
  }

An example of a conformance for ``CMutablePointer``::

  struct CMutablePointer<T>: _BuiltinInOutAddressConvertible {
    let ptr: Builtin.RawPointer

    typealias InOutType = T

    @_transparent
    static func _convertFromInOutAddress(_ p: Builtin.RawPointer)
    -> CMutablePointer {
      return CMutablePointer(p)
    }
  }

  func foo(_ p: CMutablePointer<Int>) { }

  var i = 0
  foo(&i)

The lifetime of the variable, stored property owning object, or writeback
buffer backing the inout is guaranteed for the lifetime of the callee that
receives the converted parameter, as if the callee had received the inout
parameter directly.

Inout Writeback Conversion
--------------------------

Inout address conversion alone is not enough for ``ObjCInOut`` to work as
intended, because the change to the ``__autoreleasing`` convention for the
pointed-to object reference requires a writeback temporary. The
``_BuiltinInOutWritebackConvertible`` protocol allows for an additional
writeback to be introduced before and after the address of the ``inout`` is
taken::

  protocol _BuiltinInOutWritebackConvertible {
    /// The original type from which inout conversions are allowed to the
    /// conforming type.
    typealias InOutType

    /// The type of the temporary writeback whose address is used to construct
    /// the converted value.
    typealias WritebackType

    /// Get the initial value the writeback temporary should have on entry to
    /// the call.
    class func _createWriteback(inout InOutType) -> WritebackType

    /// Create a value of the conforming type using the address of the writeback
    /// temporary.
    class func _convertFromWritebackAddress(_ p: Builtin.RawPointer) -> Self

    /// Write the writeback temporary back to the original value.
    class func _commitWriteback(inout InOutType, WritebackType)
  }

An example of a conformance for ``ObjCInOut``::

  struct ObjCInOut<T: class>: _BuiltinInOutWritebackConvertible {
    let ptr: Builtin.RawPointer

    typealias InOutType = T!
    typealias WritebackType = Builtin.RawPointer

    @_transparent
    static func _createWriteback(ref: inout T!)
    -> Builtin.RawPointer {
      // The initial object reference is passed into the callee effectively
      // __unsafe_unretained, so pass it as a RawPointer.
      return unsafeBitCast(ref, Builtin.RawPointer.self)
    }

    @_transparent
    static func _commitWriteback(ref: inout T!,
                                 value: Builtin.RawPointer) {
      // The reference is autoreleased on return from the caller, so retain it
      // by loading it back as a T?.
      ref = unsafeBitCast(value, T!.self)
    }

    @_transparent
    static func _convertFromWritebackAddress(_ value: Builtin.RawPointer) {
      return ObjCInOut(value)
    }
  }

The lifetime of the writeback is guaranteed for the lifetime of the callee that
receives the converted parameter, as if the callee had received the writeback
temporary as a mutable logical property of the original inout parameter.

