2
votes

I have an enum with an associated value of struct. When I write this code it compiles without error:

protocol MyProtocol {}

struct MyAssociatedValue: MyProtocol {}

enum MyEnum {
    case myCase(MyAssociatedValue)
}

func myEnumClosureMapping() -> (MyAssociatedValue) -> MyEnum {
    return MyEnum.myCase
}

But than I added another function like this:

func mySecondEnumClosureMapping() -> (MyProtocol) -> MyEnum {
    return MyEnum.myCase
}

Now I get a compiler error saying: Cannot convert return expression of type '(MyAssociatedValue) -> MyEnum' to return type '(MyProtocol) -> MyEnum'.

MyAssociatedValue struct conforms to MyProtocol protocol so this code should compile without errors. What might be the reason of compiler error?

1
Who says T is of type MyAssociatedValue? It could be any concrete type that conforms to MyProtocol. Let's say we conformed Int to MyProtocol, and called myGenericEnumClosureMapping with T of type Int (remember, it's the caller that decides the type of T, not the callee). If your code was allowed, we could then pass an Int to a MyAssociatedValue. - Hamish
I edited the question to use protocols instead. Still getting a compiler error. - Ceyhun Ozugur
The problem is the same – you can pass anything that conforms to MyProtocol into the returned function (like Int if we conformed it), but the associated value is of the specific type MyAssociatedValue. - Hamish
Note that if you make a force cast func myEnumClosureMapping() -> (MyProtocol) -> MyEnum { return MyEnum.myCase as! (MyProtocol) -> MyEnum } in both cases (generic and above) the compiler works fine. I think the problem is that @Hamish and @gnasher729 pointed, without the cast the compiler doesn't know what you're trying to pass it, can be anything and the type safe property of Swift doesn't allow it - Victor Sigler

1 Answers

1
votes

No, it shouldn't compile. The compiler expects a closure that can map anything supporting the MyProtocol protocol to a MyEnum. You are giving it a closure that can only map MyAssociatedValue to a MyEnum. If that closure was called with a MyProtocol that isn't a MyAssociatedValue, then the call would crash, therefore it isn't allowed.