The Swift compiler is slow due to how types are inferred
Swift’s powerful type inference and operator overloading are blamed for severe compile-time slowdowns, with seemingly simple expressions triggering combinatorial explosions in the type checker. Commenters debate whether this is an inherent consequence of Swift’s expressive type system or a fixable design and tooling problem, comparing it to faster languages like Haskell, OCaml, Rust, Kotlin, Dart, and Go. The thread also questions Apple’s long‑term priorities for Swift, noting regressions in compiler performance, the impact of newer features like macros and SwiftUI, and the lack of strong cross‑platform tooling.
Root causes of Swift compile slowness
- Main pain point: type checking of complex expressions, especially when literals, operator overloading, generics, and protocol conformances interact.
- The compiler must consider many combinations of overloads and literal types (e.g.,
+with many candidates, multipleExpressibleBy…Literaladopters), causing combinatorial explosions even in small expressions. - Some examples show invalid code taking ~40 seconds just to produce a type error, suggesting exponential behavior and possibly additional algorithmic/path/implementation issues.
Type system and inference debates
- Several comments stress that the core issue is not “type inference” per se, but Swift’s mix of:
- Ad-hoc polymorphism via overloads.
- Subtyping.
- Very flexible literal typing.
- Comparisons are made to SAT/NP-complete/EXPTIME-hard problems; SAT solvers are mentioned as powerful but too unpredictable for compilers.
- Others argue this is partly self‑inflicted: aggressive operator overloading and many overloads for the same names create huge search spaces.
- Some suggest Swift’s understanding of “bidirectional type checking” is muddled; bidirectional systems can in principle improve performance if designed carefully.
Comparisons to other languages
- Haskell/OCaml/ML-style systems are cited as having powerful yet fast inference because they avoid subtyping and/or heavy ad‑hoc overloading.
- Demonstrations show Haskell handling similarly overloaded-looking code quickly, though pathological cases with gigantic inferred types still exist.
- Rust and Swift both forbid implicit numeric widening (e.g.,
Int * Doublerequires explicit conversion), but Rust is seen as getting more predictable inference and better error messages. - Scala is mentioned as doing similar inference “a lot faster,” implying Swift’s performance is not theoretically inevitable.
Apple tooling, priorities, and ecosystem
- Some believe Apple’s developer tools org is under-resourced, causing a cycle: visible performance fixes around WWDC, then regressions as new features land.
- Explicit modules are cited as an example where promised compile-time wins turn into regressions for some projects.
- Others counter that Apple is investing in systemic fixes and that recent WWDCs show progress, so blanket “Apple doesn’t care” claims are seen as overstated.
Mitigations and alternative approaches
- Practical advice discussed:
- Add explicit types or casts in “hot” expressions.
- Break large expressions into smaller sub-expressions.
- Limit or avoid clever operator overloading.
- Ideas for compiler behavior:
- Early bail-out or warnings when it leaves a “fast path” and enters expensive search.
- Incremental/incrementally cached type checking on ASTs.
- Tools/CI that surface the worst offending expressions to encourage cleanup.
- Some suggest more radical design changes (stricter overloading rules, fewer implicit literal types) but acknowledge these would be source-breaking.