Почему использование dynamicType для принудительно развернутого nil необязательного типа значения работает?

Я был действительно смущен, обнаружив, что следующий код просто отказывается аварийно завершать работу с типичным исключением « неожиданно найден ноль при развертывании необязательного значения », которое можно ожидать при принудительном развертывании bar.

struct Foo {
    var bar: Bar?
}
struct Bar {}

var foo = Foo()

debugPrint(foo.bar) // nil
debugPrint(foo.bar!.dynamicType) // _dynamicType.Bar

Кажется, dynamicType каким-то образом способен вернуться к определенному типу bar - без сбоев.

Обратите внимание, что это происходит, только когда Bar определяется как тип значения (как @dfri говорит ), Foo является struct или final class (как отмечает @MartinR ) & foo является изменчивым.

Первоначально я считал, что это может быть просто оптимизация компилятора из-за того, что тип bar известен во время компиляции, поэтому поэтому развертывание силы могло быть оптимизировано, но оно также аварийно завершается, когда Bar ] определяется как final class. Кроме того, если я установлю «Уровень оптимизации» на -Onone, он все равно будет работать.

Я склонен думать, что это странная ошибка, но хотел бы получить подтверждение.

Это ошибка или функция с dynamicType, или я просто что-то здесь упускаю?

(Использование Xcode 7.3 с Swift 2.2)


Обновление Swift 4.0.3

Это все еще воспроизводимо (с еще более минимальным примером) в Swift 4.0.3:

var foo: String?
print(type(of: foo!)) // String

Здесь мы используем dynamicType ' s преемник, type(of:), чтобы получить динамический тип; и, как и в предыдущем примере, он не падает.

10
задан Hamish 1 March 2018 в 21:52
поделиться