Clone Confetti
Smell. .clone() scattered through the code: clones whose result is
immediately passed by reference, clones inside loops, and clones of large
collections added to make the code compile.
for frame in frames.clone() { // whole Vec copied
let name = decoder.clone().lookup(&frame); // decoder cloned per frame
results.push(name.clone()); // name is not used again
}
Why generation produces it. A borrow-check error has two fixes: restructure the ownership, which requires understanding the whole design, or add a clone, which usually compiles immediately. An agent iterating until the code compiles tends to take the second option. Each stray clone marks a borrow error that was worked around instead of resolved. The loop, reconstructed:
let frames = load_frames();
for frame in frames { handle(frame); } // `frames` moved into the loop
let n = frames.len(); // error[E0382]: borrow of moved value
for frame in frames.clone() { .. } // the agent's fix: copy everything
for frame in &frames { .. } // the structural fix: borrow
Principle. A clone is a claim that two owners need independent copies
of the data. A stray clone is one that fails that test: the second
owner doesn’t exist. The structural fixes are to pass &T down, end the borrow earlier,
or move ownership instead of copying.
Prompt. “Remove clones that exist only to satisfy the borrow checker. Prefer borrowing. Where ownership transfer is the intent, move instead of cloning. For each clone that remains, add a one-line comment explaining why two independent copies are required.”
The comment requirement makes each remaining clone carry its own justification, for the agent and for the next reviewer. Clones without a good justification tend to disappear in the regeneration.