title: Swift Type Checking Takes Too Long on Very Short Function
body: <p>I have set the Swift compiler flag <code>-warn-long-function-bodies</code> to 90 milliseconds, to see which functions in my project are taking too long to compile (due to type checking).</p>
  
  <p>I have the following method:</p>
  
  <pre><code>func someKey(_ sectionType: SectionType, row: Int) -&gt; String {
      let suffix = row == 0 ? "top" : "content"
      return "\(sectionType)_\(suffix)"
  }
  </code></pre>
  
  <p><em>(<code>SectionType</code> is an String-backed enum)</em></p>
  
  <p>As it is above, it takes <strong>96ms</strong> on a 2017 MacBook Pro. The first thing I tried is to circumvent string interpolation and use <code>\(sectionType.rawValue)</code> instead of <code>\(sectionType)</code>, but now it gives me <strong>106 ms</strong>. Wrong move...</p>
  
  <p>Next, I changed:</p>
  
  <pre><code>let suffix = row == 0 ? "top" : "content"
  </code></pre>
  
  <p>to:</p>
  
  <pre><code>let suffix = "top"
  </code></pre>
  
  <p>The warning goes away, so it is the ternary operator that is causing trouble. </p>
  
  <p>I tried this instead:</p>
  
  <pre><code>let suffix: String = { // Note the type annotation!
      if row == 0 {
          return "top"
      }
      return "content"
  }()
  </code></pre>
  
  <p>...but now it is the <em>closure</em> that takes 97 ms (the whole function, 101).</p>
  
  <p>I even tried the more explicit:</p>
  
  <pre><code>    let suffix: String = {
          if row == 0 {
              return String("top")
          } else {
              return String("content")
          }
      }()
  </code></pre>
  
  <p>...and I get closure: 94ms; function: 98ms.</p>
  
  <p><strong>What's going on?</strong> </p>
  
  <p>Is my 90-milliseconds limit too low? I know there was (is?) a type-checking bug with <strong>dictionary</strong> literals, but this seems something entirely different...?  </p>
  
  <p>My environment is Xcode 8.3.2 (8E2002), 
  Swift: <code>Apple Swift version 3.1 (swiftlang-802.0.53 clang-802.0.42)</code></p>
  
  <hr>
  
  <p><strong>But Wait! There's more...</strong></p>
  
  <p>I tried this function body:</p>
  
  <pre><code>func someKey(_ sectionType: SectionType, row: Int) -&gt; String {
      if row == 0 {
          return "\(sectionType.rawValue)_top"
      } else {
          return "\(sectionType.rawValue)_content"
      }
  }
  </code></pre>
  
  <p>...and it takes 97ms~112ms!?</p>
  
  <hr>
  
  <p><strong>Addendum:</strong> I transplanted the function and enum to a clean, minimal project (Single View Application) set up the same warning but it does not happen. I'm sure the project as a whole is affecting this one method somehow, but can't quite figure how yet...</p>
  
  <hr>
  
  <p><strong>Addendum 2</strong>: I tested the static version of my function: use fixed suffix "top" regardless of the value of <code>row</code>(this takes less than 90 ms and triggers no warning), <strong>but</strong> added the following <code>if</code> block:</p>
  
  <pre><code>func someKey(_ sectionType: SectionType, row: Int) -&gt; String {
      if row == 0 {
          print("zero")
      } else {
          print("non-zero")
      }
  
      let suffix: String = "top"
      return "\(sectionType)_\(suffix)"
  }
  </code></pre>
  
  <p>This takes me back to 96~98 ms! <strong>So the problem arises when comparing row to zero?</strong></p>
  
  <hr>
  
  <p><strong>Workaround:</strong> I kept playing with my code and somehow discovered that if I replace the <code>if</code> block with a <code>switch</code> statement, the issue goes away:</p>
  
  <pre><code>func someKey(_ sectionType: SectionType, row: Int) -&gt; String {
      let suffix: String = {
          switch row {
          case 0:
              return "top"
          default:
              return "content"
          }
      }()
      return "\(sectionType)_\(suffix)"
  }
  </code></pre>
  
  <p>(I won't answer my own question because I do not consider this an explanation of what's really going on)</p>