tonisuter.comToni Suter's Bloghttps://tonisuter.com/2020-01-19T14:30:00+01:00Toni SuterUnderstanding Copy-on-write Value Types in Swifthttps://tonisuter.com/blog/2020/01/understanding-copy-on-write-value-types-swift/2020-01-19T14:30:00+01:002021-07-15T17:51:29+02:00Toni Suter<p>In Swift, the standard collection types like <code>Array<Element></code> and <code>String</code> are implemented as structs and have value semantics. So when you
assign an array to a new variable or pass it as an argument to a function, a copy of the array is created. Of course instances of these
collection types can be very large and contain thousands or even millions of elements. Thus, it would not be very efficient to perform a deep
copy of all the elements every time an array or a string is passed as an argument to a function. Swift uses <a href="https://en.wikipedia.org/wiki/Copy-on-write">copy-on-write</a>
to decide when a copy is really necessary in order to maintain value semantics.</p>
<p>The way this works is that each array instance internally has a reference that points to a buffer which contains the actual elements. When an
array is assigned to a new variable, Swift will only perform a shallow copy at first. At this point both instances of the array share a reference to the same
buffer. Once you start mutating one of the arrays (e.g., by appending or removing an element) Swift performs a deep copy and makes sure that both instances have
a separate buffer.</p>
<p>This blog post shows how Swift’s copy-on-write mechanism works in detail by implementing a <code>Stack<Element></code> value type. For the sake of simplicity, the type
has some serious limitations:</p>
<ul>
<li>Instances of <code>Stack<Element></code> have a fixed capacity</li>
<li><code>Stack<Element></code> doesn’t conform to any of Swift’s collection protocols</li>
<li><code>Stack<Element></code> doesn’t have a conditional conformance to <code>Equatable</code> or <code>Hashable</code></li>
</ul>
<p>Thus, this code should not be used in production. If you ever want or need to create a stack type, you should probably just wrap
a regular Swift array (or use the <code>Array<Element></code> directly).</p>
<p>That being said, let’s now have a look at how we can use the stack type.</p>
<h3>Step 1: Creating an instance of <code>Stack<Int></code></h3>
<div class="highlight"><pre class="highlight swift"><code><span class="kd">import</span> <span class="kt">Stack</span>
<span class="k">var</span> <span class="nv">stack1</span> <span class="o">=</span> <span class="kt">Stack</span><span class="o"><</span><span class="kt">Int</span><span class="o">></span><span class="p">(</span><span class="nv">capacity</span><span class="p">:</span> <span class="mi">5</span><span class="p">)</span>
<span class="n">stack1</span><span class="o">.</span><span class="nf">push</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
<span class="n">stack1</span><span class="o">.</span><span class="nf">push</span><span class="p">(</span><span class="mi">20</span><span class="p">)</span>
<span class="n">stack1</span><span class="o">.</span><span class="nf">push</span><span class="p">(</span><span class="mi">30</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"stack1: "</span><span class="p">,</span> <span class="n">stack1</span><span class="p">)</span> <span class="c1">// stack1: [10, 20, 30]</span>
</code></pre></div>
<p>The following image shows what <code>stack1</code> looks like in memory. It has a pointer to an instance of the <code>FixedSizeBuffer<Int></code> class which
manages a raw buffer via an <code>UnsafeMutablePointer<Int></code>. As you can see, the fixed-size buffer currently has a reference count of 1:</p>
<p><img src="/images/understanding-copy-on-write-value-types-swift/copy-on-write-step1.png">
<br/></p>
<h3>Step 2: Creating a copy of the stack instance</h3>
<p>We can create a copy of <code>stack1</code> by assigning it to a new variable:</p>
<div class="highlight"><pre class="highlight swift"><code><span class="k">var</span> <span class="nv">stack2</span> <span class="o">=</span> <span class="n">stack1</span> <span class="c1">// At this point, both stacks share the same buffer.</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"stack1: "</span><span class="p">,</span> <span class="n">stack1</span><span class="p">)</span> <span class="c1">// stack1: [10, 20, 30]</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"stack2: "</span><span class="p">,</span> <span class="n">stack2</span><span class="p">)</span> <span class="c1">// stack2: [10, 20, 30]</span>
</code></pre></div>
<p>As shown in the following image, both stacks now reference the same fixed-size buffer which therefore has a reference count of 2:</p>
<p><img src="/images/understanding-copy-on-write-value-types-swift/copy-on-write-step2.png">
<br/></p>
<h3>Step 3: Mutating one of the copies</h3>
<p>Finally, we pop an element from <code>stack2</code>:</p>
<div class="highlight"><pre class="highlight swift"><code><span class="n">stack2</span><span class="o">.</span><span class="nf">pop</span><span class="p">()</span> <span class="c1">// To maintain value semantics, stack2 clones the</span>
<span class="c1">// shared buffer before performing the pop() operation.</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"stack1: "</span><span class="p">,</span> <span class="n">stack1</span><span class="p">)</span> <span class="c1">// stack1: [10, 20, 30]</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"stack2: "</span><span class="p">,</span> <span class="n">stack2</span><span class="p">)</span> <span class="c1">// stack2: [10, 20]</span>
</code></pre></div>
<p>The <code>Stack<Element></code> type recognized that we are mutating a stack instance which shares its internal buffer with another stack instance.
Therefore, in order to preserve value semantics, it creates a deep copy of the fixed-size buffer before performing the mutation:</p>
<p><img src="/images/understanding-copy-on-write-value-types-swift/copy-on-write-step3.png">
<br/></p>
<h3>Implementation</h3>
<p>Let’s look at the implementation of the <code>Stack<Element></code> type. The key section of this code is the computed property <code>bufferForWriting</code>.
Whenever we want to mutate the stack, we access its internal fixed-size buffer via this property. It uses the built-in function
<a href="https://developer.apple.com/documentation/swift/2429905-isknownuniquelyreferenced"><code>isKnownUniquelyReferenced()</code></a> to test whether there
is only one stack instance that references the buffer. If the buffer is shared with another stack, a new copy of the buffer is created:</p>
<div class="highlight"><pre class="highlight swift"><code><span class="kd">public</span> <span class="kd">struct</span> <span class="kt">Stack</span><span class="o"><</span><span class="kt">Element</span><span class="o">></span><span class="p">:</span> <span class="kt">CustomStringConvertible</span> <span class="p">{</span>
<span class="k">var</span> <span class="nv">buffer</span><span class="p">:</span> <span class="kt">FixedSizeBuffer</span><span class="o"><</span><span class="kt">Element</span><span class="o">></span>
<span class="kd">public</span> <span class="nf">init</span><span class="p">(</span><span class="nv">capacity</span><span class="p">:</span> <span class="kt">Int</span><span class="p">)</span> <span class="p">{</span>
<span class="k">self</span><span class="o">.</span><span class="n">buffer</span> <span class="o">=</span> <span class="kt">FixedSizeBuffer</span><span class="p">(</span><span class="nv">capacity</span><span class="p">:</span> <span class="n">capacity</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">var</span> <span class="nv">bufferForWriting</span><span class="p">:</span> <span class="kt">FixedSizeBuffer</span><span class="o"><</span><span class="kt">Element</span><span class="o">></span> <span class="p">{</span>
<span class="k">mutating</span> <span class="k">get</span> <span class="p">{</span>
<span class="k">if</span> <span class="o">!</span><span class="nf">isKnownUniquelyReferenced</span><span class="p">(</span><span class="o">&</span><span class="n">buffer</span><span class="p">)</span> <span class="p">{</span>
<span class="n">buffer</span> <span class="o">=</span> <span class="kt">FixedSizeBuffer</span><span class="p">(</span><span class="nv">cloning</span><span class="p">:</span> <span class="n">buffer</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">buffer</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">public</span> <span class="k">var</span> <span class="nv">count</span><span class="p">:</span> <span class="kt">Int</span> <span class="p">{</span> <span class="n">buffer</span><span class="o">.</span><span class="n">count</span> <span class="p">}</span>
<span class="kd">public</span> <span class="k">var</span> <span class="nv">capacity</span><span class="p">:</span> <span class="kt">Int</span> <span class="p">{</span> <span class="n">buffer</span><span class="o">.</span><span class="n">capacity</span> <span class="p">}</span>
<span class="kd">public</span> <span class="k">var</span> <span class="nv">isEmpty</span><span class="p">:</span> <span class="kt">Bool</span> <span class="p">{</span> <span class="n">count</span> <span class="o">==</span> <span class="mi">0</span> <span class="p">}</span>
<span class="kd">public</span> <span class="k">mutating</span> <span class="kd">func</span> <span class="nf">push</span><span class="p">(</span><span class="n">_</span> <span class="nv">element</span><span class="p">:</span> <span class="kt">Element</span><span class="p">)</span> <span class="p">{</span>
<span class="nf">precondition</span><span class="p">(</span><span class="n">count</span> <span class="o"><</span> <span class="n">capacity</span><span class="p">,</span> <span class="s">"Can't push element onto a full stack"</span><span class="p">)</span>
<span class="n">bufferForWriting</span><span class="o">.</span><span class="nf">append</span><span class="p">(</span><span class="n">element</span><span class="p">)</span>
<span class="p">}</span>
<span class="kd">@discardableResult</span>
<span class="kd">public</span> <span class="k">mutating</span> <span class="kd">func</span> <span class="nf">pop</span><span class="p">()</span> <span class="o">-></span> <span class="kt">Element</span> <span class="p">{</span>
<span class="nf">precondition</span><span class="p">(</span><span class="o">!</span><span class="n">isEmpty</span><span class="p">,</span> <span class="s">"Can't pop last element from an empty stack"</span><span class="p">)</span>
<span class="k">return</span> <span class="n">bufferForWriting</span><span class="o">.</span><span class="nf">removeLast</span><span class="p">()</span>
<span class="p">}</span>
<span class="kd">public</span> <span class="kd">func</span> <span class="nf">peek</span><span class="p">()</span> <span class="o">-></span> <span class="kt">Element</span><span class="p">?</span> <span class="p">{</span>
<span class="k">guard</span> <span class="o">!</span><span class="n">isEmpty</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">return</span> <span class="kc">nil</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">buffer</span><span class="p">[</span><span class="n">count</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
<span class="p">}</span>
<span class="kd">public</span> <span class="k">var</span> <span class="nv">description</span><span class="p">:</span> <span class="kt">String</span> <span class="p">{</span>
<span class="k">var</span> <span class="nv">result</span> <span class="o">=</span> <span class="s">"["</span>
<span class="n">result</span> <span class="o">+=</span> <span class="p">(</span><span class="mi">0</span><span class="o">..<</span><span class="n">count</span><span class="p">)</span>
<span class="o">.</span><span class="n">map</span> <span class="p">{</span> <span class="kt">String</span><span class="p">(</span><span class="nv">reflecting</span><span class="p">:</span> <span class="n">buffer</span><span class="p">[</span><span class="nv">$0</span><span class="p">])</span> <span class="p">}</span>
<span class="o">.</span><span class="nf">joined</span><span class="p">(</span><span class="nv">separator</span><span class="p">:</span> <span class="s">", "</span><span class="p">)</span>
<span class="n">result</span> <span class="o">+=</span> <span class="s">"]"</span>
<span class="k">return</span> <span class="n">result</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<p>The <code>FixedSizeBuffer<Element></code> class is not shown here, but you can find the full source code plus a few unit tests on GitHub at the following
URL: <a href="https://github.com/tonisuter/COW-Stack">https://github.com/tonisuter/COW-Stack</a>.</p>
Unbounded Ranges in Swift 4https://tonisuter.com/blog/2017/08/unbounded-ranges-swift-4/2017-08-21T22:30:00+02:002021-07-15T17:51:29+02:00Toni Suter<p>In Swift, the expression <code>1...10</code> represents a closed range from 1 through 10. The <code>...</code> is an infix operator
that is declared in the standard library and the expression <code>1...10</code> applies the corresponding <code>...</code> operator
function to the operands 1 and 10. The value that results from this expression is an instance of the type
<code>CountableClosedRange<Int></code> which is also declared in the standard library. Additionally, Swift 4 adds one-sided
ranges to the standard library as described in proposal <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0172-one-sided-ranges.md">SE-172</a>.</p>
<p>However, recently I discovered that there is yet another kind of range in the Swift 4 standard library: the so-called <em>unbounded range</em>.
Here’s how you can use unbounded ranges:</p>
<div class="highlight"><pre class="highlight swift"><code><span class="k">let</span> <span class="nv">str1</span> <span class="o">=</span> <span class="s">"Example"</span>
<span class="k">let</span> <span class="nv">str2</span> <span class="o">=</span> <span class="n">str1</span><span class="p">[</span><span class="o">...</span><span class="p">]</span>
<span class="nf">print</span><span class="p">(</span><span class="n">str1</span><span class="p">,</span> <span class="nf">type</span><span class="p">(</span><span class="nv">of</span><span class="p">:</span> <span class="n">str1</span><span class="p">))</span> <span class="c1">// Example String</span>
<span class="nf">print</span><span class="p">(</span><span class="n">str2</span><span class="p">,</span> <span class="nf">type</span><span class="p">(</span><span class="nv">of</span><span class="p">:</span> <span class="n">str2</span><span class="p">))</span> <span class="c1">// Example Substring</span>
<span class="k">let</span> <span class="nv">arr1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
<span class="k">let</span> <span class="nv">arr2</span> <span class="o">=</span> <span class="n">arr1</span><span class="p">[</span><span class="o">...</span><span class="p">]</span>
<span class="nf">print</span><span class="p">(</span><span class="n">arr1</span><span class="p">,</span> <span class="nf">type</span><span class="p">(</span><span class="nv">of</span><span class="p">:</span> <span class="n">arr1</span><span class="p">))</span> <span class="c1">// [1, 2, 3] Array<Int></span>
<span class="nf">print</span><span class="p">(</span><span class="n">arr2</span><span class="p">,</span> <span class="nf">type</span><span class="p">(</span><span class="nv">of</span><span class="p">:</span> <span class="n">arr2</span><span class="p">))</span> <span class="c1">// [1, 2, 3] ArraySlice<Int></span>
</code></pre></div>
<p>When you pass an unbounded range to the subscript of any collection, you get back a subsequence that contains all elements of the original collection. Apparently, this is a useful thing to do in a few rare cases, but I am going to ignore that here, because I am more interested
in how this is implemented. </p>
<p>At first I thought that the Swift team must have added support for this in the Swift compiler, since it is not possible to declare
an operator that doesn’t take any operands. But after a little bit of digging, I realized that this can be implemented with Swift’s existing language features and doesn’t require any changes to the compiler. Here’s how it works.</p>
<p>In contrast to the other ranges, the expression <code>...</code> doesn’t actually call an operator function and doesn’t create an instance of some kind of range type. Instead it is just a reference to an operator function in the standard library. Here’s the declaration of that operator function (see <a href="https://github.com/apple/swift/blob/61ad3c07ef94bb9280b90833baefa95228cf031b/stdlib/public/core/Range.swift.gyb#L1170-L1174">Range.swift.gyb</a>):</p>
<div class="highlight"><pre class="highlight swift"><code><span class="kd">public</span> <span class="kd">enum</span> <span class="kt">UnboundedRange_</span> <span class="p">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="k">postfix</span> <span class="kd">func</span> <span class="o">...</span> <span class="p">(</span><span class="nv">_</span><span class="p">:</span> <span class="kt">UnboundedRange_</span><span class="p">)</span> <span class="o">-></span> <span class="p">()</span> <span class="p">{</span>
<span class="nf">fatalError</span><span class="p">(</span><span class="s">"uncallable"</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<p>As you can see, the operator function is declared as a static postfix operator function inside an enum type. However, those details don’t
really matter, because the function is uncallable. This is because, the enum <code>UnboundedRange_</code> is a so-called <em>uninhabited type</em>, which means that it is a type that doesn’t have any values. Therefore, we can’t create an instance of <code>UnboundedRange_</code> which would be required in order to call the <code>...</code> operator function. Instead, we can only reference the function. This function reference is then directly passed as an argument to the subscript. The following code shows how this subscript is implemented for types that adopt the <code>_Indexable</code> protocol (see <a href="https://github.com/apple/swift/blob/61ad3c07ef94bb9280b90833baefa95228cf031b/stdlib/public/core/Range.swift.gyb#L1175-L1188">Range.swift.gyb</a>):</p>
<div class="highlight"><pre class="highlight swift"><code><span class="kd">public</span> <span class="kd">typealias</span> <span class="kt">UnboundedRange</span> <span class="o">=</span> <span class="p">(</span><span class="kt">UnboundedRange_</span><span class="p">)</span><span class="o">-></span><span class="p">()</span>
<span class="kd">extension</span> <span class="n">_Indexable</span> <span class="p">{</span>
<span class="c1">// ...</span>
<span class="kd">@_inlineable</span>
<span class="kd">public</span> <span class="nf">subscript</span><span class="p">(</span><span class="nv">x</span><span class="p">:</span> <span class="kt">UnboundedRange</span><span class="p">)</span> <span class="o">-></span> <span class="kt">SubSequence</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">self</span><span class="p">[</span><span class="n">startIndex</span><span class="o">...</span><span class="p">]</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<p>There is a typealias called <code>UnboundedRange</code> which makes it easier to declare methods and subscripts that take an unbounded range as an argument. In the example above, there is not much we can do with the parameter <code>x</code> inside the body of the subscript since <code>x</code> is an uncallable function and doesn’t have any properties or methods. Thus, the implementation just delegates to another subscript, passing a one-sided range that covers the entire collection.</p>
Bi-directional Type Inference in Swifthttps://tonisuter.com/blog/2017/08/bi-directional-type-inference-swift/2017-08-06T16:00:00+02:002021-07-15T17:51:29+02:00Toni Suter<p>A few months ago, I noticed the following paragraph while reading <a href="https://github.com/apple/swift/blob/master/docs/TypeChecker.rst">Swift’s Type Checker documentation</a>:</p>
<blockquote>
<p>Swift’s type inference allows type information to flow in two directions. As in most mainstream languages, type information can flow from the leaves of the expression tree up to the root. However, Swift also allows type information to flow from the context at the root of the expression tree down to the leaves. This bi-directional type inference is common in languages that use ML-like type systems, but is not present in mainstream languages like C++, Java, C#, or Objective-C.</p>
</blockquote>
<p>At that time, I had never heard the term <em>bi-directional type inference</em> before. While I did know about certain language features (e.g., closures, implicit member expressions) that rely on this kind of type inference, I didn’t realize that it also impacts things like overload resolution.</p>
<p>In this blog post, I show a few examples of bottom-up type inference and top-down type inference which can be subsumed under the term bi-directional type inference. Knowing how Swift uses bi-directional type inference can give you a better understanding of its type system.</p>
<h3>Bottom-up Type Inference</h3>
<p>Bottom-up type inference is the kind of type inference where the type information flows from the bottom of the abstract syntax tree (AST) to the top. It is the more common kind of type inference and is used in many statically-typed
programming languages. The following code snippet shows a few examples of bottom-up type inference in Swift:</p>
<div class="highlight"><pre class="highlight swift"><code><span class="k">let</span> <span class="nv">age</span> <span class="o">=</span> <span class="mi">26</span> <span class="c1">// age is of type Int</span>
<span class="k">let</span> <span class="nv">name</span> <span class="o">=</span> <span class="s">"Toni"</span> <span class="c1">// name is of type String</span>
<span class="k">let</span> <span class="nv">pair</span> <span class="o">=</span> <span class="p">(</span><span class="n">age</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span> <span class="c1">// pair is of type (Int, String)</span>
</code></pre></div>
<p>The type of <code>pair</code> is inferred from its initial value <code>(age, name)</code>. The following picture shows the AST for that expression:</p>
<p><img src="/images/bi-directional-type-inference-swift/bottom-up-type-inference-ast.png" style="max-width: 60%" alt="AST for expression (age, name)" title="AST for expression (age, name)"></p>
<p>The type of each identifier expression is determined by performing a name lookup. For example, for the name <code>age</code>, the type checker finds a constant that has the type <code>Int</code>. Similarly, for the name <code>name</code> it finds a constant of type <code>String</code>. Finally, the type of the tuple expression at the root of the AST is a tuple type that is composed of the types of the two tuple elements, resulting in the type <code>(Int, String)</code>. Thus, the type information flows from the leaves of the tree up to the root.</p>
<p>With bottom-up type inference, leaf nodes have an intrinsic type. For example, integer literals default to the type <code>Int</code> and string literals default to the type <code>String</code> which is what happens when the compiler infers the types of the constants <code>age</code> and <code>name</code>. Similarly, an identifier expression references some entity (e.g., a variable or a function) that also has a type. </p>
<h3>Top-down Type Inference</h3>
<p>As mentioned above, Swift also allows type information to flow in the other direction; from top to bottom. This can be seen with various kinds of expressions such as literals, implicit member expressions, closures and function call expressions.</p>
<h4>Literals</h4>
<p>First, let’s look at Swift’s literals:</p>
<div class="highlight"><pre class="highlight swift"><code><span class="k">let</span> <span class="nv">x</span> <span class="o">=</span> <span class="mi">2</span> <span class="c1">// x is of type Int</span>
<span class="k">let</span> <span class="nv">y</span><span class="p">:</span> <span class="kt">Double</span> <span class="o">=</span> <span class="mi">2</span> <span class="c1">// y is of type Double</span>
</code></pre></div>
<p>This code illustrates that integer literals can be used to initialize constants / variables of type <code>Int</code> as well as ones that are of type <code>Double</code>. By default, an integer literal is of type <code>Int</code>. With an explicit type annotation we can change it to be of type <code>Double</code> instead.</p>
<p>The type annotation in a constant / variable declaration acts as a contextual type for the initial value. There are other language constructs where there is a contextual type for an expression, but I will talk about that in a different blog post. Integer literals can be used wherever the contextual type conforms to the <code>ExpressibleByIntegerLiteral</code> protocol. Types such as <code>Int</code>, <code>UInt</code>, <code>Double</code> and <code>Float</code> all conform to
this protocol.</p>
<p>Note that the above example only works, because an integer literal is not the same as an instance of type <code>Int</code>. In contrast, the following code does not compile, because <code>x</code> is an instance of type <code>Int</code> and there is no implicit conversion from <code>Int</code> to <code>Double</code>:</p>
<div class="highlight"><pre class="highlight swift"><code><span class="k">let</span> <span class="nv">x</span> <span class="o">=</span> <span class="mi">2</span> <span class="c1">// x is of type Int</span>
<span class="k">let</span> <span class="nv">y</span><span class="p">:</span> <span class="kt">Double</span> <span class="o">=</span> <span class="n">x</span> <span class="c1">// error: cannot convert value of type 'Int' to specified type 'Double'</span>
</code></pre></div>
<p>If we really wanted to convert <code>x</code> into a <code>Double</code>, we would have to write <code>let y = Double(x)</code> in order to explicitly convert it by calling one of <code>Double</code>‘s initializers.</p>
<p>Other literals work in the same vein. For example, array literals default to the type <code>Array<T></code> but they can also be used to initialize constants / variables of type <code>Set<T></code> because the type <code>Set</code> conforms to the <code>ExpressibleByArrayLiteral</code> protocol:</p>
<div class="highlight"><pre class="highlight swift"><code><span class="k">let</span> <span class="nv">arr</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span> <span class="c1">// arr is of type Array<Int></span>
<span class="k">let</span> <span class="nv">set</span><span class="p">:</span> <span class="kt">Set</span><span class="o"><</span><span class="kt">Int</span><span class="o">></span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span> <span class="c1">// set is of type Set<Int></span>
</code></pre></div>
<h4>Implicit Member Expressions</h4>
<p>Implicit member expressions are often used to abbreviate references to enum cases, when the enum type is known from the context:</p>
<div class="highlight"><pre class="highlight swift"><code><span class="kd">enum</span> <span class="kt">Season</span> <span class="p">{</span>
<span class="k">case</span> <span class="n">spring</span>
<span class="k">case</span> <span class="n">summer</span>
<span class="k">case</span> <span class="n">fall</span>
<span class="k">case</span> <span class="n">winter</span>
<span class="p">}</span>
<span class="k">var</span> <span class="nv">season</span> <span class="o">=</span> <span class="kt">Season</span><span class="o">.</span><span class="n">summer</span> <span class="c1">// season is of type Season</span>
<span class="n">season</span> <span class="o">=</span> <span class="o">.</span><span class="n">fall</span>
</code></pre></div>
<p>In this example, the variable <code>season</code> is first initialized with the explicit member expression <code>Season.summer</code>, which means that its inferred type is <code>Season</code>. Since the variable <code>season</code> now has a fixed type, we can use the implicit member expression <code>.fall</code> to change its value. In other words, the type of the variable acts as a contextual type for the expression <code>.fall</code>.</p>
<h4>Closures</h4>
<p>Closures are another one of Swift’s language features that heavily relies on top-down type inference. The parameter types and return types of closures are often not specified explicitly but instead inferred from the closure’s context:</p>
<div class="highlight"><pre class="highlight swift"><code><span class="k">let</span> <span class="nv">numbers</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span> <span class="c1">// numbers is of type Array<Int></span>
<span class="k">let</span> <span class="nv">positiveNumbers</span> <span class="o">=</span> <span class="n">numbers</span><span class="o">.</span><span class="n">filter</span> <span class="p">{</span> <span class="n">n</span> <span class="k">in</span> <span class="n">n</span> <span class="o">>=</span> <span class="mi">0</span> <span class="p">}</span>
<span class="nf">print</span><span class="p">(</span><span class="n">positiveNumbers</span><span class="p">)</span> <span class="c1">// [1, 3]</span>
</code></pre></div>
<p>In this example, the <code>filter()</code> method expects a single argument of type <code>(Int) -> Bool</code>. This is also the contextual type for the closure that is passed as argument, which in turn means that the inferred type for <code>n</code> is <code>Int</code>.</p>
<p>Let’s change this example a little bit by using floating point literals instead of integer literals in the initial value of the constant <code>numbers</code>:</p>
<div class="highlight"><pre class="highlight swift"><code><span class="k">let</span> <span class="nv">numbers</span> <span class="o">=</span> <span class="p">[</span><span class="mf">1.0</span><span class="p">,</span> <span class="o">-</span><span class="mf">2.0</span><span class="p">,</span> <span class="mf">3.0</span><span class="p">]</span> <span class="c1">// numbers is of type Array<Double></span>
<span class="k">let</span> <span class="nv">positiveNumbers</span> <span class="o">=</span> <span class="n">numbers</span><span class="o">.</span><span class="n">filter</span> <span class="p">{</span> <span class="n">n</span> <span class="k">in</span> <span class="n">n</span> <span class="o">>=</span> <span class="mi">0</span> <span class="p">}</span>
<span class="nf">print</span><span class="p">(</span><span class="n">positiveNumbers</span><span class="p">)</span> <span class="c1">// [1.0, 3.0]</span>
</code></pre></div>
<p>Now the inferred type of <code>numbers</code> is <code>Array<Double></code> instead of <code>Array<Int></code> which also means that the <code>filter()</code> method now expects an argument of type <code>(Double) -> Bool</code>. Additionally, the type of <code>n</code> has changed to <code>Double</code> as well.</p>
<h4>Overload Resolution</h4>
<p>In Swift, functions can be overloaded. At compile time, the type checker needs to determine, which of the overloads is called in a particular function call. In contrast to many other programming languages, overload resolution in Swift not only depends on the argument types but also on the contextual type of a function call:</p>
<div class="highlight"><pre class="highlight swift"><code><span class="kd">func</span> <span class="nf">f</span><span class="p">()</span> <span class="o">-></span> <span class="kt">Int</span> <span class="p">{</span>
<span class="k">return</span> <span class="mi">2</span>
<span class="p">}</span>
<span class="kd">func</span> <span class="nf">f</span><span class="p">()</span> <span class="o">-></span> <span class="kt">String</span> <span class="p">{</span>
<span class="k">return</span> <span class="s">"test"</span>
<span class="p">}</span>
<span class="k">let</span> <span class="nv">x</span> <span class="o">=</span> <span class="nf">f</span><span class="p">()</span> <span class="c1">// error: ambiguous use of 'f()'</span>
<span class="k">let</span> <span class="nv">y</span><span class="p">:</span> <span class="kt">Int</span> <span class="o">=</span> <span class="nf">f</span><span class="p">()</span> <span class="c1">// Overload Resolution picks f: () -> Int</span>
<span class="k">let</span> <span class="nv">z</span><span class="p">:</span> <span class="kt">String</span> <span class="o">=</span> <span class="nf">f</span><span class="p">()</span> <span class="c1">// Overload Resolution picks f: () -> String</span>
</code></pre></div>
<p>In the declaration of <code>x</code> there is no contextual type, which makes the function call <code>f()</code> ambiguous, because the type checker doesn’t know which overload to pick. In the declarations of <code>y</code> and <code>z</code> there is an explicit type annotation, which allows the type checker to choose the correct overload with the matching return type. Note that in many programming languages it is not possible to declare two functions that only differ in their return type.</p>
<p>This kind of top-down type inference works through multiple levels of indirection as shown in the following example:</p>
<div class="highlight"><pre class="highlight swift"><code><span class="kd">func</span> <span class="nf">f</span><span class="p">()</span> <span class="o">-></span> <span class="kt">Int</span> <span class="p">{</span>
<span class="k">return</span> <span class="mi">2</span>
<span class="p">}</span>
<span class="kd">func</span> <span class="nf">f</span><span class="p">()</span> <span class="o">-></span> <span class="kt">String</span> <span class="p">{</span>
<span class="k">return</span> <span class="s">"test"</span>
<span class="p">}</span>
<span class="kd">func</span> <span class="n">id</span><span class="o"><</span><span class="kt">T</span><span class="o">></span><span class="p">(</span><span class="n">_</span> <span class="nv">value</span><span class="p">:</span> <span class="kt">T</span><span class="p">)</span> <span class="o">-></span> <span class="kt">T</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">value</span>
<span class="p">}</span>
<span class="k">let</span> <span class="nv">x</span> <span class="o">=</span> <span class="nf">id</span><span class="p">(</span><span class="nf">id</span><span class="p">(</span><span class="nf">f</span><span class="p">()))</span> <span class="c1">// error: ambiguous use of 'f()'</span>
<span class="k">let</span> <span class="nv">y</span><span class="p">:</span> <span class="kt">Int</span> <span class="o">=</span> <span class="nf">id</span><span class="p">(</span><span class="nf">id</span><span class="p">(</span><span class="nf">f</span><span class="p">()))</span> <span class="c1">// Overload Resolution picks f: () -> Int</span>
<span class="k">let</span> <span class="nv">z</span><span class="p">:</span> <span class="kt">String</span> <span class="o">=</span> <span class="nf">id</span><span class="p">(</span><span class="nf">id</span><span class="p">(</span><span class="nf">f</span><span class="p">()))</span> <span class="c1">// Overload Resolution picks f: () -> String</span>
</code></pre></div>
<p>Here the result of the function call <code>f()</code> is passed through two invocations of the generic identity function <code>id()</code>. The declaration of <code>x</code> is still ambiguous, since there is no explicit type annotation. For the constants <code>y</code> and <code>z</code> the explicit type annotation determines the type that should be used as the argument for the generic parameter <code>T</code> of the outer <code>id()</code> call. The generic parameter <code>T</code> of the outer <code>id()</code> call is then used as the argument for the generic parameter <code>T</code> of the inner <code>id()</code> call. Finally, the generic parameter <code>T</code> of the inner <code>id()</code> call constrains the call to <code>f()</code> and allows the type checker to choose the correct overload with the matching return type.</p>
<h3>Conclusion</h3>
<p>This blog post has shown several examples of bottom-up and top-down type inference. Swift’s type checker uses a constraint-based system to implement this kind of bi-directional type inference. I will write more about these implementation details in future blog posts.</p>