Clang just added a new section to its Internals manual on the "immutability" and "faithfulness" of its AST nodes. I wanted to bring up (with no particular urgency) whether Swift should have something similar. So far, he Swift AST has followed the "faithfulness" part pretty well, but because of the separate parsing and type-checking phases (or "semantic checking", if you prefer) it's pretty mutable.
We've had thoughts before about making the AST less mutable in various ways, one of the reasons being because it makes it easier to do live-editing tricks like incremental type-checking, where you throw out just the types that could have been touched by a change. It can also make circularity issues much easier to catch, although the request evaluator is doing that too. On the flip side, though, we've seen evidence that accessing fields of AST nodes is noticeably faster than looking them up in a map—this was tested with Clang nodes, which are allocated at offset -1 now but used to be in a global map on the ASTContext.
But wait. The Swift AST has done fairly well on the faithfulness front…but still wasn't enough to perfectly recreate the original source; instead, we now have SwiftSyntax for that. So some people (mostly not me) have also talked about building ASTs from SwiftSyntax nodes, and maintaining a link back for the source information. If we do go down that path, we'd have to be careful to not slow down compilation, but it would also allow dropping information from AST nodes that would be redundant with the syntax nodes.
I mostly wanted to bring this up so people could read the Clang change. But it seems like there's a good chance "immutable + faithful" isn't the place to end up for Swift's AST. Thoughts?
(And yes, this is sort of another IR: Syntax -> AST -> SIL -> LLVM IR -> LLVM MC -> assembly. That's compilers for you…but it also means being careful about perf.)