SE-0283: Tuples conform to Equatable, Comparable, and Hashable

I'll discuss more in detail about what is being added, and what is considered ABI (what needs to stick around) to hopefully provide some more light about the "technical debt" being added.

First, is the addition of a new protocol conformance kind for the compiler. This new conformance kind is used to inform the compiler that these conformances get lowered into special conformances provided by the runtime. When we see a tuple being used as an Equatable parameter or calling the == operator on tuples, we assign this new conformance kind to be used. Once variadic generics, parameterized extensions, and extending non-nominal types are all implemented, a normal tuple conformance to EHC (Equatable, Hashable, and Comparable) can be implemented within the standard library. Assuming once that's possible it'll require the newest Swift version, this new conformance kind should be able to go away because the compiler can check the type and protocol being used in a conformance and check against the deployment target. If we happen to see tuples with EHC against a lower Swift version when the regular conformances came out, we should be able to lower to the special back deployed conformances.

Second, are the runtime additions. There are two parts to adding a new conformance to a type in the runtime (in this case tuples with EHC). The first part are the conformance descriptors. There is a conformance descriptor for every single type conformance in Swift. This tells the runtime that said type conforms to said protocol along with other information like getting the protocol witness table. We have to add 3 of these to the Swift runtime to support the 3 protocol conformances. These conformance descriptors are ABI. Joe mentioned here: Special Case Protocol Conformance: Long-term Tradeoffs for Near-term Conformance - #21 by Joe_Groff that these conformance descriptors could become aliases to the real deal once it's available, meaning we can remove the structures from the runtime and alias them instead. The other part of the runtime additions are the protocol function implementations. It's exactly how it sounds, these are functions being added to the runtime that are being called every time you call one of EHC's functions or variable getters. E.g. (1, 2) == (2, 1) invokes the equal witness method in the runtime to determine if tuple1 is equal to tuple2. These functions are not ABI because they are a property of the conformance descriptors for the runtime to emplace into the witness table. So because these conformance descriptors can become aliases in the future, these function implementations should also be removed in favor of the real implementation. (@Joe_Groff did I butcher any of this?)

So, the only things we need to keep around forever are the conformance descriptors for older clients to use. Perhaps my use of entry point is confusing, but these are the parts of the ABI that we need to support, or potentially just make into an alias. Assuming variadic generics + parameterized extensions + non-nominal extensions require a specific Swift version, we'll also want to keep around some logic to be able to back deploy usage of tuple EHC conformance to older clients.

  1. Variadic generics, parameterized extensions, and extending non-nominals along with actually adding these conformances to the standard library. I do wonder if we also need @available on new conformances?
  2. I'm not sure anyone has a concrete timeline for all of these, but I know for parameterized extensions I want to release that sometime this year.
  3. I'm not sure how much runtime hackery is needed to back deploy all of those features, or if it's even possible, but it's best to assume they all will.

So the back deployment feature is being added to Swift compatibility libraries. There are only compatibility libraries for older runtimes that get linked given an older runtime compatibility version. There is not a compatibility library for the current Swift. If a client is not using an older Swift runtime, then we don't link against those libraries (or at least I don't think so, I'm still learning!) and instead use the Swift runtime's implementation of functions. We have to add this support to the Swift runtime along with the compatibility libraries to enable all parties to use this feature. Hopefully I didn't butcher explaining this :sweat_smile:

I think I did a poor job of explaining this last sentence. It was intended to say that because these implementations are in the runtime, we have a unique opportunity to utilize the compatibility libraries to back deploy this to older clients.


I know parts of this post were pretty technical, but I wanted to make it clear what is being added and what needs to be supported going forward. If you have more questions, please ask!

12 Likes