Go Home Swift Compiler, You’re Drunk

Swift is approaching its two year anniversary. Thus far it has experienced high adoption and continues to grow as developers transition away from Objective-C. As a programming language, Swift is great. It feels productive to work in, and has a nice variety of modern language features.

After going through some changes, the language and platform seem to be stabilizing (ignoring some Swift 3 caveats). At this point, it would seem that the Swift development experience should be smooth sailing in open waters, not navigating through a maze of icebergs. For the most part, I think this is true. However, I have also run into some icebergs.

Consider the following code:

let myCompany = [
   "employees": [
        "employee 1": ["attribute": "value"],
        "employee 2": ["attribute": "value"],
        "employee 3": ["attribute": "value"],
        "employee 4": ["attribute": "value"],
        "employee 5": ["attribute": "value"],
        "employee 6": ["attribute": "value"],
        "employee 7": ["attribute": "value"],
        "employee 8": ["attribute": "value"],
        "employee 9": ["attribute": "value"],
        "employee 10": ["attribute": "value"],
        "employee 11": ["attribute": "value"],
        "employee 12": ["attribute": "value"],
        "employee 13": ["attribute": "value"],
        "employee 14": ["attribute": "value"],
        "employee 15": ["attribute": "value"],
        "employee 16": ["attribute": "value"],
        "employee 17": ["attribute": "value"],
        "employee 18": ["attribute": "value"],
        "employee 19": ["attribute": "value"],
        "employee 20": ["attribute": "value"],

Copy the above code into XCode, press “build,” and go get a coffee. Come back in 12 hours. Yes, the above dictionary literal code takes at least 12 hours to compile. The compilation time grows roughly exponentially with each employee that is added. The good news is that this bug was submitted in December. The bad news is that it hasn’t been fixed yet, and strange issues like these can creep into your codebase and cause egregiously long compile times.

I stumbled across this issue when I noticed that our unit tests were taking a suspiciously long time to build. Eventually, it became annoying, so I decided to investigate. I was able to narrow the problem down to a single unit test that by itself was taking minutes to compile. The test wasn’t doing anything strange, just defining a JSON structure that we were testing our ability to parse. After some poking around the code, and internet searches, I came across the above bug report. It made me wonder how many other unit tests or code snippets we had that might be contributing to a bloated compilation time.

Be aware of Swift’s inability to efficiently parse and compile simple Dictionary/Array literals, at least until the problem is fixed, and keep an eye open for other icebergs.

For folks that find this post in the future, I used Swift 2.2 and XCode 7.3 in the above example. The output of xcrun swift -version is

Apple Swift version 2.2 (swiftlang-703.0.18.1 clang-703.0.29)
Target: x86_64-apple-macosx10.9

For those interested, I put the project I used to test/reproduce this issue on my Github page.

Update: Big thanks to everyone for the interesting discussion here, on Reddit, and on Hacker News. I have learned a lot about the complexities of type inference. Per the discussion, the best way to work around this problem is to explicitly define types for the dictionary literal (as Brian describes below). It also looks like a fix has been submitted for this issue (see Joe's comment below). The commit message for the fix is awesome!