In the document, the Chapter "Opaque Types" describes the difference between protocol types and opaque types as function return types as follows:
Another problem with this approach is that the shape transformations don’t nest. The result of flipping a triangle is a value of type
Shape
, and theprotoFlip(_:)
function takes an argument of some type that conforms to theShape
protocol. However, a value of a protocol type doesn’t conform to that protocol; the value returned byprotoFlip(_:)
doesn’t conform toShape
. This means code likeprotoFlip(protoFlip(smallTriangle))
that applies multiple transformations is invalid because the flipped shape isn’t a valid argument toprotoFlip(_:)
.
However, in practice, unlikely, it is valid as proven by the following example:
#if swift(>=5.8)
print("hello swift 5.8+")
#endif
protocol Shape {
func draw() -> String
}
struct Triangle: Shape {
var size: Int
func draw() -> String {
var result: [String] = []
for length in 1...size {
result.append(String(repeating: "*", count: length))
}
return result.joined(separator: "\n")
}
}
struct FlippedShape<T: Shape>: Shape {
var shape: T
func draw() -> String {
if shape is Square {
return shape.draw()
}
let lines = shape.draw().split(separator: "\n")
return lines.reversed().joined(separator: "\n")
}
}
struct Square: Shape {
var size: Int
func draw() -> String {
let line = String(repeating: "*", count: size)
let result = Array<String>(repeating: line, count: size)
return result.joined(separator: "\n")
}
}
func flip<T: Shape>(_ shape: T) -> some Shape {
return FlippedShape(shape: shape)
}
func protoFlip<T: Shape>(_ shape: T) -> Shape {
if shape is Square {
return shape
}
return FlippedShape(shape: shape)
}
let smallTriangle = Triangle(size: 3)
let nestedThing = protoFlip(protoFlip(smallTriangle))
print(nestedThing.draw())
// hello swift 5.8+
// *
// **
// ***
What do you think about it?
Can it be a bug of the compiler?
Originally, it doesn't make sense that "However, a value of a protocol type doesn’t conform to that protocol."
Thanks!