Swift added the any keyword to the language. It gets used whenever a type is a boxed protocol (aka, existential container) and by default, the swift compiler will generate any for any type that would get bound into an existential container. The reasoning behind this, I've read, is that putting in any draws attention to this so that when you're using it, you realize that there is a cost to using this type.
What is the cost?
An existential container is a variable sized struct that contains a fixed-sized payload of 3 machine words, followed by a pointer to the type metadata for the value in the payload. This is then followed by 0 or more protocol witness table pointers. What is a witness table? It's a vtable -a table of function pointers that go to methods- that is sits separate from a type.
The cost is in allocating (if needed) the existential container, copying (with reference counting) the value into the payload OR allocating room on the heap for a copy of the value , copying (with reference counting) and then putting the pointer to the value into the payload. So, no, it's not free. I do not, however, see how the use of any does anything to draw attention to the cost other than to add syntactic clutter to the language.
public func doSomething (a: any SomeProtocol) { }
By comparison, you could also write equivalent code that is nearly equivalent to this like so:
public func doSomething<T:SomeProtocol> (a: T) { }
This uses a different ABI as there is no existential container and the type metadata pointer and protocol witness table(s) get passed in implicit arguments.
In order to do this I:
added a new case to the type grammar in the production rules that with match any type.
fixed an issue in SwiftInterfaceReflector that was not getting the text representing a type, but GetText () does not include whitespace that may have existed in the original file and any is technically part of the type so I was getting anyType instead of any Type.
added a case in TypeSpecParser to spot the any token and mark it in the TypeSpec type, and adjusted all the copy constructors and comparers
swift now explicitly adds two implicit module imports to every compilation _StringHandling and _Concurrency which we have be able to load or ignore. I ignore them
Swift added the
any
keyword to the language. It gets used whenever a type is a boxed protocol (aka, existential container) and by default, the swift compiler will generateany
for any type that would get bound into an existential container. The reasoning behind this, I've read, is that putting inany
draws attention to this so that when you're using it, you realize that there is a cost to using this type.What is the cost? An existential container is a variable sized struct that contains a fixed-sized payload of 3 machine words, followed by a pointer to the type metadata for the value in the payload. This is then followed by 0 or more protocol witness table pointers. What is a witness table? It's a vtable -a table of function pointers that go to methods- that is sits separate from a type.
The cost is in allocating (if needed) the existential container, copying (with reference counting) the value into the payload OR allocating room on the heap for a copy of the value , copying (with reference counting) and then putting the pointer to the value into the payload. So, no, it's not free. I do not, however, see how the use of
any
does anything to draw attention to the cost other than to add syntactic clutter to the language.By comparison, you could also write equivalent code that is nearly equivalent to this like so:
This uses a different ABI as there is no existential container and the type metadata pointer and protocol witness table(s) get passed in implicit arguments.
In order to do this I:
type
grammar in the production rules that with matchany
type.SwiftInterfaceReflector
that was not getting the text representing a type, butGetText ()
does not include whitespace that may have existed in the original file andany
is technically part of the type so I was gettinganyType
instead ofany Type
.TypeSpecParser
to spot theany
token and mark it in theTypeSpec
type, and adjusted all the copy constructors and comparers_StringHandling
and_Concurrency
which we have be able to load or ignore. I ignore themAdded a unit test.