протокола типизированного значения представлены с использованием «экзистенциального контейнера» (см this great WWDC talk на них, или on Youtube), который состоит из значений буфера фиксированного размера для того, чтобы хранить значение (если размер значения превышает это, он будет выделять кучу), указатель на таблицу свидетелей протокола для реализации методов поиска и указатель на таблицу показателей значения, чтобы управлять временем жизни значения.
Unspecialized generics используют практически тот же формат (я вхожу в это немного глубже in this Q&A) - когда они вызываются, указатели на протокол и таблицы значений значения передаются функции, а само значение сохраняется локально внутри функции, используя буфер значений, который будет выделяться для значений, больших этого буфера.
Таким образом, из-за явного сходства в том, как они реализованы, мы можем сделать вывод о том, что невозможность говорить в терминах протоколов с связанными типами или ограничениями Self
вне обобщений является лишь текущим ограничением языка. Нет никакой реальной технической причины, почему это невозможно, оно просто не реализовано (пока).
Вот отрывок из дженериков манифеста «Generalized existentials», которая обсуждает, как это может работать на практике:
Ограничения на экзистенциальных типов пришли от реализации ограничения, но разумно, чтобы позволить значение типа протокола , даже если протокол имеет ограничения Self или связанные типы. Для примера рассмотрит IteratorProtocol
снова и как она может быть использована в качестве экзистенциальных:
protocol IteratorProtocol {
associatedtype Element
mutating func next() -> Element?
}
let it: IteratorProtocol = ...
it.next() // if this is permitted, it could return an "Any?", i.e., the existential that wraps the actual element
Кроме того, разумно хотеть, чтобы ограничить связанные типов экзистенциальным, например, «А Sequence
чей тип элемента String
» может быть выражено, помещая где положение в protocol<...>
или Any<...>
(за «Переименование protocol<...>
Any<...>
к»):
let strings: Any<Sequence where .Iterator.Element == String> = ["a", "b", "c"]
Ведущий .
показывает, что мы говорим о динамическом типе, , т. е. Self
, который соответствует протоколу Sequence
. Нет причин, по которым мы не можем поддерживать произвольные where
статьи в пределах Any<...>
.
Из-за возможности ввода значения в виде протокола с ассоциированным типом это всего лишь короткий шаг, позволяющий применять для данного типа тип-литье и, таким образом, позволять что-то вроде вашего первого расширения для компиляции.
Все объяснения приведенной ошибки Я нашел просмотр [SO], где в основном говорят: «Мы не знаем значений для связанных типов, так как мы можем их отличить?». По этому объяснению, я не думаю, что второй образец должен скомпилировать, следовательно, мой вопрос. – Raphael