Interesting idea. I don’t think we can use traits in the sense LLVM usually uses that word, because those require a templated, header-only implementation, and I don’t think that’s feasible here. We could use virtual inheritance though, with some caveats (for example, to make the memory management work out, we’d want sub-type iteration to be callback-based rather than iterator-based).
My general inclination here is to try the separate type system first, and fall back to this variant if it turns out to add significant cost.
The function prototype itself would be short-lived, but my assumption was that the argument/return types would use the “usual” uniqued type system representation, with a cache on the translation from Clang to ABI types. If we make the types ephemeral, we wouldn’t be able to cache the translation, which may be problematic for complex record types.