<< All versions

Skill v1.0.0

currentAutomated scan100/100
kewang0622/clonetax/rust-ownership
──Details
PublishedSeptember 27, 2026 at 02:16 AM
Content Hashsha256:d0d0fc7acf099a5b...
Git SHA52877ad1cffc
──Files
Files (1 file, 3.6 KB)
SKILL.md3.6 KBactive
SKILL.md · 72 lines · 3.6 KB

version: "1.0.0" name: rust-ownership description: Stops coding agents from "fixing" Rust borrow-checker errors with .clone(), Arc, RefCell or Box::leak when the real fix is to restructure ownership. Use when writing or repairing Rust code, when rustc reports E0382, E0499, E0502, E0506, E0515 or E0597, when a borrow checker error must be resolved, or when reviewing Rust code for unnecessary clones and allocations. license: MIT metadata: author: KeWang0622 evidence: EVIDENCE.md


Rust ownership — do not clone your way out

When rustc rejects your code with a borrow or move error, it usually gives you nothing to act on: on 5 of the 6 cases in this repo's corpus it emits no help and no note at all. In the one case where it does offer a help, that help is "consider cloning the value".

So the path of least resistance is to clone until it compiles. Do not take it. Cloning to escape a borrow conflict does not fix the conflict — it makes two objects where the code assumed one.

The rule

Never introduce `.clone()`, `Arc`, `Rc`, `RefCell` or `Box::leak` for the purpose of silencing a compiler error. Those are designs, not fixes. Reach for them only when the design genuinely calls for shared or owned data, and say so explicitly.

When you hit a borrow error, work in this order:

  1. Shorten the borrow. Bind only what you need (a bool, a usize, an owned

key) inside a tight scope so the borrow ends before the conflicting use.

  1. Change the signature. If a callee only reads, take &T / &str instead of T.
  2. Sequence the accesses. Do the read, finish with it, then do the write.
  3. Use the API built for it. entry, split_at_mut, indices, std::mem::take.
  4. Only then consider owning the data — and when you do, say in one sentence why

sharing or copying is the right design, not just what made the error go away.

Per-error playbook

CodeWhat it meansDo NOTDo
E0382Value used after being movedPass x.clone()Take &T in the callee
E0499Two mutable borrows at onceClone the collectionSequence them, or split_at_mut
E0502Mutable borrow while immutably borrowedClone the looked-up valueEnd the read in a tight scope, or use entry
E0506Assign to a borrowed valueClone the structShorten the reference's lifetime
E0515Return a reference to a localBox::leakReturn the owned value
E0597Borrow outlives its referentWrap in Rc<RefCell<_>>Restructure so the value outlives the borrow

The one that actually bites

E0499 and E0502 are the dangerous ones. Cloning there compiles cleanly, passes tests, and is silently wrong: the two halves of the code now mutate different objects, so writes through one are invisible to the other.

clippy::redundant_clone will not save you. It only fires when the original is never used again. In exactly these cases the original is still used — that is why the borrow conflicted — so clippy stays silent.

When cloning IS right

Cloning is not banned. It is correct when the data genuinely needs independent ownership: sending a value to another thread, storing a snapshot that must not change, or when profiling shows the copy is cheap and the restructure is not worth it. The test is whether you can state the reason without referring to the compiler error.

Evidence

Every claim above comes from compiling the programs in corpus/ with a real rustc and reading --error-format=json. See EVIDENCE.md, which is generated by node scripts/extract.mjs and re-verified in CI.

All versions