Reputation: 77
How is it possible to pass around a protocol instance if the implementing type is a ValueType? When you pass around a protocol you have no knowledge of the underlying type. It could be ValueType or it could be ReferenceType.
I have a struct
MyStruct that implements some protocol VectorProtocol
. I then have a function called arrayMaker that basically is just going to create instances of MyStruct and return one of those. This function is a bit convoluted for the example, I admit.
ArrayMaker is returning a protocol, but the implementing class is a ValueType. How exactly is the lifetime of this object now managed given this is concretely a ValueType? I could even take this protocol instance and store it for a very long time as a member to some other class.
Basically: I'm not sure how it is that the instance I return from this function can continue to live without reference semantics.
Is it possible for a struct to somehow be quietly promoted to reference semantics by Swift?
import Foundation
protocol VectorProtocol {
var x: Int { get set }
var y: Int { get set }
var z: Int { get set }
}
struct MyStruct : VectorProtocol {
var x: Int;
var y: Int;
var z: Int;
}
func arrayMaker() -> VectorProtocol {
// protocolArray, and everything in it should be released
// from memory upon function exit I would think
var protocolArray: [MyStruct] = []
for _ in 1...5 {
protocolArray.append(MyStruct(x: Int.random(in: 0..<10), y: Int.random(in: 0..<10), z: Int.random(in: 0..<10)))
}
// only makes sense to me for this to live if semantics are reference
return protocolArray[3]
}
let vectorProtocol = arrayMaker()
print("Protocol has X Value: \(vectorProtocol.x)")
Upvotes: 2
Views: 291
Reputation: 299325
The return value of VectorProtocol is a protocol existential, which is basically a 3 word "box" around a value. Your value is only 3 words long, so it will fit in the box. (If it were larger than 3 words, it would be copied into heap storage, and the box would memory manage it).
These 3-word boxes are passed on the stack, so they don't require any heap memory. The three values are just put directly on the stack (together with a few other words of housekeeping).
If this were a class, then the existential box would just hold a pointer to it (along with a few other words of housekeeping).
This was all explained in the WWDC 2016 session 416, Understanding Swift Performance, but Apple appears to have removed that from developer.apple.com. You can still find some notes about it at WWDC Notes and the transcript is available through the Wayback Machine.
Upvotes: 4