Swift 3:将具有关联值的枚举大小写转换为具有协议参数的闭包会导致编译器错误

Swift 3:将具有关联值的枚举大小写转换为具有协议参数的闭包会导致编译器错误,swift,enums,swift3,protocols,Swift,Enums,Swift3,Protocols,我有一个关联值为struct的枚举。当我编写此代码时,它编译时不会出错: protocol MyProtocol {} struct MyAssociatedValue: MyProtocol {} enum MyEnum { case myCase(MyAssociatedValue) } func myEnumClosureMapping() -> (MyAssociatedValue) -> MyEnum { return MyEnum.myCase }

我有一个关联值为struct的枚举。当我编写此代码时,它编译时不会出错:

protocol MyProtocol {}

struct MyAssociatedValue: MyProtocol {}

enum MyEnum {
    case myCase(MyAssociatedValue)
}

func myEnumClosureMapping() -> (MyAssociatedValue) -> MyEnum {
    return MyEnum.myCase
}
但是,我添加了另一个类似这样的函数:

func mySecondEnumClosureMapping() -> (MyProtocol) -> MyEnum {
    return MyEnum.myCase
}
现在我得到一个编译器错误,它说:
无法将类型为“(MyAssociatedValue)->MyEnum”的返回表达式转换为返回类型“(MyProtocol)->MyEnum”


MyAssociatedValue
struct符合
MyProtocol
protocol,因此此代码应无错误地编译。编译器错误的原因可能是什么?

不,它不应该编译。编译器需要一个闭包,可以将任何支持MyProtocol协议的东西映射到MyEnum。您给它的闭包只能将MyAssociatedValue映射到MyEnum。如果使用不是MyAssociatedValue的MyProtocol调用该闭包,则调用将崩溃,因此不允许

谁说
T
属于
MyAssociatedValue
类型?它可以是符合
MyProtocol
的任何具体类型。假设我们将
Int
MyProtocol
一致,并使用
Int
类型的
T
调用
myGenericEnumClosureMapping
(请记住,决定
T
类型的是调用方,而不是被调用方)。如果您的代码被允许,我们可以将
Int
传递给
MyAssociatedValue
。我编辑了这个问题,改为使用协议。仍然存在编译器错误。问题是相同的–您可以将符合
MyProtocol
的任何内容传递到返回的函数中(如符合
Int
),但关联的值是特定类型的
MyAssociatedValue
。请注意,如果进行强制转换
func myEnumClosureMapping()->(MyProtocol)->MyEnum{return MyEnum.myCase as!(MyProtocol)->MyEnum}
在这两种情况下(泛型和更高版本),编译器都工作得很好。我认为问题在于@Hamish和@gnasher729指出,没有强制转换,编译器不知道您试图传递什么,可以是任何东西,Swift的类型安全属性不允许它