Habr AI→ original

LLMs write Rust with seven categories of hidden errors the compiler doesn’t catch

A developer used Claude, GPT, and Cursor for six months as a second Rust developer. Seven types of hidden errors were identified: lifetime laundering, Mutex in

LLMs write Rust with seven categories of hidden errors the compiler doesn’t catch
Source: Habr AI. Collage: Hamidun News.
◐ Listen to article

A developer spent six months using Claude, GPT, and Cursor as a full-fledged second Rust programmer in production code. Over this period, he carefully tracked errors and compiled an impressive list: seven categories of errors that LLMs make systematically. The most troubling part — these errors pass the compiler, unit tests, and even the static analyzer clippy. Yet they violate memory safety or destroy the application architecture.

Seven Types of Hidden Errors

Here are the categories that LLMs break again and again:

  • Lifetime laundering — variables live longer than Rust's type system allows. This leads to use-after-free at runtime.
  • Mutex through await — a lock that holds the mutex during asynchronous waiting. Guaranteed deadlock.
  • Drop in transactions — forget to call drop when needing to close a resource (close a file, roll back a transaction). Resource leaks.
  • Unaligned read — memory dereference with incorrect alignment. Processor crashes on ARM, silently breaks on x86.
  • Async cancellation — improper cancellation of asynchronous operations. Leaves suspended states.
  • Orphan rule — violation of the orphan rule when implementing traits. Compiles in one project, breaks when adding a dependency.
  • Arrays on the stack — allocating huge arrays on the stack (instead of the heap). Stack overflow, segfault.

Why This Is Dangerous for Production

The whole point of Rust is that the compiler catches errors during development, not in production. But these seven errors slip past the compiler — because they don't violate syntax or formal typing rules. As a result, the code compiles without warnings, passes unit tests, runs through clippy, and ships to production. Everything breaks there, but it's too late. This is worse than an explicit compiler error, because the developer is confident that everything is fine.

Why LLMs Break This

Rust is a marginal language in the LLM dataset. Python, JavaScript, and Java account for 70% of the code that models were trained on. Rust — maybe 2-3%. Moreover, Rust requires deep understanding of ownership, lifetimes, and the type system, which LLMs understand only superficially. Models see patterns and copy them. They know that 'you usually write it this way,' but don't know why it works in Java and breaks in Rust. So they reproduce patterns incorrectly, creating an illusion of compilable code.

Rust breaks LLMs because it's a language where you have to think, not

just copy patterns.

Practical Conclusions

The developer doesn't advise abandoning LLMs entirely, but recommends:

  • Don't rely on LLMs for critical sections: cryptography, memory operations, concurrency
  • Require formal code review even if the compiler doesn't complain
  • Use Miri — an interpreter that catches undefined behavior during development
  • Learn Rust well enough to either write code yourself or be able to find bugs in LLM code

What This Means

LLMs are a useful tool, but not a replacement for humans. In dynamic languages, they work well (Python, JavaScript), because there are fewer rules that need to be understood intuitively. In Rust, you either need to check every line or keep humans in the decision loop. For frameworks like Next.js or Django, an LLM assistant is a powerful accelerator. For Rust in production, it's more of a draft for human review than a full colleague.

ZK
Hamidun News
AI news without noise. Daily editorial selection from 400+ sources. A product by Zhemal Khamidun, Head of AI at Alpina Digital.
What do you think?
Loading comments…