- Xcode. A really rough ide that has a hard time at scale, choking on package refreshes, many targets, and more. It has a special entitlement so you can't even binary patch it if you want to fix it!
- Build systems. Cargo is _much_ easier to work with than SPM.
- Macros support, codegen is still largely done outside of the macro system, which should indicate its use.
- Linter / format support. Yeah, it exists, last I checked it's just a good bit worse.
- Performance. There are MANY performance cliffs in Swift; most can be fixed by a sufficiently determined compiler developer, but at this point we've kinda departed talking about the language as-is.
- Type inference time. Swift's bidirectional type inference causes a ton of choking on complex expressions, which is a real problem with its number one use case, SwiftUI.
- An exacerbating factor on the above, imports are all implicitly module-scoped, meaning that changing a single file means recomputing the types for all files in the module. And because SPM and Xcode have such a rough time with multiple targets, that usually means that a single change can lead to recompiling all Swift files.
- Weirdness around classes and structs? I understand that they had to do it for objc compatibility, but I would've found it much cleaner if they'd just from the start had something replacing class, like a fully-sugared `final class Box<T>` that replaces all uses of class.
I agree that for the most part it _could_ be an easier rust, but between including bidirectional type inference without a cut operator and poor tooling I struggle to find where it's actually easier in cases that you can't just use typescript and dodge all the non-typecheck compilation headaches entirely.
This is wrong, you don't need a `Box` here. The Rust compiler forces you to have a layer of indirection, but `Vec` already does that.
Also, it works okay at best with VS Code, and you couldn’t pay me to use Xcode.
Kotlin tried doing similar things to gain adoption on the server side. But server-side programming is a crowded space, and people just don’t like writing distsys code in another JVM language. Swift’s story is a little better on that front.
If you want a quick-and-dirty language, Python and TypeScript do the job. For perf-sensitive, highly concurrent environments, Go is hard to compete against. A lot of ops tooling and infra code is written in Go. For systems programming and embedded code, Rust is a better choice.
So while it’s fun to think about what language X gives you in terms of syntax, in practice it’s rarely enough to pick a language like Swift for your next non-toy backend distsys work.
Also, Apple. Given their stance against free and open source software, I wouldn't be too thrilled to pick a language that works better in their walled garden.
How good is the developer experience on a non-Apple platform really? Linux is my primary platform and my perception is, that allmost all of the swift eco system is for Apple. Libraries, tools, documentation, IDEs, tutorials, etc. all assume, that you use an Apple.
Can someone tell me who does not use an Apple-device and uses swift?
Are there people who see a "match" statement, smash both hands on the table, and shout, "WHAT THE ___ is a ------- MATCH STATEMENT?!!! THIS IS SO $%^&@*#%& CONFUSING!! I DON'T KNOW THAT WORD!! I ONLY KNOW SWITCH!!"
I my view, and I might be wrong, many features of Rust are chosen specifically to have the language comply to the zero-cost rule. Such as the ownership model.
[1] https://doc.rust-lang.org/book/ch15-04-rc.html
[2] https://doc.rust-lang.org/book/ch15-05-interior-mutability.h...
Arc is no longer being developed ( http://www.newswarner.com/2025/05/27/the-browser-company-exp... ) and AFAICT their efforts to port Swift to Windows for its sake have been cancelled.
Parameter defaults, and null short circuiting are two of them.
I find writing Swift is faster for me, and it’s easier to learn for people than Rust. Also Swift interop with other languages is much simpler.
Though there are way fewer resources to learn Swift, and cargo is superior to SPM. And of course rust is better cross platform today, but Swift is closing the gap.
I think they feel like very similar languages overall, and they both influence each other.
I'd love for the experience outside of Xcode to get better (even on a mac, developing for macOS/iOS) but I have to say that I didn't find Xcode to be _that_ aweful. I've certainly used worse IDEs, which is partly why I dislike IDEs altogether.
1: https://log.beshr.com/notes-on-swift-from-building-an-ios-ga...
So creating more confusion and losing the devs who are not aware (so would prefer a plainer language) is somehow more convenient and a masterclass in... deception (a positive since when)?
I have used Swift (stopped about two years ago) and use Rust extensively these days.
People commenting here have mentioned the dreadful Xcode. But if you want to build systems on Apple, without investing a lot in setup, you are stuck with Xcode.
To be clear it's failures as an editor or build system are not the main problems with Xcode (albethey very frustrating when the intermittent problems show up) it is the abject failure of the tooling.
We never got the profiler to produce anything intelligible after days of trying, spread over several weeks.
SwiftUI is not part of the conversation here, and I limit the amount of UI building I do, but it shares all the problems of declarative UI frameworks - mainly "where is the code?". Debugging logic problems is nigh impossible in code you're unfamiliar with
The very worst part of Swift were the thread control. Trivial to overwrite shared memory, "DispatchQueus" (?IIRC?) are a thin wrap of fork, and do nothing but add complications
Swift is probably better than Objective C, the latter being from the 1980s, and things have moved on, if your target is iOS and friends, and you are sure you never want to port, then obeying Apple is a wise business decision. Other than that stay away from it. Use Go for most things, and Rust when you must
How about Rust is Rust. Swift doesn't really appeal to me as a high level programer. C#, JS and Python largely pay my bills.
The non apple ecosystem just isn't there, and it was never built to be cross platform. If I need to build something I'd probably lean on the languages I already know.
A few times a close friend has wanted an app built and I went with Flutter/Dart + Firebase.
I'm using Godot for games.
Learning a new language, even a similar one is a time investment. In fact I just want better tooling for the languages I already know. Word to UV for Python.
Swift is a mix of great features, miserable features, and... every other feature that someone on Evolution dreamt up (with the exception of those that would fix the miserable features)
Swift is unique among high-level languages in that the mental effort required to do many simple things rivals that of a low-level language.
This example doesn't show me any meaningful difference, and Rust also let's you attach functionality to enums.
What matters more is the long-term value for what’s being built and maintained.
For portable, high-performance backends, Rust often offers a higher value/friction tradeoff, IMO.
For Apple platform development, Swift is the obvious choice.
Swift’s cross-platform story has improved, but outside the Apple ecosystem the incentives still seem weaker compared to Rust.
So overall, IMO, Rust tends to have a higher net value beyond Apple-specific use cases.
Kotlin put a lot of work into proving itself as something more than just a language for Android development, starting first with backend.
It seems like once KMP became viable Swift is just trying catch back up.
This is plain wrong, and it undermines the credibility of the author and the rest of the piece. Rust did not invent ownership in the abstract; it relies on plain RAII, a model that predates Rust by decades and was popularized by C++. What Rust adds is a compile-time borrow checker that enforces ownership and lifetime rules statically, not a fundamentally new memory-management paradigm.
The more you deviate from this, the more cracks there are.
I really wanted to like it, but the experience was terrible, from the editing side (with vscode) all the way to the performance of existing frameworks (tried both Vapor and grpc-swift-2).
Outside of the Apple ecosystem it's going to be friction all the way. There are better choices.
This tool will transparently compile if after a while: https://github.com/jrz/tools
last time when I used Swift was v3 - and transition from v2 was a little rough.
the language kept adding features becoming a baby C++
if they had invested in bringing outside parties early on - not just iOS etc - swift would've replaced python
Swift is a more convenient Rust - https://news.ycombinator.com/item?id=41464371 - Sept 2024 (308 comments)
If Rust is too low level for you, you can write Go or Kotlin or even something new and fresh like Gleam.
We were all told to "prefer structs" over classes in Swift, but structs are always passed by value.
We're also told to maintain "one source of truth" (which I'm sure a lot of us did anyway). But you can't do that when you're copying stuff all over the place.
So now what? I got so sick of trying to figure out how to pass structs into views for modification by the user that I made everything a class. What a relief. Now I could get back to work on functionality instead of constructing absurd gymnastics to get altered data back from a view.
I find the whole "structs are passed by value, classes by reference" thing hokey as hell and poor style. People reading the code don't know if the called function can change the passed-in object or not; they have to go see if it's a class or a struct. Lame.
Rust is more complicated than C but has good reasons for everything it does. It's lower level too, which is fine. If I want high level, I look to JS and not Swift.
And it's not a more convenient Rust. I'd rather use Zig or Go (neither of which are worthy in the eyes of true Crustaceans, but which just get the job done).
Swift started out pretty nice but they've added too much Liquid Glass since then, the type system constraint solving madness and forcing actors down everyone's throat come to mind.
I don't touch it unless forced to these days.
Giving a familiar name to a concept which behaves in familiar ways some of the time and surprising ways other times seems like a dirty trick to me, not a convenience.
Both are great languages
So what do you need to do to make Swift as fast as Rust?
Some previous discussion:
Really interesting results, not sure how well it is written but works. I was quite found of Rust syntax; it certainly is not as convoluted as C++ (in my opinion).
Then I read this article. Since I was already eye-balling Swift for some time, I decided to give it a try and port to it, using Rust implementation as reference, and this time, without much of A. I. assistance, if I could help it.
I'm using an qcow2 Debian trixie arm image in UTM as playground. I found out that there is no packaging for Debian at the time of this writing: https://github.com/swiftlang/swift/issues/60690. No problem! They have a script for installing: https://www.swift.org/install/linux/
curl -O https://download.swift.org/swiftly/linux/swiftly-$(uname -m).tar.gz && \
tar zxf swiftly-$(uname -m).tar.gz && \
./swiftly init --quiet-shell-followup && \
. "${SWIFTLY_HOME_DIR:-$HOME/.local/share/swiftly}/env.sh" && \
hash -r
But, god damn, the size is huge, Unsupported Linux platform
Debian GNU/Linux 13 (trixie) is not an officially supported platform, but the toolchains for another platform may still work on it.
Please select the platform to use for toolchain downloads:
0) Cancel
1) Ubuntu 24.04
2) Ubuntu 22.04
3) Ubuntu 20.04
4) Ubuntu 18.04
5) Fedora Linux 39
6) RHEL 9
7) Amazon Linux 2
8) Debian GNU/Linux 12
Pick one of the available selections [0-8] :
8
Installing swiftly in /home/debby/.local/share/swiftly/bin/swiftly...
Creating shell environment file for the user...
Updating profile...
Fetching the latest stable Swift release...
Installing Swift 6.2.3
Downloading Swift 6.2.3
100% [========================================================]
Downloaded 947.6 MiB of 947.6 MiB
Verifying toolchain signature...
Extracting toolchain...
The file `/home/debby/ent/agateteper/.swift-version` has been set to `Swift 6.2.3`
The global default toolchain has been set to `Swift 6.2.3`
Swift 6.2.3 is installed successfully!
There are some dependencies that should be installed before using this toolchain.
You can run the following script as the system administrator (e.g. root) to prepare
your system:
apt-get -y install libicu-dev libcurl4-openssl-dev libedit-dev libsqlite3-dev
libncurses-dev libpython3-dev libxml2-dev pkg-config uuid-dev libstdc++-12-dev
947.6 MiB ! I wonder why is that...Hah! But RC is GC! [1]
> Again, this is just deception for those developers coming from C-like languages. Swift’s error handling works exactly like Rust’s behind the scenes, but it is hidden in a clever, familiar syntax.
But the indent heavy syntax is one of the worst parts of exceptions?
Rust:
fn value_in_cents(coin: Coin) -> u8 {
Swift:
func valueInCents(coin: Coin) -> Int {
Well, that settles it — it is known languages that use snake_case are superior.> This is because Rust is fast by default, and lets you be slow, while Swift is easy by default and lets you be fast.
Good, good, you're onto something here.
> There is a perception that Swift is only a good language for Apple platforms. While this was once true, this is no longer the case and Swift is becoming increasingly a good cross-platform language.
Sigh. But you just said defaults matter, come on. Let me paraphrase: "This is because Swift is for Apple platforms by default, while Rust is cross-platform by default."
Swift is a lovely language, but had to go with C#+Avalonia, which can give me truly multi-platform app. If only SwiftUI was properly supported on Windows, that would be great.
For now, .NET/C# + Avalonia seems the most convenient way to write Desktop apps, well, if you don't want to pay for Delphi ;)
Was this article vibe dictated?
Nah.
For UI, why would anyone choose a language that has no automatic GC that can handle cycles?
Also you might want to rework the `Box` example because you don't actually need to use `Box` in that case - the `Vec` already provides indirection.