Implementation issues with SE-0283 (Tuples are EHC)

I wanted to post this in the recent Status of SE-0283? (Tuples Conform to Equatable, Comparable, and Hashable) , but figured it might be better suited for a separate compilerish thread.

The two main issues that I've had trouble coming to terms with are 1. the assembly needed in the runtime and 2. the lack of hooks in older runtimes to implement backwards compatibility in a "clean" or non-hacky way in my eyes.

The first issue is only really an issue on platforms Swift is not currently supported on because I've worked my way through designing the assembly needed to work on Darwin, Windows, and a subset of Linux. Shortly afterwards I realized I could do the same thing the compatibility libraries do when resolving relative references (which is why the data structures needed for these conformances are in assembly to begin with) by having a constructor inject the relative references. The obvious downside to this is that there is a small startup cost, but allows the implementation to rely solely on C++ and no assembly.

The second issue is a little more difficult for me. When a Swift program uses a conformance (either by passing in a value in a generic constrained function, constructing a type with protocol constraints, etc.), depending on the conformance we may need to create a new witness table at runtime. In the case of tuples, we do need to make a new witness table with a list of all the element witness tables. We need to directly reference the data structure that models this conformance when generating a new witness table. Because this feature is new for the runtime, older runtimes don't have this conformance data structure to reference, so the compiler/runtime has 2 options. Either the compiler emits a stub function within a program that essentially checks the runtime version and dlsyms the correct data structure (I'm unsure if dlsym can even find the backward conformance), or the runtime already has a hook that does this dlsym and gives us back the right thing. There's a set list of runtime functions that are already hooked, but only 1 or maybe 2 of them could work in this case of generating a new witness table. That's great for the backward clients because these conformances work a little differently for them, but applications deploying to those older targets but running on the newer runtime will pay a performance cost, again because of the implementation difference between the conformances on new vs. old.

Perhaps I'm overcomplicating a lot of this (or all of it), and if I am I apologize. I've been considering maybe it's just better we wait until general conformances on non-nominal so that things aren't as special cased and the compiler has more information to be able to solve some of these issues for us. I initially wrote this for the evolution thread, but since moved it over here. Please ask if you need more detail!

18 Likes

@Alejandro Thank you for this detailed 2021 deep-dive into SE-0283's implementation challenges! Your analysis of the runtime assembly needs (especially the relative reference injection to avoid platform-specific code) and the backward compatibility headaches (stub functions/dlsym vs. hooked runtime functions) was incredibly insightful. It's clear a ton of thought went into weighing the startup costs and perf implications for mixed old/new runtime scenarios. Kudos for laying that out so clearly.

Fast-forward to November 2025: Your suggestion to wait for general conformances on non-nominal types feels spot-on, and it looks like we're closer now. Slava's 2023 pitch on User-defined tuple conformances (status: implementation in progress, feature flag TupleConformances) seems to build directly on this, enabling the runtime hooks and witness table generation that blocked SE-0283.

I've revived the discussion in my recent pitch:
[Pitch] Automatic Hashable Conformance for Tuples (Revival of SE-0283)

It focuses narrowly on Hashable (as a minimal step toward full E/C/H) to unblock common use cases like tuple dictionary keys, while preserving your concerns about safety and perf.

Questions for you or the compiler team:

  • Has the TupleConformances work addressed the assembly/relative ref issues (e.g., via C++-only paths)?
  • For backward compat, are the new runtime caches (like in iOS 15+) reducing the perf hit for apps on older targets?
  • Would a scoped Hashable-only implementation (up to arity 6) be feasible as a bridge?

I'd love your thoughts, happy to iterate or help prototype if useful. Let’s get tuples hashing!

1 Like