From Lwn · · 1m 40s
Compiling Rust to readable C with Eurydice
Eurydice converts Rust code to clean C for high-assurance software.
In brief
Eurydice converts Rust code to clean C for high-assurance software. Eurydice compiles Rust to readable C code for high-assurance systems, preserving structure while handling Rust-specific features. Originally reported by Lwn.
Eurydice converts Rust to C
Eurydice converts Rust code to clean C code for high-assurance software where verification tools expect C.
“Eurydice has a more ambitious goal: converting Rust code to clean C code.”
Eurydice started in 2023
Eurydice began in 2023 and uses MIT and Apache-2.0 licenses as part of the Aeneas project.
“Eurydice was started in 2023, and includes some code under the MIT license and some under the Apache-2.0 license.”
Aeneas project by Inria and Microsoft
The Aeneas project, maintained by Inria and Microsoft, develops tools for formal verification of Rust code.
“It's part of the Aeneas project, which works to develop several different tools related to applying formal verification tools to Rust code.”
Eurydice compiler structure
Eurydice follows compiler structure: take Rust program, convert to intermediate representation, modify with passes, output C code.
“Eurydice follows the same general structure as many compilers: take a Rust program, convert it into an intermediate representation (IR), modify the IR with a series of passes, and then output it as code in a lower-level language (in this case, C).”
Preserving Rust code structure
Eurydice preserves Rust code structure by removing Rust-specific constructs while maintaining evaluation order.
“Unlike other compilers, however, Eurydice is concerned with preserving the overall structure of the code while removing constructs that exist in Rust but not in C.”
Example: gcd and lcm functions
Eurydice compiles Rust gcd and lcm functions to C with temporary variables to preserve evaluation order.
“Here's how Eurydice compiles those functions to C: uint64_t example_gcd(uint64_t a, uint64_t b) { ... }”
C code readability
The generated C code is readable but requires temporary variables to maintain Rust's evaluation order.
“It does, however, preserve the structure of the code. Even the evaluation order of the original is preserved by adding extra temporary variables (uu____0 in example_lcm()) where necessary.”
Rust to C limitations
Eurydice cannot handle Rust's iterators and generics, requiring monomorphization and temporary code.
“For example, for loops that use an iterator instead of a range need to be compiled to while loops that call into some of Eurydice's support code to manage the state of the iterator.”
Dynamically sized types
Eurydice handles dynamically sized types with flexible array members and known-length arrays.
“Eurydice emits two different types: a version of the dynamically sized type that has a flexible array member, and one that has a known-length array member.”
Formal verification challenges
Preserving dynamic type sizes is critical for formal verification to avoid false bounds checks.
“If Eurydice compiled DynamicallySized to use a flexible array member everywhere, analysis of the C code might point out 'missing' bounds checks that were not required in Rust.”
Eurydice's current limitations
Eurydice works best for small, self-contained Rust programs without complex features.
“In its current form, Eurydice works best for small, self-contained programs that avoid complex Rust features.”
Eurydice's future potential
Eurydice could help bridge Rust and C ecosystems for high-assurance software.
“Eurydice is only the newest tool in a rapidly expanding collection of ways to fold, spindle, and mutilate Rust code to fit into more environments.”
What matters most
Eurydice compiles Rust to readable C code for high-assurance systems, preserving structure while handling Rust-specific features.





