C2Rust is an open-source project that aims to make it possible to migrate C99-compliant code to Rust. Working on this relatively new tool has also allowed its creators to learn several lessons about the way C code is written and to explore the current limitations to Rust replacing this at the ABI level.
The rationale behind c2rust is enabling the incremental migration of system software to make it more secure by removing memory corruption as much as possible. Rust is an excellent candidate for this since it combines memory safety with uncompromised speed and interoperability. In particular, since its memory handling does not rely on garbage collection or reference counting, Rust is a great fit for interoperability with C and C++ over FFI, which is often an issue with GC-ed and reference counting languages. But manually translating code is a slow and expensive process, so rust2c
tries to help with the first step.
Our goal is to build useful tools that make it easier to take existing C code and get up and running with Rust. We aim to automate much of the translation and rewriting process so that migrating legacy systems is practical and scalable with minimal manual effort.
Indeed, rust2c
seems to be able to correctly transpile even complex pieces of software such as lua, nginx and zstd that can be run without any changes. In other cases, for example with Quake 3, minor fixes are required, and in others, for example with some Linux kernel module, c2rust
may not be able to transpile the original.
In fact, though, rust2c
only provides a translation to non-idiomatic, unsafe Rust, and it could not be otherwise since C type systems hide so much relevant information required to make even basic assumptions. For example, if we take strncpy
declaration, it really requires its two arguments destination
and source
to be arrays, but its signature hides this fact behind the generic notion of a pointer to a character:
char* strncpy (char* destination, const char* source, size_t num);
This means generating safe and idiomatic Rust code still requires manual effort, since there is no easy way an automatic tool can understand that those pointers should be Rust vectors, with its compile-time safety guarantees, instead of unsafe, raw pointers.
In spite of this, rust2c
creators maintain, there is still a value in automatic translation to Rust, since it provides a base for refactoring in a language that lends itself much better to the task thanks to a stricter compiler.
Still, not all C code can be translated into correct, albeit unsafe Rust code. This does not only affect automatic transpilation, but the possibility of using Rust as an ABI-compatible replacement for C altogether. This is related to a number of issues that bar feature parity across the two languages. These include varying floating point representations found in the wild; features provided by GCC extensions such as symbol aliases, packed structures, and aligned globals; and large static library binary size. All of those are found in a number of existing C programs and libraries that c2rust
creators analyzed.
The team behind rust2c
is also working on a refactoring tool aimed at removing unsafety from rust2c
-generated code. This tool supports a large number of commands that apply refactorings, sometimes relying on specific annotations added to the non-idiomatic Rust code.
Written in Rust itself, rust2C
can be installed on Linux and macOS and require Rust nightly.