> Rust has its macros, Swift has its result-builders.

The difference is that Rust macros are general — they're useful for everybody, and they can be used to implement nearly any kind of custom syntax or code generation.

There was talk on swift-evolution going back to the Swift 2-3 days about how Swift was eventually going to get “hygienic macros” that looked something like Rust’s proc-macros. But this was a very long-term goal; everyone knew it would take years to design and implement such a system that had the flexibility, safety, and expressivity we all wanted.

In the meantime though, Apple started to add a lot of complicated features using compiler magic. This started with Codable, which added language support for serializing and deserializing objects to formats like JSON. This was awesome, and became one of Swift’s best features IMO. But the implementation bothered me a little: it’s a protocol where the compiler will synthesize a default boilerplate implementation if you don’t implement it manually. But this is exactly the kind of thing that a real hygienic macro system would be better for; e.g. Rust's serde does the same thing as Codable, but it's way more powerful and more flexible. IIRC some people pointed this out on the forums, but this was dismissed with “we want to ship this now, and macros are years down the road.” Oh well, don’t let perfect be the enemy of good, right?

But the Swift 5 release had even more compiler magic — a bunch more protocols gained automatic compiler synthesis, and then “result builders” happened. Again: a feature that’s helpful in isolation, and solves a real problem, but greatly increases the language surface area. And since these features are implemented using compiler magic, only the compiler team can add new features, and it takes a long time. So in practice, the only magic features that get implemented are those that Apple needs for their libraries. Whereas if they had spent that time and effort working on a hygienic macro system, they could have achieved Codable, result builders, and every other use case library authors can imagine. Chris Lattner has indicated that this sort of thing was part of the reason he left the core team: "It is obvious that Swift has outgrown my influence, and some of the design premises I care about (e.g. "simple things that compose") don't seem in vogue any more." [0]

It became clear (partly through this, but also because of a LOT of other stuff) that the evolution of the Swift language was being driven by Apple's internal schedules, and not the other way around. Controversial or half-baked features were frequently rushed through review in order to be ready in time for WWDC -- or even worse, shown off in surprise reveals at WWDC, with the core team saying things like "yeah we know this is a bad design, but we showed it in the WWDC keynote so we can't change it now" [1].

At this point, I started to experiment with Rust because Swift's memory-management overhead was causing me too many performance headaches. It felt like a breath of fresh air: the language feels like it evolves at a snails' pace compared to Swift, but every feature that makes it into stable is extremely polished and very well-thought-out, especially with regard to how it fits with the rest of the language, and how it works in "weird" situations like embedded environments.

[0]: https://forums.swift.org/t/core-team-to-form-language-workgr...

[1]: https://forums.swift.org/t/se-0258-property-wrappers-second-...