Priority of protocol extensions with implicitly unwrapped optionals -- bug?

When using implicitly unwrapped optionals, the priority of protocol extensions seems to be wrong. Consider this example:

import SwiftUI

protocol SpecializedView: View {}

struct MyView: SpecializedView {
    var body: some View {
        EmptyView()
    }
}

extension View {
    var isSpecialized: Bool {
        false
    }
}

extension SpecializedView {
    var isSpecialized: Bool {
        true
    }
}

I've only been able to reproduce the issue with SwiftUI Views. This is a minimally working example that exhibits the behavior:

@main
struct ProtocolExtensions: App {
    var body: some Scene {
        WindowGroup {
            Button("Test") {
                let view1: MyView = MyView()
                let view2: MyView? = MyView()
                let view3: MyView! = MyView()

                print(view1.isSpecialized)  // true
                print(view2.isSpecialized)  // false  -> Why does this compile?
                print(view2!.isSpecialized) // true
                print(view3.isSpecialized)  // false
                print(view3!.isSpecialized) // true
            }
        }
    }
}

Is this a bug? I'm using Xcode 13.2.1

It's not written in the conformance list, but X? where X is a View is also a View. So you're using MyView? implementation of isSpecialized, which is the default implementation, i.e., false.

2 Likes

Hm, does that mean there is something like this in the SwiftUI framework?

extension Optional: View where Wrapped: View {
    var body: some View {
        Group {
            if let view = self {
                view
            } else {
                EmptyView()
            }
        }
    }
}
1 Like

Probably, it's kinda tricky to jump to conformance definition. So yea, that's essentially what happened, and that's why you see an alternating true/false.

2 Likes

Almost. The documentation tells us that Optional.Body == Never:

extension Optional: View where Wrapped: View {
  typealias Body = Never
  var body: some View { fatalError() }
}

So Optional is one of the built-in views whose body property can never produce a value. SwiftUI knows how to render these views "natively".

1 Like
Terms of Service

Privacy Policy

Cookie Policy