Nested functions and @ViewBuilder: strange compiler errors

The following code gives a strange compiler error that doesn't seem relevant:

struct ContentView: View {

    var body: some View {

        func world() -> String {
            "world"
        }

        Text("Hello, \(world())!")
    }
}

The error message is:

Closure containing a declaration cannot be used with result builder 'ViewBuilder'

Interestingly, if I add return in world() (i.e. return "world") the compiler shows an error elsewhere and also adds a warning, both not being very relevant either. This seems like a compiler bug more than anything else.

Any ideas what's going on?

I think it's telling you that nesting a function declaration directly in a result builder isn't supported.

You could try hoisting the definition of world() out of body, or change it to:

var world: () -> String = {
    "world"
}
1 Like

There's probably some workaround, but the error message ("Closure containing a declaration...") doesn't seem to be relevant, there's no closure containing a declaration here. Plus just adding return makes the compiler say something else completely and point elsewhere, it's why I thought it's a compiler bug.

Besides, why wouldn't nested functions be supported in ViewBuilders?

I suspect (but don't know for sure) that the misleading diagnostics are related to implementation details of result builders. I wouldn't be surprised, for example, if a closure is synthesized in the middle somewhere.

Result builders historically had some limitations on what syntax worked inside of them. Many of those limitations were removed in SE-0373: Lift all limitations on variables in result builders, but I wouldn't be surprised if some remain.

2 Likes