Can't override resultBuilder

I try to add a custom ViewBuilder to replace SwiftUI.ViewBuilder, but my custom ViewBuilder won't trigger it, here's my code, I have copied all the functions from ViewBuilder:


@resultBuilder public struct ObservableViewBuilder {

    /// Builds an expression within the builder.
    public static func buildExpression<Content>(_ content: Content) -> Content where Content : View {
        content
    }

    /// Builds an empty view from a block containing no statements.
    public static func buildBlock() -> EmptyView {
        EmptyView()
    }
    /// Passes a single view written as a child view through unmodified.
    ///
    /// An example of a single view written as a child view is
    /// `{ Text("Hello") }`.
    public static func buildBlock<Content>(_ content: Content) -> Content where Content : View {
        content
    }

    public static func buildBlock<each Content>(_ content: repeat each Content) -> TupleView<(repeat each Content)> where repeat each Content : View {
        TupleView((repeat each content))
    }

    /// Provides support for “if” statements in multi-statement closures,
    /// producing an optional view that is visible only when the condition
    /// evaluates to `true`.
    public static func buildIf<Content>(_ content: Content?) -> Content? where Content : View {
        content
    }

    /// Provides support for "if" statements in multi-statement closures,
    /// producing conditional content for the "then" branch.
    public static func buildEither<TrueContent, FalseContent>(first: TrueContent) -> _ConditionalContent<TrueContent, FalseContent> where TrueContent : View, FalseContent : View {
        ViewBuilder.buildEither(first: first)
    }

    /// Provides support for "if-else" statements in multi-statement closures,
    /// producing conditional content for the "else" branch.
    public static func buildEither<TrueContent, FalseContent>(second: FalseContent) -> _ConditionalContent<TrueContent, FalseContent> where TrueContent : View, FalseContent : View {

        ViewBuilder.buildEither(second: second)
    }

    /// Provides support for "if" statements with `#available()` clauses in
    /// multi-statement closures, producing conditional content for the "then"
    /// branch, i.e. the conditionally-available branch.
    public static func buildLimitedAvailability<Content>(_ content: Content) -> AnyView where Content : View {
        ViewBuilder.buildLimitedAvailability(content)
    }
}

struct ContentView: View {
    @ObservableViewBuilder
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .padding()
    }
}

It's only triggered if I add ObservableViewBuilder to another property, and then call this new one in body.

Is this a bug?

The body property is marked with @ViewBuilder in the protocol, so you might just be required to use it:

@ViewBuilder var body: Body { get }
associatedtype Body: View

But @ViewBuilder in Protocol is not mandatory, for example, the compiler disables @ViewBuilder in this code:

var body: some View {
    print("")
    return EmptyView()
}

So It looks like a bug to me.

I just ran into this issue as well. I opened a bug on the Swift Github repo with non-SwiftUI specific instance of the issue: Wrong result builder used if protocol and conformance apply different result builders · Issue #70078 · apple/swift · GitHub