Cannot convert return expression of type 'Circle' to return type 'some Shape'

Why does the compiler throw this error for returnShapes2?

protocol Shape {}
struct Circle: Shape {  }
struct Rectangle: Shape {  }

func returnShapes() -> Shape { Bool.random() ? Circle() : Rectangle() }
// Error: Cannot convert return expression of type "Circle" to return type "some Shape"
func returnShapes2() -> some Shape { Bool.random() ? Circle() : Rectangle() }
func returnShapes3() -> some Shape { Circle() }

This is a restriction of opaque result types: while the caller does not see what the concrete return type of the method is, the method is still required to return only one type on all paths. In the case of returnShapes2, you may return either Circle or Rectangle, which are different concrete types. That is not allowed.

To do this you'd need to use type erasure via an AnyShape structure.

3 Likes

I see, I have to return AnyShape with Circle/Rectange

protocol Shape {
    associatedtype S
}
extension Shape {
    typealias S = Self
}

struct Circle: Shape { }
struct Rectangle: Shape {}

struct AnyShape: Shape  {
    init<S: Shape>(_ shape: S) { }
}

let shape = Bool.random() ? AnyShape(Circle()) : AnyShape(Rectangle())
1 Like

May I ask what's the purpose of doing this elaborate type setup?

It's probably related to this earlier question.

1 Like

I tried to figure out how to use the protocol, associate type and some keyword together.