Confused with omitted return keyword in SwiftUI

Hi!

I have a question regarding omitting the return keyword in Swift. I'm aware that from Swift 5.1 it's possible to omit return from single expression closures, functions and computed properties, but I suddenly noticed that it also could be omitted in blocks with multiple expressions when using SwiftUI. This doesn't seem to be the case for regular computed properties though. I have a short example of what I mean below:

import SwiftUI

struct ContentView: View {
    var a: String {
        let s = "hello"
        return s // return is required here because of statement above
    }
    
    var body: some View {
        let b = "world"
        Text(a + " " + b) // return is optional here
    }
}

So I'm curious, how does this work and what language feature is Apple using to not require the return keyword in the blocks passed to the body property? :thinking:

That's a different feature. You see, View.body is defined with @ViewBuilder in the protocol declaration, so if the conformance lacks any return keyword, the compiler will assume that you're applying ViewBuilder to that body.

Though I'm not sure if omitting return or implicit result builder takes precedence when both applies.

For more information about result builder, which includes ViewBuilder, you can check out SE-0289.

3 Likes

Specifically, the feature is called a result builder, of which ViewBuilder is an example.

1 Like

Ah! I was thinking it maybe could have something to do with the ViewBuilder but couldn't quite understand how at first. I'll check it! Thanks for such a swift response (pun intended :wink:)!

The result builder pass will take precedence:

@resultBuilder
struct ExprCounter {
    static func buildBlock(_ exprs: Any...) -> Int {
        return exprs.count
    }
}

func countExprs(@ExprCounter _ f: () -> Int) {
    print(f())
}

countExprs {
    0
} // Prints "1"

Though you can disable the result builder behavior by adding explicit return:

countExprs {
    return 0
} // Prints "0"
4 Likes

Also, from the proposal:

return statements are ill-formed when they appear within a transformed function. However, note that the transformation is suppressed in closures that contain a return statement, so this rule is only applicable in func s and getters that explicitly provide the attribute.

1 Like

For this "implicit" result builder in particular, it's in the section Inferring Result Builder from Protocol Requirement of SE-289.

I missed that we can use constants in between now. :thinking: