While C and C++ remain the backbone for embedded programming, there are alternatives that often offer improvements in areas such as productivity, safety, and reliability while providing low-level control and resource management. One of the newer alternatives is Rust, an emerging programming language designed to be a “safe, concurrent practical language.” It is designed to provide safe memory utilization without the need for transparent garbage collectors like those used with Java.
Rust includes features like pattern matching, trait-based generics, and zero cost abstractions, but its claim to fame centers around its guaranteed memory safety and threads without data races. Memory and multitasking tend to be areas that can cause problems with C and C++ applications due to their less restrictive compilers.
Rust was started by Mozilla, the organization that brings you the Firefox web browser. Rust now has its own open source community. You can download compilers, documentation and tools at the Rust website. The community is quite active, but commercial compiler support is where there is a vast gulf between Rust and established languages like C and C++.
Rust gets its memory safety support through language semantics. For example, variables are immutable by default versus C and C++ (and most imperative programming languages) where variables are mutable by default. Variables can be explicitly defined as mutable.
Functional programming languages like Haskell also have immutable variables, although they include the ability to pass around variables that may get a value at a later time. One reason for having immutable variables is that it makes proving aspects of a program easier. It also improves readability of code, which can be important in code reviews as well as maintenance. Immutability also has implications in caching and parallel processing.
In addition, Rust has stricter semantics when it comes to pointers, the bane of C programmers. Rust has the concept of owners and borrowers of pointers. Borrowed pointers can be passed as arguments, but they do not have the arbitrary exchangability of C pointers because Rust enforces lifetimes. Rust tracks the lifetime of data that is referenced and will not allow borrowed pointers to be used where the lifetime of the items referenced has expired. For example, returning a pointer to a function’s local variable would not be allowed. These kinds of errors are common in C applications that assume the programmer knows what they are doing.
The Rust compiler does a lot more checking than C or C++ because of Rust’s semantics, but it does not do the formal proof checking often required for safety critical applications. This type of checking is available in SPARK, a subset of Ada, and there are verification tools and methodologies that are used with C and C++ in safety and security critical environments, but these typically augment manual certification.
The RustBelt project is designed to provide formal proof checking for a subset of Rust. “RustBelt: Securing the Foundations of the Rust Programming Language,” a paper by Ralf Jun, Jacques-Henri Jourdan, Robbert Krebbers, and Derek Dreyer, presents an overview of Rust, as well as what formal proofs can be applied and how this is done. The proof checking has been applied to a number of Rust libraries and there is more work to be done. It is a good first step that will be needed when Rust is used in safety critical applications.
I did mention SPARK earlier, but it’s worth repeating here as SPARK already incorporates formal proof checking in commercially based compilers, as well as open source implementations. SPARK is a subset of Ada 2012. Both incorporate Ada contracts. Rust has a syntax that is more similar to C and C++, but SPARK and Ada tend to have semantics more in line with C and C++.
Rust has an active and robust community. It is being used in many projects, and research in areas like self-driving cars are taking advantage of it as well. I do not know of any commercial embedded applications that are using Rust at this point.
C and C++ developers who are looking for comparable support should examine the numerous static analysis products available. This will not provide the same level of support that Rust or SPARK will, but they provide significantly more support than is built into any C or C++ compiler. They are very good alternatives to migrating to a new programming language.