Skip to content
Back to skills

Rust Clone Optimization

ASecurity

Use when optimizing Rust code to remove unnecessary .clone() calls, when asked to improve memory efficiency, or when reviewing code for excessive cloning

  • 57 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 17, 2026
code-qualityrustgorefactoringapiperformance

Works with

  • api

Security analysis

A100/100

Scanned October 17, 2026

npx -y skills add diegosouzapw/awesome-omni-skill --skill rust-clone-optimization --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Rust Clone Optimization?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Rust Clone Optimization
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/diegosouzapw-rust-clone-optimization/badge)](https://www.skillsdirectory.com/skills/diegosouzapw-rust-clone-optimization)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: rust-clone-optimization
description: Use when optimizing Rust code to remove unnecessary .clone() calls, when asked to improve memory efficiency, or when reviewing code for excessive cloning
---

# Rust Clone Optimization

## Overview

Remove unnecessary `.clone()` calls by using borrowing, reordering, or minimal structural changes. **Prioritize simple solutions over clever ones.**

## When to Use

- Asked to "remove clones" or "optimize memory"
- Reviewing Rust code for efficiency
- Seeing many `.clone()` calls in hot paths

**When NOT to use:**
- `Arc::clone()` / `Rc::clone()` - these are cheap, intentional
- Cold paths with small data - optimization not worth complexity
- Prototyping phase - correctness before performance

## Analysis Hierarchy

**Try techniques in this order. Stop at the first that works.**

```
1. REORDER    → Move usage before the value is needed elsewhere
2. BORROW     → Pass &T or &str instead of owned
3. COW        → Cow<'_, str> for "sometimes owned"
4. STRUCTURAL → Change struct to hold references (last resort)
```

**Never jump to step 4 before exhausting 1-3.**

## Quick Reference

| Clone Pattern | First Try | Example |
|---------------|-----------|---------|
| Clone then move original | Reorder: use clone target first | Move `state.modal = ...` after using `login_state` |
| `.map(\|x\| x.field.clone())` | Check if caller accepts `&str` | `from_entry(entry, &name)` not `from_entry(entry, name.clone())` |
| Clone to avoid borrow conflict | Reorder operations | Extract data before mutable borrow |
| Clone in struct field assignment | Check if `Cow<str>` fits | `name: Cow<'a, str>` |
| Clone inside loop | Clone once outside | `let s = x.clone(); for _ in 0..n { use(&s) }` |

## Technique 1: Reorder

**Before:**
```rust
let username = login_state.username.clone();
let password = login_state.password.clone();
state.modal = Modal::LoginPending;  // Invalidates login_state
api.send(ApiCommand::Login { username, password });
```

**After:**
```rust
// Send BEFORE changing modal - no clone needed
let cmd = ApiCommand::Login {
    username: login_state.username.clone(),  // Still need if Login takes owned
    password: login_state.password.clone(),
};
state.modal = Modal::LoginPending;
api.send(cmd);
```

**Check:** Does `ApiCommand::Login` need owned `String`? If it accepts `&str`, remove clones entirely.

## Technique 2: Borrow

**Before:**
```rust
fn process(name: String) { println!("{}", name); }
let task_name = task.name.clone();
process(task_name);
```

**After:**
```rust
fn process(name: &str) { println!("{}", name); }  // Accept reference
process(&task.name);  // No clone
```

**When to use:** Function only reads the value, doesn't store it.

## Technique 3: Cow

**Before:**
```rust
struct Form {
    name: String,  // Always owned
}
// Must clone even for borrowed data
form.name = borrowed_str.to_string();
```

**After:**
```rust
use std::borrow::Cow;

struct Form<'a> {
    name: Cow<'a, str>,  // Borrowed OR owned
}
// No clone for borrowed
form.name = Cow::Borrowed(borrowed_str);
// Clone only when needed
form.name = Cow::Owned(compute_name());
```

**When to use:** Struct sometimes gets owned data, sometimes borrowed. Adds lifetime parameter.

## Technique 4: Structural (Last Resort)

Change struct to hold references:

```rust
// Before: owns data
struct EntryForm { task_name: String }

// After: borrows data
struct EntryForm<'a> { task_name: &'a str }
```

**Costs:**
- Adds lifetime parameters throughout
- May require significant refactoring
- Can complicate APIs

**Only use when:** Hot path with large data AND techniques 1-3 don't apply.

## Common Mistakes

| Mistake | Why It's Wrong |
|---------|----------------|
| Using `std::mem::replace` to avoid clone | Over-engineered; try reordering first |
| Removing Arc/Rc clones | These are O(1), intentional for sharing |
| Adding lifetimes everywhere | Complexity cost often exceeds clone cost |
| Optimizing cold paths | Profile first; don't optimize what doesn't matter |

## Audit Process

1. **Find clones:** `rg '\.clone\(\)'` in target directory
2. **Categorize each:**
   - Arc/Rc → Skip (intentional)
   - Hot path → Prioritize
   - Cold path → Low priority
3. **For each hot-path clone:**
   - Can I reorder? → Do it
   - Can caller accept `&T`? → Change signature
   - Need "sometimes owned"? → Use `Cow`
   - None work? → Consider if optimization is worth structural change
4. **Verify:** `cargo test` after each change

## Checklist

- [ ] Identified Arc/Rc clones (skip these)
- [ ] Prioritized by hot path vs cold path
- [ ] Tried reordering before other techniques
- [ ] Checked if callers can accept references
- [ ] Only used Cow/structural changes when simpler options failed
- [ ] Ran tests after changes
- [ ] Kept changes minimal - no over-engineering

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.