Hi all,
I was expecting that the results of calling _openExistential and using implicit existential opening would be the same, but when I run the following:
value: 0 typeUsingTself: Int typeUsingTypeOf: Int
value: 0 typeUsingTself: Any typeUsingTypeOf: Any
value: 0.0 typeUsingTself: Double typeUsingTypeOf: Double
value: 0.0 typeUsingTself: Any typeUsingTypeOf: Any
value: zero typeUsingTself: String typeUsingTypeOf: String
value: zero typeUsingTself: Any typeUsingTypeOf: Any
Does anyone know why simply calling genericFunction(x) won't capture the type inside the function?
Your generic function has no constraints, so it won’t open any existentials. I think this was done to avoid changing existing code that already passed Any into unconstrained generic positions.
protocol ProtocolA {
associatedtype Value
}
struct StructA<Value>: ProtocolA {
var value: Value
// ...
}
and
func makeA(_ value: Any) -> any ProtocolA {
// create an instance of StructA using an appropriate type
// (not just Any) and return it as any ProtocolA
}
I can easily do that when Value is constrained by some protocol, but what if I wanted Value to be anything, without having to invent a special protocol to make this work?
I think you’ve found the one case that isn’t covered by the existing rules: wrapping a value in some kind of container. I don’t know of a workaround; maybe somebody more recently working on Swift does.
It doesn’t have anything to do with “capturing”—the static type really is Any, and that’s because genericFunction’s generic parameter has no constraints, so Any is just fine without having to open the existential to pass the argument to the function.
For backward compatibility with versions of Swift before implicitly opened existentials were implemented, this behavior is preserved for Swift 5 even in releases where the feature is now implemented. For the Swift 6 language mode, the existential will be opened as you’re expecting.
See the original proposal text for more explanation here.