Wednesday, November 20, 2019

How Swift Achieved Dynamic Linking Where Rust Couldn’t

Alexis Beingessner (tweet, Hacker News):

For those who don’t follow Swift’s development, ABI stability has been one of its most ambitious projects and possibly it’s defining feature, and it finally shipped in Swift 5. The result is something I find endlessly fascinating, because I think Swift has pushed the notion of ABI stability farther than any language without much compromise.

So I decided to write up a bunch of the interesting high-level details of Swift’s ABI. This is not a complete reference for Swift’s ABI, but rather an abstract look at its implementation strategy. If you really want to know exactly how it allocates registers or mangles names, look somewhere else.

Also for context on why I’m writing this, I’m just naturally inclined to compare the design of Swift to Rust, because those are the two languages I have helped develop. Also some folks like to complain that Rust doesn’t bother with ABI stability, and I think looking at how Swift does helps elucidate why that is.

Patrick Walton:

I should mention that Rust tried in its early days to do witness tables (“type descriptors”/“tydescs”). I wrote a lot of that code.

Ironically, one of the big reasons we ripped it out was because of code bloat.

IIRC switching to monomorphization actually reduced code size by quite a bit.

Though the biggest reason was just performance: we couldn’t get type descriptor overhead below 20% of the program runtime or so, which was unacceptable.

Doug Gregor:

I still think that Swift’s library evolution story (ties in with the ABI) is the only novel feature of the Swift language. Everything else is lovingly borrowed and integrated from other languages

Joe Groff:

Reabstraction might also be a novel implementation technique. Some papers on levity polymorphism in Haskell declared the problem unsolvable without a JIT


Comments RSS · Twitter

Leave a Comment