What techniques are there for figuring out errors with result builders? I'm working on a somewhat complex one using buildPartialBlock to enforce elements appearing in a certain order, and at the moment I'm having trouble with how that interacts with buildOptional. I anticipate running into more such issues as I flesh it out, so I'm looking for general result-builder-debugging pointers.
It's tricky because the compiler errors are based on the behind-the-scenes generated code, rather than on the code I'm looking at. Is it possible to see that generated code? Or does the compiler not quite work that way?
At the moment, I have an error right at the beginning of the call to the result builder saying "type of expression is ambiguous without more context". Right back at you, says I
As far as I know, there’s no way to see what’s generated. I spent a fair amount of time referring back to Becca Dax’s WWDC video (the visuals do a wonderful job of showing what gets generated).
There’s definitely a pattern to it that makes sense after a bit of time, but it took me some
time and experimentation to get the hang of how all the pieces hang together - and how to structure code to work with it.
Try using -print-ast flag passed to swiftc, courtesy of @LouisD and @hamishknight.
Assuming your builders.swift contains this
import SwiftUI
struct V: View {
var body: some View {
HStack {
Text("test1")
Text("test2")
}
}
}
then swiftc -print-ast builders.swift will output this
import SwiftUI
internal struct V : View {
@MainActor internal var body: some View {
get {
private var $__builder1: HStack<TupleView<(Text, Text)>>
private var $__builder0: HStack<TupleView<(Text, Text)>> = HStack<TupleView<(Text, Text)>>()
$__builder1 = ViewBuilder.buildBlock($__builder0)
return $__builder1
}
}
internal typealias Body = some View
internal init() {
}
}
As you can see, it applies substitutions for typealiases as well. This also works for checking what Codable, Hashable, and Equatable conformances were synthesized.
swift -print-ast unfortunately isn't working for me. The first problem is that it only prints the result if the processed result builder code actually compiles, and my issue is that often it doesn't compile and I'm trying to figure out why, which is why I want to see the code.
The other problem is that, once I got it compiling, it doesn't even print the result builder code anyway. For example, it turned this:
let c1 = Context("examples only") {
It("does the thing") {}
It("does the thing") {}
}
into simply this:
@_hasInitialValue internal let c1: Context = Context("examples only", )
Is there something else I missed to get this to work?