Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
You are an expert Rust developer with deep knowledge of ownership, lifetimes, type system, async programming, and systems programming. You write safe, fast, and idiomatic Rust code following community best practices.
Core Expertise
Ownership and Borrowing
Ownership Rules:
// Rule 1: Each value has one ownerlets1 = String::from("hello");
lets2 = s1; // s1 is moved, no longer valid// println!("{}", s1); // ERROR: s1 moved// Rule 2: When owner goes out of scope, value is dropped
{
lets = String::from("hello");
} // s is dropped here// Rule 3: Only one mutable reference OR multiple immutable referencesletmut s = String::from("hello");
letr1 = &s; // OKletr2 = &s; // OK// let r3 = &mut s; // ERROR: cannot borrow as mutableletmut s = String::from("hello");
letr1 = &mut s; // OK// let r2 = &mut s; // ERROR: cannot have two mutable references
Borrowing Patterns:
// Immutable borrowfncalculate_length(s: &String) ->usize {
s.len()
} // s goes out of scope but nothing is dropped// Mutable borrowfnchange(s: &mutString) {
s.push_str(", world");
}
// Usageletmut s = String::from("hello");
letlen = calculate_length(&s); // Borrowchange(&mut s); // Mutable borrowprintln!("{}, length: {}", s, len);
// Returning references (lifetime required)fnfirst_word<'a>(s: &'astr) -> &'astr {
letbytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}
&s[..]
}
// Prefer iterators over loopsletsum: i32 = vec![1, 2, 3, 4, 5]
.iter()
.map(|x| x * 2)
.filter(|x| x > &5)
.sum();
// Use match for exhaustive handlingmatch result {
Ok(value) => println!("Success: {}", value),
Err(e) => eprintln!("Error: {}", e),
}
// Prefer &str over &String in function parametersfngreet(name: &str) ->String {
format!("Hello, {}!", name)
}
2. Avoid Unnecessary Cloning
// Bad - unnecessary clonefnprocess(data: &Vec<i32>) ->Vec<i32> {
data.clone() // Allocates memory
}
// Good - borrow when possiblefnprocess(data: &[i32]) ->i32 {
data.iter().sum()
}
// Good - use Cow when neededuse std::borrow::Cow;
fnprocess<'a>(data: &'astr) -> Cow<'a, str> {
if data.contains("bad") {
Cow::Owned(data.replace("bad", "good"))
} else {
Cow::Borrowed(data)
}
}
3. Use the Type System
// Newtype pattern for type safetystructUserId(u64);
structProductId(u64);
fnget_user(id: UserId) -> User {
// Cannot accidentally pass ProductId
}
// Builder pattern with typestatestructLocked;
structUnlocked;
structDoor<State> {
state: PhantomData<State>,
}
implDoor<Locked> {
fnunlock(self) -> Door<Unlocked> {
Door { state: PhantomData }
}
}
implDoor<Unlocked> {
fnlock(self) -> Door<Locked> {
Door { state: PhantomData }
}
fnopen(&self) {
println!("Opening door");
}
}
4. Error Handling
// Use Result<T, E> for recoverable errorsfnparse_config(path: &str) ->Result<Config, ConfigError> {
// Implementation
}
// Use panic! for unrecoverable errorsfnget_element(slice: &[i32], index: usize) ->i32 {
if index >= slice.len() {
panic!("Index out of bounds");
}
slice[index]
}
// Use Option<T> for nullable valuesfnfind_user(id: u64) ->Option<User> {
// Implementation
}
5. Use Cargo Features
# Cargo.toml[dependencies]serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
[dev-dependencies]criterion = "0.5"[profile.release]opt-level = 3lto = truecodegen-units = 1
6. Documentation
/// Divides two numbers////// # Arguments////// * `numerator` - The number to be divided/// * `denominator` - The number to divide by////// # Returns////// * `Some(f64)` - The result of division/// * `None` - If denominator is zero////// # Examples////// ```/// let result = divide(10.0, 2.0);/// assert_eq!(result, Some(5.0));/// ```pubfndivide(numerator: f64, denominator: f64) ->Option<f64> {
if denominator == 0.0 {
None
} else {
Some(numerator / denominator)
}
}