| :orphan: |
| |
| We have a pretty good user model for C pointer interop now, but the language |
| model still needs improvement. Building the user model on top of implicit |
| conversions has a number of undesirable side effects. We end up with a mess of |
| pointer types--the intended user-facing, one-word pointer types |
| ``UnsafeMutablePointer`` and ``OpaquePointer``, which expose a full pointer-ish API |
| and are naturally ABI-compatible with C pointers; and the bridging pointer |
| types, ``ObjCMutablePointer``, ``CMutablePointer``, ``CConstPointer``, |
| ``CMutableVoidPointer``, and ``CConstVoidPointer``, which have no real API yet |
| but exist only to carry an owner reference and be implicitly convertible, and |
| rely on compiler magic to be passed to C functions. Since we can do the magic |
| pointer bridging only in limited places, we assault users writing method |
| overrides and reading synthesized headers with both sets of pointer types in a |
| confusing jumble. |
| |
| The best solution to this is to burn the user model into the language, giving |
| function applications special powers to provide the user model for pointers. We |
| then provide only one set of plain pointer types, with |
| special intrinsic behavior when used as function arguments. |
| |
| The Pointer Types |
| ================= |
| |
| In the standard library, we provide three pointer types: |
| |
| - ``UnsafePointer<T>``, corresponding to ``T const *`` in C and ARC, |
| - ``UnsafeMutablePointer<T>``, corresponding to ``T *`` in C, and ``T* __strong *`` in |
| ARC for class types, and |
| - ``AutoreleasingUnsafeMutablePointer<T>`` (for all ``T: AnyObject``), corresponding |
| to ``T* __autoreleasing *`` in ARC. |
| |
| These types are all one word, have no ownership semantics, and share a common |
| interface. ``UnsafePointer`` does not expose operations for storing to the |
| referenced memory. ``UnsafeMutablePointer`` and ``AutoreleasingUnsafeMutablePointer`` differ |
| in store behavior: ``UnsafeMutablePointer`` assumes that the pointed-to reference has |
| ownership semantics, so ``ptr.initialize(x)`` consumes a reference to ``x``, |
| and ``ptr.assign(x)`` releases the originally stored value before storing the |
| new value. ``AutoreleasingUnsafeMutablePointer`` assumes that the pointed-to |
| reference does not have ownership semantics, so values are autoreleased before |
| being stored by either initialize() or assign(), and no release is done on |
| reassignment. Loading from any of the three kinds of pointer does a strong |
| load, so there is no need for a separate ``AutoreleasingUnsafePointer``. |
| |
| Conversion behavior for pointer arguments |
| ========================================= |
| |
| The user model for pointer arguments becomes an inherent capability of function applications. The rules are: |
| |
| UnsafeMutablePointer<T> |
| ----------------------- |
| |
| When a function is declared as taking an ``UnsafeMutablePointer<T>`` argument, it can |
| accept any of the following: |
| |
| - ``nil``, which is passed as a null pointer, |
| - an ``UnsafeMutablePointer<T>`` value, which is passed verbatim, |
| - an inout expression whose operand is a stored lvalue of type ``T``, which is |
| passed as the address of the lvalue, or |
| - an inout ``Array<T>`` value, which is passed as a pointer to the start of the |
| array, and lifetime-extended for the duration of the callee. |
| |
| As a special case, when a function is declared as taking an |
| ``UnsafeMutableRawPointer`` argument, it can accept the same operands as |
| ``UnsafeMutablePointer<T>`` for any type T. |
| |
| So if you have a function declared:: |
| |
| func foo(_ x: UnsafeMutablePointer<Float>) |
| |
| You can call it as any of:: |
| |
| var x: Float = 0.0 |
| var p: UnsafeMutablePointer<Float> = nil |
| var a: [Float] = [1.0, 2.0, 3.0] |
| foo(nil) |
| foo(p) |
| foo(&x) |
| foo(&a) |
| |
| And if you have a function declared:: |
| |
| func bar(_ x: UnsafeMutableRawPointer) |
| |
| You can call it as any of:: |
| |
| var x: Float = 0.0, y: Int = 0 |
| var p: UnsafeMutablePointer<Float> = nil, q: UnsafeMutablePointer<Int> = nil |
| var a: [Float] = [1.0, 2.0, 3.0], b: Int = [1, 2, 3] |
| bar(nil) |
| bar(p) |
| bar(q) |
| bar(&x) |
| bar(&y) |
| bar(&a) |
| bar(&b) |
| |
| AutoreleasingUnsafeMutablePointer<T> |
| ------------------------------------ |
| |
| When a function is declared as taking an ``AutoreleasingUnsafeMutablePointer<T>``, it |
| can accept any of the following: |
| |
| - nil, which is passed as a null pointer, |
| - an ``AutoreleasingUnsafeMutablePointer<T>`` value, which is passed verbatim, or |
| - an inout expression, whose operand is primitive-copied to a temporary |
| nonowning buffer. The address of that buffer is passed to the callee, and on |
| return, the value in the buffer is loaded, retained, and reassigned into the |
| operand. |
| |
| Note that the above list does not include arrays, since implicit autoreleasing-to-strong writeback of an entire array would probably not be desirable. |
| |
| So if you have a function declared:: |
| |
| func bas(_ x: AutoreleasingUnsafeMutablePointer<NSBas?>) |
| |
| You can call it as any of:: |
| |
| var x: NSBas? |
| var p: AutoreleasingUnsafeMutablePointer<NSBas?> = nil |
| bas(nil) |
| bas(p) |
| bas(&x) |
| |
| UnsafePointer<T> |
| --------------------- |
| |
| When a function is declared as taking an ``UnsafeMutablePointer<T>`` argument, it can |
| accept any of the following: |
| |
| - nil, which is passed as a null pointer, |
| - an ``UnsafeMutablePointer<T>``, ``UnsafePointer<T>``, or |
| ``AutoreleasingUnsafeMutablePointer<T>`` value, which is converted to |
| ``UnsafePointer<T>`` if necessary and passed verbatim, |
| - an inout expression whose operand is an lvalue of type ``T``, which is passed |
| as the address of (the potentially temporary writeback buffer of) the lvalue, |
| or |
| - an ``Array<T>`` value, which is passed as a pointer to the start of the |
| array, and lifetime-extended for the duration of the callee. |
| |
| As a special case, when a function is declared as taking an |
| ``UnsafeRawPointer`` argument, it can accept the same operands as |
| ``UnsafePointer<T>`` for any type ``T``. Pointers to certain integer |
| types can furthermore interoperate with strings; see `Strings`_ below. |
| |
| So if you have a function declared:: |
| |
| func zim(_ x: UnsafePointer<Float>) |
| |
| You can call it as any of:: |
| |
| var x: Float = 0.0 |
| var p: UnsafePointer<Float> = nil |
| zim(nil) |
| zim(p) |
| zim(&x) |
| zim([1.0, 2.0, 3.0]) |
| |
| And if you have a function declared:: |
| |
| func zang(_ x: UnsafeRawPointer) |
| |
| You can call it as any of:: |
| |
| var x: Float = 0.0, y: Int = 0 |
| var p: UnsafePointer<Float> = nil, q: UnsafePointer<Int> = nil |
| zang(nil) |
| zang(p) |
| zang(q) |
| zang(&x) |
| zang(&y) |
| let doubles = [1.0, 2.0, 3.0] |
| let ints = [1, 2, 3] |
| zang(doubles) |
| zang(ints) |
| |
| A type checker limitation prevents array literals from being passed directly |
| to ``UnsafeRawPointer`` arguments without type annotation. As a |
| workaround, you can bind the array literal to a constant, as above, or |
| specify the array type with ``as``:: |
| |
| zang([1.0, 2.0, 3.0] as [Double]) |
| zang([1, 2, 3] as [Int]) |
| |
| This limitation is tracked as <rdar://problem/17444930>. |
| |
| Strings |
| ======= |
| |
| Pointers to the following C integer and character types can interoperate with |
| Swift ``String`` values and string literals: |
| |
| - ``CChar``, ``CSignedChar``, and ``CUnsignedChar``, which interoperate with |
| ``String`` as a UTF-8 code unit array; |
| - (not implemented yet) ``CShort``, ``CUnsignedShort``, and ``CChar16``, which interoperate with |
| ``String`` as a UTF-16 code unit array; and |
| - (not implemented yet) ``CInt``, ``CUnsignedInt``, ``CWideChar``, and ``CChar32``, which interoperate |
| with ``String`` as a UTF-32 code unit array. |
| |
| A ``UnsafePointer`` parameter with any of the above element types may take |
| a ``String`` value as an argument. The string is transcoded to a null-terminated |
| buffer of the appropriate encoding, if necessary, and a pointer to the buffer |
| is passed to the function. The callee may not mutate through the array, and |
| the referenced memory is only guaranteed to live for the duration of the call. |
| |