Ваш первый пример
Проблема в первом примере - это просто ваше понимание этой строки:
enum CodingKeys: DynamicKey
Вы говорите:
Есть идеи, почему компилятор говорит, что Foo.CodingKeys не соответствует CodingKeys, когда он наследует от DynamicKey, который имеет соответствие?
Но Foo.CodingKeys не «наследуется от DynamicKey». Ничто не может «наследовать» от структуры. Обозначения здесь не имеют ничего общего с наследованием. То, что вы сделали, это перечисление с необработанным значением типа DynamicKey. (Обычно вы не сможете этого сделать - необработанный тип значения должен быть «выражаемым литералом строки, целого числа или числа с плавающей точкой», но вы можете обойти это, сделав DynamicKey Equatable и ExpressibleByStringLiteral.)
Это тот же синтаксис, как если бы вы сказали:
enum MyEnum : Int {
case myCase // zero
}
(Вы также запутали себя, используя магическое имя CodingKeys для своего перечисления. Но, вероятно, это не совсем так.)
Ваш второй пример
Тогда во втором примере, где DynamicKey является классом, вы запутались в совершенно противоположном направлении. Здесь вы сделали что-то совершенно другое:
enum CodingKeys: DynamicKey & CodingKey {
Здесь ваше перечисление не имеет какой-либо необработанный тип значения; материал после двоеточия объявляет ограничение протокола. Но здесь вы обманули себя еще одним способом, потому что на самом деле часть DynamicKey не имеет значения; код скомпилировался бы так же хорошо, если бы вы просто сказали
enum CodingKeys: CodingKey {
Все, что на самом деле происходит в этом примере, это то, что вы просили об автоматическом синтезе соответствия CodingKey, и вы его получили.