The best Rust prompts paste the full compiler error with its error code, show enough code to see who owns what, and forbid the lazy fixes (an extra clone(), an unwrap(), a lifetime added at random) that make the error go away without solving it. Below are 12 Rust prompts for ChatGPT, Claude, Claude Code and Codex covering the borrow checker, error handling, idiomatic code, concurrency, unsafe code and maintenance.
For general jobs such as explaining code, writing a regex or a commit message, see the coding prompts. The prompts here are specific to Rust.
How to use these prompts
Copy a prompt, replace each blank in double braces, or keep the default after the colon. {{edition:2021}} means the 2021 edition unless you change it.
Three habits make the answers better:
- Paste the whole error, with the code. Most Rust errors include an error code, and each code has a page in the compiler error index. E0502, for example, means a value "already borrowed with a certain mutability (either mutable or immutable) was borrowed again with a different mutability."
- Say your edition and toolchain. Editions change some rules, so tell the model which one
Cargo.tomlsets. - Ask for the reason before the fix. A model that explains the ownership problem first is far less likely to paper over it with
clone().
In an agent, let it run cargo check after every change; the compiler is the best reviewer you have.
How do you fix borrow checker errors with AI?
1. Explain a compiler error
For any error you don't understand yet. The Rust Book's rules of references are short: at any given time you can have either one mutable reference or any number of immutable references, and references must always be valid.
Explain this Rust compiler error, then fix it.
Error (full output, including the error code):
{{error}}
Code:
{{code}}
1. Who owns each value involved, and where each borrow starts and ends.
2. Which rule the code breaks, in plain language.
3. The fix that changes the design the least. Do not add clone(),
unwrap(), Rc or RefCell unless you explain why the simpler options don't
work.
2. Remove unnecessary clones
For code that compiles only because clone() was sprinkled everywhere. Each removed clone is a real allocation saved.
This Rust code compiles but calls clone() in many places, probably to get
past the borrow checker:
{{code}}
For each clone, decide whether it is needed. Where it isn't, replace it
with a borrow, a move, or a change in function signature (for example
taking &str instead of String). Keep every clone that is truly needed and
say why. Do not change public signatures unless I agree: {{public_api:keep the public API as is}}.
3. Fix lifetime errors in a struct
For structs that hold references and the "does not live long enough" errors that follow. Often the better answer is to own the data.
I have a Rust struct that holds references, and I get lifetime errors:
{{code}}
Error:
{{error}}
Explain what the lifetimes in the error mean for this code. Then give two
options: (a) fix the lifetime annotations, and (b) change the struct to own
its data. Compare them on simplicity, performance and how callers use the
struct, and recommend one for {{use_case:a short-lived parser}}.
How do you handle errors in Rust?
4. Replace unwrap with proper error handling
For prototypes that panic on bad input. The Rust Book chapter on Result explains that ? returns early with the error, converts it through the From trait, and only works in functions whose return type is compatible.
Replace every unwrap() and expect() in this Rust code with proper error
handling, unless a panic is truly correct (then keep expect with a
message saying why it can't fail).
- Propagate errors with ? and change function signatures to return Result.
- Add context so the final error says what was being done.
- Use {{error_crate:only the standard library}} for error types.
- Convert between Option and Result explicitly where needed (ok_or,
ok()).
{{code}}
5. Design an error enum for a library
For crates others depend on. Callers need to match on error kinds, not parse strings.
Design the error type for this Rust library: {{library_description}}.
Callers need to tell apart: {{cases:I/O failure, invalid input, not found}}.
Write an error enum with Display and std::error::Error implementations,
From conversions for the underlying errors, and source() returning the
cause where there is one. Mark it non_exhaustive if new variants are
likely, and explain the trade-off. Show how a caller matches on it.
How do you write idiomatic Rust?
6. Port code to idiomatic Rust
For moving a module from another language. Line-by-line ports fight the borrow checker; designs built around ownership don't.
Port this {{from:Python}} code to idiomatic Rust, edition {{edition:2021}}.
- Design the data around ownership first: who owns what, and what is
borrowed.
- Use enums and match for variants instead of class hierarchies or flags.
- Return Result for anything that can fail.
- Use iterators where they read better than index loops.
- Standard library only unless a crate is clearly better; list any crate
and why.
After the code, list behavior differences, such as integer overflow,
string indexing and how errors surface.
{{code}}
7. Work through Clippy warnings
For a long list of lints. The Clippy book says there are over 800 lints, sorted into groups such as correctness, suspicious, style, complexity and perf, with stricter groups like pedantic off by default. If you don't have it, the Clippy installation page gives the command rustup component add clippy.
Here is the output of cargo clippy for my crate:
{{clippy_output}}
Code:
{{code}}
Group the warnings by lint. For each lint, explain in one sentence what it
catches, show the fix, and say whether the change could alter behavior.
Fix correctness and suspicious lints first. If a lint is a false alarm
here, show how to allow it at the narrowest scope with a comment explaining
why.
8. Rewrite loops with iterators
For index-heavy loops that are hard to read. Asking about performance keeps the model honest about allocations.
Rewrite these Rust loops using iterator adapters (map, filter, fold,
zip, windows, chunks and so on) where it makes the code clearer:
{{code}}
Keep loops where an iterator chain would be harder to read, and say why.
Point out any place where the new version allocates more (for example an
extra collect) or changes the order of side effects.
How do you write concurrent and unsafe Rust safely?
9. Share state across threads or tasks
For "cannot be sent between threads safely" errors and the question of whether to use a mutex or channels.
I need to share {{state:a cache of user sessions}} between {{workers:several threads}}
in Rust. Current code and error:
{{code}}
{{error}}
Compare these options for my case: Arc with Mutex or RwLock, message
passing with channels, and restructuring so each thread owns its data.
Recommend one, show the code, and explain which traits (Send, Sync) make
it compile. Point out any place a lock is held across a slow call or an
await.
10. Review an unsafe block
For FFI code and performance hacks. The Rust Book chapter on unsafe Rust lists five things unsafe allows, such as dereferencing a raw pointer and calling an unsafe function, and describes Miri, an official Rust tool that detects undefined behavior at runtime.
Review this unsafe Rust code.
{{code}}
1. List every operation that needs unsafe and the invariant each one
relies on.
2. Say whether callers can break those invariants through the safe API.
3. Write a SAFETY comment for each unsafe block.
4. Suggest a safe alternative if one exists with acceptable cost.
5. Write tests to run under Miri (cargo +nightly miri test) that exercise
the risky paths.
How do you test and maintain Rust code?
11. Write tests, including doc tests
For library code. Doc tests double as examples in the generated documentation.
Write tests for this Rust module.
{{code}}
- Unit tests in a #[cfg(test)] module, one behavior per test, with names
that say what is checked.
- Cover edge cases: empty input, boundaries, invalid input and every error
variant.
- Add a doc test example to each public function showing typical use.
- Use {{style:assert_eq! with clear messages}}.
12. Migrate to the 2024 edition
The 2024 edition shipped with Rust 1.85.0. The Edition Guide's migration steps are cargo update, cargo fix --edition, setting the edition in Cargo.toml, then cargo build or cargo test. It notes that the automatic migration does not update doctests.
I ran cargo fix --edition to move this crate from edition {{from:2021}} to
2024. These warnings or errors remain:
{{output}}
Code they point to:
{{code}}
For each one, explain which edition change causes it and show the manual
fix. Then list anything cargo fix can't migrate that I should check by
hand, including doctests and macros, and tell me which claims to confirm
in the Edition Guide.
What should you check before you accept the answer?
AI-written Rust tends to go wrong in the same few places, so check these every time:
- New clones and unwraps. Search the diff for
clone(),unwrap()andexpect(that weren't there before. - Rc and RefCell. They are sometimes right, but often a sign the model gave up on ownership. Ask why.
- Unsafe. Any new
unsafeblock needs a SAFETY comment and a reason a safe version won't do. - Real compiler output. Run
cargo check,cargo clippyandcargo testyourself, or have an agent run them and paste the results.
Turn your favorite one into a skill
When one of these prompts becomes a daily habit, make it a skill so Claude Code or Codex uses it automatically. The compiler error and unwrap prompts are good first candidates. Paste one into the free SKILL.md generator, which needs no sign-up, and it becomes a valid SKILL.md. For reviewing unsafe or security-sensitive code more broadly, see the security review prompts. For a garbage-collected alternative, see the golang prompts.
To keep prompts like these close, save them in Kipt. Your library lives as Markdown in a private GitHub repo you own, each blank stays fillable when you copy, and Cmd+K finds any prompt by name or tag.