The languages have a shared legacy and feel quite similar in certain aspects, with Swift being a higher level adaptation.
Swift is a lot easier to use, with automatic reference counting, quite a bit more convenience and syntax sugar, and a class system.
It's a lovely language.
It lacks what are the defining features of Rust (for me) though: low level control available when required but usually hidden behind nice abstractions, borrow checker, concurrency safeguards (Send/Sync in Rust), trait system over classes, and a good macro system.
The biggest conceptual downside for me is the class system with inheritance, overrides, etc: Rust has traits that are somewhat similar to Haskell type classes, and are much nicer and more coherent to use in many domains. (it's far from perfect, especially around the severely limited trait objects and dynamic dispatch, but that is a longer topic)
The biggest practical downsides are Apples disregard for other platforms (Linux/Windows are very much second/third class citizens) and the Objective-C compatibility baggage, which makes the language a bit messy.
But overall I think it is easy to like and appreciate both languages.
> The biggest practical downsides are Apples disregard for other platforms.
This is unfortunately true, but I see Swift committee making serious efforts to overcome that. I hope it gets better with time. Swift on Backend (vapor/Kitura) are simply ages behind Actix.
Another language that's syntactically close is Kotlin/native, even though it has quite different goals. These 3 languages have brought much excitement to development in the past few years.
How so? Swift has a stable ABI that, among other things, enables it to expose FFI bindings to many other languages. Rust has made the pragmatic choice of having no stable FFI beyond the C one, so if you want to setup FFI to a Rust library you'll have to write C-compatible wrapping code in Rust and expose that.
It's pretty rare for a language to have a stable ABI, no? I mean Rust still doesn't have one.
Swift's ClangImporter does this automatically in the language via clang modules, unlike Rust's bindgen.
It's worth noting that improved and cross-platform support is a stated priority for the next Swift version. It's already quite usable on Ubuntu, and Windows and other Linux distros beyond Ubuntu have been added to the CI pipeline for Swift development.
What I love about Swift is that it's an incredibly expressive language which is easy to write, so it's possible to be incredibly productive in it. The type system is awesome, the syntax is super clean and consistent, and thanks to a lot of well-thought-out syntactic sugar it often feels like I'm almost working in a DSL for the problem I'm working on.
What I miss from Rust when working with Swift is the level of specificity. Swift makes some assumptions about how values and references are handled, which makes things easy to code, but can often result in unnecessary copying and reference counting which can only be avoided by bending over backwards in the implementation or resorting to the unsafe API. I like how Rust gives me precise tools for specifying exactly how memory should be handled.
To be honest, I think my perfect language would have something like Swift's front-end, and something like Rust's memory model.
There is/was talk of trying to either do escape analysis or add some hints so the compiler can get rid of those checks but AFAIK that hasn't happened yet?
Modern idiomatic swift uses reference types quite sparingly, and Swift can be quite performant, but usually requires prolific use of profiling and optimization to get there.
Best case performance for Rust will probably always be better, because even for statically managed types, Swift leans more heavily toward copying values where Rust tries to leave them in place whenever possible.
I agree that ARC is probably an obstacle for Swift to overcome in the long term. There have been some interesting discussions in the Swift forums around this, and there may be some solutions, like for instance the compiler being smarter about knowing when ARC is truly necessary, and replacing it with simple RC when, for instance, an object never leaves the thread where it was created, which is probably true of a majority of objects.
Probably this can be addressed when Swift's ownership model is more mature, and when the concurrency model has been formally defined.
I looked at it briefly and I liked it a lot, but does it have a future as a platform-independent language?
Currently it's only officially supported on macOS and Ubuntu, but the next major release (5.3) will add official support for Windows and more linux distros.
Tooling still has a ways to go. XCode is still the best way to write Swift, but, SublimeText, vim and VSCode are usable with Swift thanks to LSP support.