Skip to content

Commit 7c9e800

Browse files
committed
Pull request #81: Document that &foo gives you a pointer valid only during the function call
Merge in DP/swift-book from inout_pointer_61908259 to release/swift_5.3_e_beta_2
2 parents b0c732b + 7e23c04 commit 7c9e800

File tree

2 files changed

+130
-8
lines changed

2 files changed

+130
-8
lines changed

ReferenceManual/Declarations.rst

+8-1
Original file line numberDiff line numberDiff line change
@@ -792,14 +792,21 @@ see :doc:`../LanguageGuide/MemorySafety`.
792792
A closure or nested function
793793
that captures an in-out parameter must be nonescaping.
794794
If you need to capture an in-out parameter
795-
without mutating it or to observe changes made by other code,
795+
without mutating it,
796796
use a capture list to explicitly capture the parameter immutably.
797797

798798
.. testcode:: explicit-capture-for-inout
799799

800800
-> func someFunction(a: inout Int) -> () -> Int {
801801
return { [a] in return a + 1 }
802802
}
803+
>> class C { var x = 100 }
804+
>> let c = C()
805+
>> let f = someFunction(a: &c.x)
806+
>> c.x = 200
807+
>> let r = f()
808+
>> print(r, r == c.x)
809+
<< 101 false
803810

804811
If you need to capture and mutate an in-out parameter,
805812
use an explicit local copy,

ReferenceManual/Expressions.rst

+122-7
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,39 @@ see :doc:`../LanguageGuide/BasicOperators` and :doc:`../LanguageGuide/AdvancedOp
4141
For information about the operators provided by the Swift standard library,
4242
see `Operator Declarations <https://developer.apple.com/documentation/swift/operator_declarations>`_.
4343

44-
In addition to the standard library operators,
45-
you use ``&`` immediately before the name of a variable that's being passed
44+
.. syntax-grammar::
45+
46+
Grammar of a prefix expression
47+
48+
prefix-expression --> prefix-operator-OPT postfix-expression
49+
prefix-expression --> in-out-expression
50+
51+
52+
.. _Expressions_InOutExpression:
53+
54+
In-Out Expression
55+
~~~~~~~~~~~~~~~~~
56+
57+
An :newTerm:`in-out expression` marks a variable
58+
that's being passed
4659
as an in-out argument to a function call expression.
47-
For more information and to see an example,
60+
61+
.. syntax-outline::
62+
63+
&<#expression#>
64+
65+
For more information about in-out parameters and to see an example,
4866
see :ref:`Functions_InOutParameters`.
4967

50-
.. TODO: Need to a brief write up on the in-out-expression.
68+
In-out expressions are also used
69+
when providing a non-pointer argument
70+
in a context where a pointer is needed,
71+
as described in :ref:`Expressions_ImplicitConversion`.
5172

5273
.. syntax-grammar::
5374

54-
Grammar of a prefix expression
75+
Grammar of an in-out expression
5576

56-
prefix-expression --> prefix-operator-OPT postfix-expression
57-
prefix-expression --> in-out-expression
5877
in-out-expression --> ``&`` identifier
5978

6079

@@ -1762,6 +1781,102 @@ can enable syntactic sugar for function call syntax
17621781
by declaring one of several methods,
17631782
as described in :ref:`Declarations_SpecialFuncNames`.
17641783

