Swift protocol extension constraint behavior is very strange

When I add a constraint extension to a protocol that has an associated type, the swift compiler ignores my constraint.

When I write:

protocol Arr {
    associatedtype Element

    func node(_ at: Int) -> Element?
}

extension Arr where Element == String {
    func node(_ at: Int) -> String? {
        nil
    }
}

struct Doo: Arr {
}

Xcode builds successfully and it thinks my Doo's Element is String. It ignores the where Element == String constraint.

When I write:

protocol Arr {
    associatedtype Element

    func node(_ at: Int) -> Element?
}

extension Arr where Element == String {
    func node(_ at: Int) -> Element? { // use Element
        nil
    }
}

struct Doo: Arr {
}

Xcode shows an error, as expected.

Is this an Xcode bug or a Swift feature?

Xcode version: Version 13.1 (13A1030d)

Swift version:

swift-driver version: 1.26.9 Apple Swift version 5.5.1 (swiftlang-1300.0.31.4 clang-1300.0.29.6)
Target: arm64-apple-macosx12.0

This look like the swift compiler add node function when I make Doo conform Arr protocol and then check the extension's constraint. This order is very strange, and add default a associated type String to Arr protocol unpectedly. And it is hard to find this reason, because the extension of protocol can be anywhere.

Why not change it to check constraint firstly and if Doo passed then add node function into it?

1 Like

As I recall, this is a known bug, but I don’t have the bug number ready at hand.