iGodric iGodric - 1 year ago 69
Swift Question

Protocol with property of type Self can only be used as generic constraint, why?

It is not possible to use a protocol with a property with Self as type as a type, container type, parameter.
I think I need an example where it makes sense, that the compiler can not infer the type.

Definitions which compile

internal protocol Lovable {
var inLoveTo: Self? {

internal final class Human: Lovable {
var inLoveTo: Human? = nil

internal final class Animal: Lovable {
var inLoveTo: Animal? = nil

internal let thing11: Human = Human()
internal let thing12: Animal = Animal()

Not working code

But the following code makes sense to me and could work. So there have to be a case where you can not infer the type at compile time, which I can not see yet.

import Darwin

let thing13: Lovable = Darwin.random() % 2 == 0 ? thing11 : thing12 // So you do not know which dynamicType thing13 has at compile time, but it should be Lovable, error: mismatching types

thing13.inLoveTo // It could be Lovable

// Does not work, even though it makes sense for me, since inLoveTo adopts Lovable
internal func partner(one: Lovable) -> Lovable {
return one.inLoveTo

What do I not see?

Answer Source

Lets go one by one:

 let thing13: Lovable = Darwin.random() % 2 == 0 ? thing11 : thing12 

In this case, it makes sense for us as a reader. But there is a shortcoming? First, even a static assignment wont compile like you do.

 let thing13: Lovable = thing11

There is a deeper meaning why not. However, thinking in this way might make sense to get started. When the compiler sees this code, it will try to cast thing11 to a type Lovable. Casting is eventually specifying how many bits make up this data structure. For example:

 int b = 10;
 char greeting[] = (char[]) b; //C

Doing so you specify a int [8 bit long] to a array of [8 bit long] chars ==> String. The string however might not be useful as it might contain garbage.

This takes us to another thing. Lovable cannot be defined alone to say how big the memory bits it will take and what will be the structure of the memory for the properties it might have. We will not know the offset, we wont know if this is a value type or a reference type. And In essence, the memory structure is not complete. The type is said to be Generic Type.

And this is why you cant assign a concrete value [bits] to a structure/type which is not completely defined in isolation.

However, this is my reasoning and im not a compiler guy. If there is a proper explanation, please do comment below. Even If this doesn't make sense, i tried my best.