Exploring the Swift standard library source code

Have you found yourself stuck trying to make sense of a framework or library and wished you could see the source code? Apple does not share the source for UIKit but if the method you are struggling to understand is part of the Swift standard library you are in luck.

Accessing the GitHub repository

Apple publishes the source code for the Swift programming language, including the standard library, in a public GitHub repository:

You may find browsing the repository on GitHub is enough for a quick look but I like to clone and download a local copy:

$ mkdir swift-source
$ cd swift-source/
$ git clone https://github.com/apple/swift.git
Cloning into 'swift'...
remote: Enumerating objects: 915646, done.
remote: Total 915646 (delta 0), reused 0 (delta 0), pack-reused 915646
Receiving objects: 100% (915646/915646), 415.74 MiB | 6.42 MiB/s, done.
Resolving deltas: 100% (742664/742664), done.
Checking out files: 100% (16802/16802), done.

You can drop the swift folder into an Xcode project to browse, but that leaves my Mac with a spinning beach ball for several minutes. I prefer to open the folder with BBEdit, which is both faster and has better multi-file search tools.

Swift repo folder hierarchy

You’ll find the source for the standard library mostly in the core sub-directory:

$ cd swift/stdlib/public/core

It’s worth taking the time to browse the source code. I find it well documented and informative. Let’s see an example where the source code helps our understanding.

A question about String

I recently wrote about testing for empty strings in Swift. In that post, I claim you should use isEmpty rather than count to avoid iterating over the entire string. A reader asked me if that was true? My claim came from the String documentation:

To check whether a string is empty, use its isEmpty property instead of comparing the length of one of the views to 0. Unlike with isEmpty, calculating a view’s count property requires iterating through the elements of the string.

Can we do better than trust the documentation? Can we use the standard library source code to see how isEmpty and count work for strings?

StringCharacterView

It’s not always obvious where to look in the standard library source code. Searching the core directory will eventually lead you to the right place but can also take you down some rabbit holes. There is a String.swift file but it doesn’t contain either isEmpty or count.

Looking back at my Swift String cheat sheet you might remember that Swift 4 made the default view of a string a collection of characters. There is a StringCharacterView.swift file in the core directory which extends String to adopt the BidirectionalCollection protocol:

// StringCharacterView.swift
extension String: BidirectionalCollection {

The StringCharacterView doesn’t define isEmpty but we do find count:

public var count: Int {
  return distance(from: startIndex, to: endIndex)
}

The distance method calls through to an internal method which we still need to find, but it’s a start:

public func distance(from start: Index, to end: Index) -> IndexDistance {
  return _distance(from: start, to: end)
}

BidirectionalCollection

A bidirectional collection extends a collection to add backward traversal over the collection:

// BidirectionalCollection.swift
public protocol BidirectionalCollection: Collection
where SubSequence: BidirectionalCollection, Indices:
BidirectionalCollection {

This is where we find the implementation of _distance and can see it does iterate (forward or backward) over the collection:

internal func _distance(from start: Index, to end: Index) -> Int {
  var start = start
  var count = 0

  if start < end {
    while start != end {
      count += 1
      formIndex(after: &start)
    }
  }
  else if start > end {
    while start != end {
      count -= 1
      formIndex(before: &start)
    }
  }

  return count
}

Let’s keep going and see if we can find isEmpty.

Collection

The Collection protocol builds on Sequence and adds the startIndex and endIndex properties together with our friends isEmpty and count:

// Collection.swift (details omitted)
public protocol Collection: Sequence {

  var startIndex: Index { get }
  var endIndex: Index { get }

  var isEmpty: Bool { get }
  var count: Int { get }

The comments in the source code give us some more hints:

For collections that don’t conform to RandomAccessCollection, accessing the count property iterates through the elements of the collection.

and for count there is this warning:

Complexity: O(1) if the collection conforms to RandomAccessCollection; otherwise, O(n), where n is the length of the collection.

The comments confirm what we understood about String but also tell us why this is the case. What matters is whether the collection conforms to RandomAccessCollection. A type like Array allows for random access, but String does not. See RandomAccessCollection for the full list.

Further down the Collection.swift file we find a protocol extension which finally gives us the default implementation of isEmpty:

public var isEmpty: Bool {
  return startIndex == endIndex
}

So for a String, we are better off using isEmpty rather than count.

Try it yourself

I hope you were able to follow along. Digging into the source code has helped my understanding of how the basic types and protocols fit together. Give it a try the next time you have a question about the standard library.

Learn More

I recommend you watch the talk on Understanding the Standard Library by Paul Hudson. He has lots of helpful hints on navigating and understanding the source code: