1

Following playground-ready code ;)

protocol Prot {
    static func instanceArray() -> [Self]
}

struct A {
    init() {
        // Do something
    }
}

extension A: Prot {
    static func instanceArray() -> [A] {
        return [A(), A()]
    }
}

func work() -> [Prot] {
    return A.instanceArray()
}

The compiler will throw an error at return A.instanceArray(): Cannot convert return expression of type [A] to return type [Prot]

Why is the compiler not able to convert these types even though A implements the protocol Prot? I know that a workaround is to change the return type of instanceArray() to [Prot] but I don't really like this solution. Is this a compiler bug or a feature?

flashspys
  • 844
  • 9
  • 20

2 Answers2

2

There is a away to get around it if you must

func work() -> [Prot] {
    return A.instanceArray().map{ $0 as Prot }
}
DogCoffee
  • 19,820
  • 10
  • 87
  • 120
1

It will be easier to see what's going on if we eliminate all the extra stuff not needed in your example. So, consider this:

protocol Prot {}
struct A : Prot {}

let arr = [A(), A()] // 1: ok
let arr2 = [A(), A()] as [Prot] // 2: ok
let arr3 = arr as [Prot] // 3: compile error

The question is then, why is [2] legal but [3] is not? The difference is that we are allowed to form an array of A instances and type it as a [Prot], but we are not allowed to cast an existing array variable, already typed as [A], to a [Prot].

You can call this a bug or a limitation of Swift if you want to, and you would certainly be justified in a filing a bug report, but in any case it's a well-known shortcoming having to do with the fact that protocols are just not quite full-fledged types.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Well covered, I think, by Rob Napier's answer to my question here: http://stackoverflow.com/questions/33112559/protocol-doesnt-conform-to-itself – matt Dec 24 '15 at 20:04