Opening line for you to use as the post subject, not part of the body:
Proposal: a fully supported Rust SDK for Sailfish, and compile-time QML diagnostics
Why I keep coming back to this
I worked with C and C++ through my career, and there is one thing I can say for sure. Using an analogy:
Writing programs in C/C++ is like navigating a mountain with unprotected cliffs, holding an instruction that says: “Please, do not fall off the cliff.”
Rust says all the time: this function has a few possible results, success is only one of them, and I will force you to handle all of them. You may have memory to work with, and I will take it back anyway; you get notified on every attempt to steal it. If you want memory outside of that scope, use my specially prepared types for that.
What Rust does and does not give you
I want to be precise here, because the marketing version of this argument is easy to attack.
- In safe Rust, memory corruption (use-after-free, buffer overflow, data race) is not something you do by accident. If it happens, the code is in an
unsafeblock, in FFI, or the compiler has a bug. That is a much stronger guarantee than “please do not fall off the cliff”. - What is still possible: panics, deadlocks, stack overflow on deep recursion, logic bugs, and everything
unsafeand FFI can do. So “a Rust application cannot crash” is not true. “Safe Rust cannot corrupt memory” is true, and that is the part that matters for a platform. - Performance is roughly on par with C++, workload by workload, and the interesting part is the predictability rather than the average. I wrote more about this below.
- The cost is real. The borrow checker slows you down at the start, and the ecosystem is younger.
The honest part: C++ has these tools too
I do not want to pretend that C++ lacks defences. RAII, unique_ptr, shared_ptr with weak_ptr, move semantics, std::span, ranges, sanitizers (ASan, TSan, UBSan), and static analysis such as clang-tidy or the MSVC analyser all exist, and a disciplined C++ codebase can be very safe. A senior C++ team has good reasons for confidence there.
The difference is not what is available, it is where the guarantee comes from:
- C++ safety is opt-in and local. A
unique_ptrprotects the pointer it owns, not the code that uses it. Ownership has to be documented, reviewed and kept in someone’s head, because the compiler cannot see intent. Any new contributor can add a leak or a dangling reference without failing the build. - Rust safety is compiler-level and global. One ownership model, enforced everywhere, and it applies across the whole dependency graph. I do not get to choose whether a library author was careful, and neither do they when they depend on me.
- Diagnostics come from the compiler, so they exist everywhere, including in the IDE. The same borrow checker, type checker and macro expansion that runs during the build runs inside the language server, which is why it can tell me which argument is wrong and how to correct it while I am still typing. In C++ I rely on documentation, hand-written annotations and clang-tidy for code I did not write. Here I get the same quality of errors for the libraries my program relies on, and those library authors got exactly the same thing in their own IDE, at the time they wrote them, whether or not they remembered to write documentation.
- Testing is part of the toolchain, not a separate purchase.
#[cfg(test)]tests are compiled by the same compiler that builds the program,cargo testruns the tests of my entire dependency tree, built-in benchmarking andclippyship with the toolchain, and the IDE can run and navigate tests. No framework to choose, no test macros to learn, no separate build configuration.
Runtime performance
This is the part I expected to be the argument against Rust, so let me be straightforward about it. Benchmarks of Rust against C and C++ typically land within a few percent of each other, faster in some workloads and slower in others, and anyone claiming a large gap in either direction is selling something.
What matters for a phone is that the number is predictable. There is no garbage collector, so no pause time, and no hidden allocation cost in the hot path, so latency does not surprise you under load. And performance becomes measurable rather than assumed: cargo bench and the built-in benchmarking support give reproducible numbers instead of arguments, and rust-analyzer warns about common mistakes, such as an accidental clone in a hot loop, long before they reach a profiler.
So the tradeoff is not “safety or speed”. The cost is the borrow checker at the beginning of a project. After that, the two goals stop competing.
The evidence, as far as I know it
Microsoft. Their research put roughly 70% of security vulnerabilities in their own code down to memory-safety issues (BlueHat, 2019). Two honest caveats: that figure is about security bugs, not about all bugs, and it is not really a verdict on Windows 7, because by then the codebase was frozen and a rewrite would not have helped.
Google / Android. Shipping Rust in production since 2021, in metadata, media, system properties, storage and Wi-Fi. They report no memory-safety vulnerabilities in the Rust code that has shipped, and they enforce a shrinking “unsafe code budget” for the rest of the platform. That is the model I would like to see used deliberately rather than opportunistically.
The ask
I am not asking Jolla to rewrite anything. C++ and QML are the reason the ecosystem exists, and keeping Sailfish OS stable across this many devices, this particular variety of devices, is a real achievement. My proposal is much narrower:
- A first-class Rust SDK. Not “you can build a crate by hand” tier, but supported: targets, cross-compilation with the existing tooling, packaging, documentation, examples, and the tooling developers expect out of the box:
cargo test, built-in benchmarking,clippy, language-server support. - QML static analysis at compile time, surfaced in the LSP. The Rust toolchain checks macros and types layer by layer and reports which argument is wrong and how it can be corrected, before you compile, and the language server shows the same while you type.
rust-analyzerandclangdalready do this well for Rust and C++. Doing the same for QML would improve the day of every Sailfish developer, and it is a far smaller ask than a language migration. - Rust where C++ cannot give guarantees. Parsers, media, network code, drivers, IPC: the places where a memory bug is most likely and hardest to reproduce.
AI-assisted development
One more thing. The era of AI-assisted development has arrived, and in the Sailfish community this can be an advantage rather than a slowdown.
In my experience, writing system and back-end applications goes much faster with AI, precisely because compiler diagnostics are informative. The compiler tells you which argument is wrong, which type does not match, and what to do about it, and the model reads those diagnostics and fixes the code. That shortens the development cycle: less time spent debugging mis(used) or mis(interpreted) data after the fact, more time spent in the editor.
So this is an argument for keeping diagnostics excellent, and for making the toolchain easy to drive for both humans and models.