Как работает дополнительная ковариация в Swift

Как ковариация работает для Optional в Swift?

Скажем, я пишу следующий код:

var nativeOptionalView: Optional<UIView>
let button = UIButton()
nativeOptionalView = .Some(button)
var nativeOptionalButton = Optional.Some(button)

nativeOptionalView = nativeOptionalButton

Он компилируется и работает отлично. Однако, если я определяю MyOptional как

enum MyOptional<T> {
    case Some(T)
    case None
}

И напишите следующее:

var myOptionalView: MyOptional<UIView>
let button = UIButton()
myOptionalView = .Some(button)
var myOptionalButton = MyOptional.Some(button)

myOptionalView = myOptionalButton

Я получаю сообщение об ошибке:

error: не может назначить значение типа 'MyOptional<UIButton>' для ввода 'MyOptional<UIView>'

Я понимаю, почему эти ошибки происходят с MyOptional, я не понимаю, почему это не происходит с Optional.

Ответ 1

Это не так. На данный момент Swift не поддерживает специальные ковариантные дженерики.

Проверка типа Swift - это выражение, а не глобальное (как в Haskell). Эта задача обработана семантическим анализом в lib/Sema. Затем система ограничений пытается соответствовать типам, а затем обрабатываются специальные случаи ковариации для и optionsals.

Это было решение для языкового дизайна. Вы должны иметь возможность делать все, что вам нужно, с помощью встроенных типов коллекций и опций. Если вы этого не сделаете, вам следует открыть радар.

Ответ 2

В то время как я согласен с тем, что, вероятно, существует какая-то "магия компилятора", это может быть выполнено в вашей пользовательской реализации путем нажатия кнопки на UIView, например.

var myOptionalButton = MyOptional.Some(button as UIView)

или

var myOptionalButton: MyOptional<UIView> = .Some(button)