I wrote an extension onto Int
as below.
extension Int {
func squared () -> Int {
return self * self
}
}
print(10.squared()) // works
The above code works. Now I want to extend the IntegerType
protocol so that Int, UInt, Int64, etc would all conform. My code is as below.
extension IntegerType {
func squared () -> IntegerType { // this line creates error
return self * self
}
}
I get error:
Protocol 'IntegerType' can only be used as a generic constraint because it has Self or associated type requirements
I already saw this question and its video & this question, still couldn't understand. I only understood that there is some associatedType
which in this case is Self
but couldn't connect the dots. I feel like also my lack of knowledge on the Generics
subject is also a reason...
Can someone elaborate a bit on the subject and why does the extension create an error?
A function return type can only be a concrete
Type
.The point is Type. Anything struct, class or Protocols that are completely defined in themselves are pure Type. However when a protocol or struct depend on another Generic Type Placeholder such as T, then this is a partial type.
Type are a data construct that compiler has to allocate certain memory.
So something like this:
let a = Array<T>()
orlet b = T
is not sufficient information for the compiler to deduce at compile time.Hence, this wont work.
Here, IntegerType is a partial type. It is a generic protocol that only when conformed can then we know the exact type. Similar to Array. Array itself is not a type. Its a generic container. Only when someone creates it with Array() or Array()... then it has a type.
The same happened with you.
then again,
then again,
Hence, as RandomAccessIndexType has Self requirement meaning until and unless someone conforms to it, Self is unknown placeholder. It is partial Type.
Since IntegerType conforms to the RandomAccessIndexType and _RandomAccessAmbuiguity which requires Distance associated type too.
Hence you cant do this too
Again IntegerType needs to know Self and Distance (associatedType).
Int however provides the details like so
Hence you can do such
because it provides Self for SignedIntegerType and Distance for its other counterpart.
Simply put it:
A partial type cannot be used where a concrete type can be. A partial type are good for other generics and constraining them.
You just have to return
Self
edit/update:
Note: You can extend all numeric types (Integer & FloatingPoint) in Swift 4 extending the Numeric Protocol
Swift 4
Swift 3