Thatâs correct, but only if youâre in a ViewBuilder context (or a result builder in general)! If you use return in your builder body, thatâll disable the result builder and turn it back into an ordinary function.
And for ordinary functions with an opaque result type, the use of if #available(...) allows SE-0360 Opaque result types with limited availability to kick in, which I think is what also happened in @teraâs workaround above.
Here are a few more examples to demonstrate how it all works (currently). In Example1, we have an implicit ViewBuilder where buildLimitedAvailability introduces AnyView to the opaque result type exactly as @CrystDragon said:
// Implicitly a ViewBuilder, returns _ConditionalContent<AnyView, Text>.
struct Example1: View {
/*@ViewBuilder*/ var body: some View {
if #available(iOS 26, *) {
Text("Hello").glassEffect()
} else {
Text("Hello")
}
}
}
But if we turn both branches to return their results in Example2, its body is no longer a ViewBuilder and the result type changes as well (into something I canât quite decipher from LLDB output, but I trust SE-0360 here):
// Returns an opaque result around the one type this consistently evaluates to.
struct Example2: View {
var body: some View {
if #available(iOS 26, *) {
return Text("Hello").glassEffect()
} else {
return Text("Hello")
}
}
}
The compiler remained silent about disabling the ViewBuilder above, but if we try to add it explicitly in Example3, weâll get a warning:
// warning: application of result builder 'ViewBuilder' disabled by explicit 'return' statement
struct Example3: View {
@ViewBuilder var body: some View {
if #available(iOS 26, *) {
return Text("Hello").glassEffect()
// ^
} else {
return Text("Hello")
}
}
}
Finally, even if you werenât in an explicit or implicit ViewBuilder body, you canât omit the return keyword because SE-0360 doesnât really interact with SE-0380 if and switch expressions any more than it did with SE-0289 Result builders.