A Rust compiler written in PHP that emits x86-64 Linux ELF binaries directly (no LLVM, no assembler, no linker). Implements ownership checking, borrow checking, type checking, move semantics, generics, traits, closures, and iterators. Useful if you need to compile Rust on a shared hosting server from 2008 where the only installed runtime is PHP.
In order to execute Rust code you of course first need to install PHP. You can do this easily on Windows 11 by running:
winget install PHP.PHP.8.4
This compiler outputs valid machine code for Linux, so the most practical approach if you're on Windows is to use WSL. Start by installing Ubuntu (if you haven't already):
After the install completes, reboot your machine and then open Ubuntu from the Start menu to finish the initial setup.
Compile a .rs file by running:
php rustc.php main.rs -o main
Then execute the compiled binary through WSL:
To see the exit code of the program:
Types
i32,bool,u8,u16,u32,u64,u128,usizeString(heap string, move semantics)&strand string slice indexing (s[0])&T,&mut Treferences with borrow checking- Structs (named fields, field access, method calls)
- Enums with optional tuple payloads and
match - Unit type
()in expressions, return types, and generic arguments - Generics on functions, structs, and
implblocks - Builtin
Option<T>andResult<T, E>withSome/None,Ok/Err(no source definitions required)
Control flow
if/else(including as expressions)while,loop,break,continuefor x in start..end(range iteration)matchwith enum arms and wildcard_return
Functions and closures
- Free functions with multiple parameters and explicit return types
const fn(accepted and treated as a regular function)implblocks withself,&self,&mut self- Trait definitions and
impl Trait for Type - Default trait method implementations
- Closures with capture-by-value (
|x: i32| x + captured_var)
Ownership and borrowing
- Move semantics for non-
Copytypes - Borrow and mutable borrow checking
Copyinference fori32,bool,&T, and all-copy structs/enums
Modules and syntax
mod name;declarations with file-based module resolutionpubvisibility on functions, structs, and fieldsusepaths for cross-module imports- Attributes
#[...]and#
Output
println!("{}", expr)— print a single valueexit(code)— explicit exit with status code
Run the full test suite:
Test cases live in tests/cases/ organized into fundamentals/valid/, fundamentals/invalid/, modules/, and programs/. Each .rs file declares its expected output in comments at the top:
// exit: 42
// stdout: hello
// error: Use of moved valueRoughly in order of impact:
- Compound assignment operators (
+=,-=,*=,/=) - Tuples and tuple destructuring
Vec<T>and heap allocationf32/f64floating pointconstandstaticitems- The
?operator (Result is supported;?is not) - Closures as function arguments (
fn apply(f: impl Fn(i32) -> i32)) - Zero-parameter closures (
|| expr) - Pattern matching beyond single-level enum variants
- Multi-format
println!(only"{}"with one argument is supported) - Lifetimes (borrow checker is simplified — no lifetime annotations)
- Additional signed integer types (
i8,i16,i64,i128)