RustAssistant: Using Large Language Models to Automatically Fix Rust Compilation Errors
Rust’s memory safety guarantees come at a cost: a steep learning curve that challenges even experienced developers. Microsoft Research has developed RustAssistant, a tool that leverages Large Language Models to automatically fix Rust compilation errors with remarkable accuracy.
The Rust Learning Challenge
Rust’s ownership-based type system prevents memory safety errors and data races, but creates complex compilation errors that intimidate newcomers. A recent Rust team survey found that 83% of developers adopting Rust at work found it challenging, with 27% saying it’s “at times a struggle.”
Consider this common error where a function tries to return a reference to a temporary value:
| |
The Rust compiler rejects this code because the returned reference outlives the mutex guard lifetime—a violation of borrowing rules that confuses many developers.
How RustAssistant Works
RustAssistant combines careful prompt engineering with iterative compiler interaction to generate accurate fixes. The tool follows this process:
- Compile and capture errors: Run the Rust compiler to collect error messages
- Localize relevant code: Extract ±50 lines around error locations
- Generate fixes: Send code and errors to an LLM with structured prompts
- Apply and validate: Parse the LLM response, apply changes, and recompile
- Iterate if needed: Handle cascading errors from initial fixes
The Changelog Format
RustAssistant’s key innovation is a structured changelog format that keeps LLMs focused on specific code changes rather than rewriting entire functions:
ChangeLog:1@src/example.rs
FixDescription: Change the return type to Arc<Bar> and wrap values in Arc
OriginalCode@19-23:
[19] impl Foo {
[20] pub fn get(&self, key: String) -> &Bar {
[21] self.map.write().unwrap().entry(key).or_insert(Bar::new())
[22] }
[23] }
FixedCode@19-24:
[19] impl Foo {
[20] pub fn get(&self, key: String) -> std::sync::Arc<Bar> {
[21] self.map.write().unwrap().entry(key).or_insert_with(
[22] || std::sync::Arc::new(Bar::new())).clone()
[23] }
[24] }
This format significantly improves accuracy by preventing the LLM from making unrelated changes.
Impressive Results
RustAssistant achieves remarkable accuracy across different datasets:
- Micro-benchmarks: 93% success rate (252/270 error codes)
- Stack Overflow questions: 74% success rate (37/50 programs)
- Real-world repositories: 74% success rate (134/182 commits from top-100 Rust crates)
The tool outperforms cargo fix, Rust’s built-in repair tool, by a significant margin. While cargo fix handles only pattern-based fixes, RustAssistant generates complex solutions requiring deep understanding of Rust concepts.
Beyond Simple Pattern Matching
RustAssistant demonstrates sophisticated understanding of Rust idioms. For the example above, it correctly suggests using Arc<Bar> for shared ownership—the same solution accepted on Stack Overflow. The tool handles:
- Ownership and borrowing: Converting between owned values and references
- Lifetime management: Adjusting function signatures and data structures
- Concurrency patterns: Using appropriate synchronization primitives
- Memory management: Applying
ManuallyDropormem::forgetwhen needed
Practical Implementation
The tool requires minimal setup and integrates into existing Rust workflows. For the top-100 crates benchmark, RustAssistant:
- Averages 10 LLM queries per commit
- Costs approximately $1.20 per commit with GPT-4
- Completes fixes in under 5 minutes (excluding API throttling)
Expanding Beyond Compilation Errors
RustAssistant’s approach generalizes to other static analysis tools. When applied to Clippy linting errors, it achieves 75% accuracy—2.4 times better than Clippy’s built-in auto-fix feature.
Key Takeaways
RustAssistant proves that LLMs can effectively handle domain-specific programming challenges when combined with:
- Structured output formats that focus model attention
- Iterative validation through compiler feedback
- Careful prompt engineering that provides relevant context
- Error grouping strategies that handle cascading fixes
The tool represents a significant step toward AI-assisted programming that understands complex language semantics, not just syntax patterns.
For Rust developers struggling with compilation errors, RustAssistant offers hope: intelligent assistance that understands the “why” behind Rust’s strict rules and suggests semantically correct solutions.