1784+
.. _Expressions_ImplicitConversion:
1785+
1786+
Implicit Conversion to a Pointer Type
1787+
+++++++++++++++++++++++++++++++++++++
1788+
1789+
In a function call expression,
1790+
if the argument and parameter have a different type,
1791+
the compiler tries to make their types match
1792+
by applying one of the implicit conversions in the following list:
1793+
1794+
* ``inout SomeType`` can become
1795+
``UnsafePointer<SomeType>`` or ``UnsafeMutablePointer<SomeType>``
1796+
* ``inout Array<SomeType>`` can become
1797+
``UnsafePointer<SomeType>`` or ``UnsafeMutablePointer<SomeType>``
1798+
* ``Array<SomeType>`` can become ``UnsafePointer<SomeType>``
1799+
* ``String`` can become ``UnsafePointer<CChar>``
1800+
1801+
The following two function calls are equivalent:
1802+
1803+
.. testcode:: inout-unsafe-pointer
1804+
1805+
-> func unsafeFunction(pointer: UnsafePointer<Int>) {
1806+
-> // ...
1807+
>> print(pointer.pointee)
1808+
-> }
1809+
-> var myNumber = 1234
1810+
---
1811+
-> unsafeFunction(pointer: &myNumber)
1812+
-> withUnsafePointer(to: myNumber) { unsafeFunction(pointer: $0) }
1813+
<< 1234
1814+
<< 1234
1815+
1816+
A pointer that's created by these implicit conversions
1817+
is valid only for the duration of the function call.
1818+
To avoid undefined behavior,
1819+
ensure that your code
1820+
never persists the pointer after the function call ends.
1821+
1822+
.. note::
1823+
1824+
When implicitly converting an array to an unsafe pointer,
1825+
Swift ensures that the array's storage is contiguous
1826+
by converting or copying the array as needed.
1827+
For example, you can use this syntax
1828+
with an array that was bridged to ``Array``
1829+
from an ``NSArray`` subclass that makes no API contract about its storage.
1830+
If you need to guarantee that the array's storage is already contiguous,
1831+
so the implicit conversion never needs to do this work,
1832+
use ``ContiguousArray`` instead of ``Array``.
1833+
1834+
Using ``&`` instead of an explicit function like ``withUnsafePointer(to:)``
1835+
can help make calls to low-level C functions more readable,
1836+
especially when the function takes several pointer arguments.
1837+
However, when calling functions from other Swift code,
1838+
avoid using ``&`` instead of using the unsafe APIs explicitly.
1839+
1840+
.. assertion:: implicit-conversion-to-pointer
1841+
1842+
>> import Foundation
1843+
>> func takesUnsafePointer(p: UnsafePointer<Int>) { }
1844+
>> func takesUnsafeMutablePointer(p: UnsafeMutablePointer<Int>) { }
1845+
>> func takesUnsafePointerCChar(p: UnsafePointer<CChar>) { }
1846+
>> func takesUnsafeMutablePointerCChar(p: UnsafeMutablePointer<CChar>) { }
1847+
>> var n = 12
1848+
>> var array = [1, 2, 3]
1849+
>> var nsarray: NSArray = [10, 20, 30]
1850+
>> var bridgedNSArray = nsarray as! Array<Int>
1851+
>> var string = "Hello"
1852+
---
1853+
// bullet 1
1854+
>> takesUnsafePointer(p: &n)
1855+
>> takesUnsafeMutablePointer(p: &n)
1856+
---
1857+
// bullet 2
1858+
>> takesUnsafePointer(p: &array)
1859+
>> takesUnsafeMutablePointer(p: &array)
1860+
>> takesUnsafePointer(p: &bridgedNSArray)
1861+
>> takesUnsafeMutablePointer(p: &bridgedNSArray)
1862+
---
1863+
// bullet 3
1864+
>> takesUnsafePointer(p: array)
1865+
>> takesUnsafePointer(p: bridgedNSArray)
1866+
---
1867+
// bullet 4
1868+
>> takesUnsafePointerCChar(p: string)
1869+
---
1870+
// invailid conversions
1871+
>> takesUnsafeMutablePointer(p: array)
1872+
!$ error: cannot convert value of type '[Int]' to expected argument type 'UnsafeMutablePointer<Int>'
1873+
!! takesUnsafeMutablePointer(p: array)
1874+
!! ^
1875+
>> takesUnsafeMutablePointerCChar(p: string)
1876+
!$ error: cannot convert value of type 'String' to expected argument type 'UnsafeMutablePointer<CChar>' (aka 'UnsafeMutablePointer<Int8>')
1877+
!! takesUnsafeMutablePointerCChar(p: string)
1878+
!! ^
1879+
17651880
.. syntax-grammar::
17661881

17671882
Grammar of a function call expression

0 commit comments

Comments
 (0)