agy-superpowers 5.2.2 → 5.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/README.md +47 -150
  2. package/package.json +1 -1
  3. package/template/agent/rules/scratch-scripts.md +37 -0
  4. package/template/agent/rules/superpowers.md +4 -51
  5. package/template/agent/skills/ai-integrated-product/SKILL.md +0 -57
  6. package/template/agent/skills/analytics-setup/SKILL.md +0 -51
  7. package/template/agent/skills/api-design/SKILL.md +0 -193
  8. package/template/agent/skills/app-store-optimizer/SKILL.md +0 -127
  9. package/template/agent/skills/auth-and-identity/SKILL.md +0 -167
  10. package/template/agent/skills/backend-developer/SKILL.md +0 -148
  11. package/template/agent/skills/bootstrapper-finance/SKILL.md +0 -55
  12. package/template/agent/skills/chrome-extension-developer/SKILL.md +0 -53
  13. package/template/agent/skills/community-manager/SKILL.md +0 -115
  14. package/template/agent/skills/content-marketer/SKILL.md +0 -111
  15. package/template/agent/skills/conversion-optimizer/SKILL.md +0 -142
  16. package/template/agent/skills/cto-architect/SKILL.md +0 -133
  17. package/template/agent/skills/customer-success-manager/SKILL.md +0 -126
  18. package/template/agent/skills/data-analyst/SKILL.md +0 -147
  19. package/template/agent/skills/devops-engineer/SKILL.md +0 -117
  20. package/template/agent/skills/email-infrastructure/SKILL.md +0 -164
  21. package/template/agent/skills/game-design/SKILL.md +0 -194
  22. package/template/agent/skills/game-developer/SKILL.md +0 -175
  23. package/template/agent/skills/growth-hacker/SKILL.md +0 -122
  24. package/template/agent/skills/idea-validator/SKILL.md +0 -55
  25. package/template/agent/skills/indie-legal/SKILL.md +0 -53
  26. package/template/agent/skills/influencer-marketer/SKILL.md +0 -141
  27. package/template/agent/skills/landing-page-builder/SKILL.md +0 -59
  28. package/template/agent/skills/launch-strategist/SKILL.md +0 -62
  29. package/template/agent/skills/market-researcher/SKILL.md +0 -53
  30. package/template/agent/skills/micro-saas-builder/SKILL.md +0 -56
  31. package/template/agent/skills/monetization-strategist/SKILL.md +0 -119
  32. package/template/agent/skills/paid-acquisition-specialist/SKILL.md +0 -119
  33. package/template/agent/skills/pricing-psychologist/SKILL.md +0 -58
  34. package/template/agent/skills/real-time-features/SKILL.md +0 -194
  35. package/template/agent/skills/retention-specialist/SKILL.md +0 -123
  36. package/template/agent/skills/rust-developer/SKILL.md +0 -281
  37. package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +0 -231
  38. package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +0 -124
  39. package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +0 -131
  40. package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +0 -132
  41. package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +0 -95
  42. package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +0 -141
  43. package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +0 -125
  44. package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +0 -127
  45. package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +0 -120
  46. package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +0 -131
  47. package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +0 -156
  48. package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +0 -122
  49. package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +0 -167
  50. package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +0 -134
  51. package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +0 -143
  52. package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +0 -121
  53. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +0 -143
  54. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +0 -187
  55. package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +0 -165
  56. package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +0 -177
  57. package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +0 -163
  58. package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +0 -146
  59. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +0 -142
  60. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +0 -160
  61. package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +0 -125
  62. package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +0 -162
  63. package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +0 -177
  64. package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +0 -184
  65. package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +0 -168
  66. package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +0 -182
  67. package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +0 -199
  68. package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +0 -175
  69. package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +0 -185
  70. package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +0 -203
  71. package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +0 -171
  72. package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +0 -158
  73. package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +0 -195
  74. package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +0 -171
  75. package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +0 -156
  76. package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +0 -191
  77. package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +0 -198
  78. package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +0 -154
  79. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +0 -167
  80. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +0 -169
  81. package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +0 -172
  82. package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +0 -189
  83. package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +0 -113
  84. package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +0 -147
  85. package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +0 -122
  86. package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +0 -161
  87. package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +0 -149
  88. package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +0 -138
  89. package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +0 -169
  90. package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +0 -116
  91. package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +0 -128
  92. package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +0 -136
  93. package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +0 -131
  94. package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +0 -179
  95. package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +0 -144
  96. package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +0 -152
  97. package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +0 -145
  98. package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +0 -133
  99. package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +0 -152
  100. package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +0 -124
  101. package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +0 -115
  102. package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +0 -151
  103. package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +0 -130
  104. package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +0 -155
  105. package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +0 -171
  106. package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +0 -138
  107. package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +0 -107
  108. package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +0 -154
  109. package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +0 -118
  110. package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +0 -157
  111. package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +0 -133
  112. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +0 -131
  113. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +0 -136
  114. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +0 -135
  115. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +0 -122
  116. package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +0 -172
  117. package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +0 -168
  118. package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +0 -142
  119. package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +0 -168
  120. package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +0 -147
  121. package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +0 -158
  122. package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +0 -139
  123. package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +0 -147
  124. package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +0 -149
  125. package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +0 -174
  126. package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +0 -159
  127. package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +0 -138
  128. package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +0 -142
  129. package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +0 -156
  130. package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +0 -172
  131. package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +0 -164
  132. package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +0 -99
  133. package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +0 -104
  134. package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +0 -94
  135. package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +0 -78
  136. package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +0 -76
  137. package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +0 -123
  138. package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +0 -127
  139. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +0 -129
  140. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +0 -131
  141. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +0 -142
  142. package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +0 -86
  143. package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +0 -154
  144. package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +0 -118
  145. package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +0 -92
  146. package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +0 -65
  147. package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +0 -101
  148. package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +0 -161
  149. package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +0 -187
  150. package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +0 -142
  151. package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +0 -152
  152. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +0 -141
  153. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +0 -181
  154. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +0 -160
  155. package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +0 -171
  156. package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +0 -130
  157. package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +0 -167
  158. package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +0 -144
  159. package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +0 -154
  160. package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +0 -141
  161. package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +0 -95
  162. package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +0 -135
  163. package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +0 -124
  164. package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +0 -135
  165. package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +0 -134
  166. package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +0 -134
  167. package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +0 -105
  168. package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +0 -65
  169. package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +0 -97
  170. package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +0 -122
  171. package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +0 -119
  172. package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +0 -153
  173. package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +0 -136
  174. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +0 -133
  175. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +0 -120
  176. package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +0 -137
  177. package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +0 -134
  178. package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +0 -150
  179. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +0 -123
  180. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +0 -113
  181. package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +0 -175
  182. package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +0 -149
  183. package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +0 -142
  184. package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +0 -133
  185. package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +0 -148
  186. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +0 -130
  187. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +0 -120
  188. package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +0 -155
  189. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +0 -139
  190. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +0 -135
  191. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +0 -162
  192. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +0 -186
  193. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +0 -162
  194. package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +0 -160
  195. package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +0 -151
  196. package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +0 -171
  197. package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +0 -142
  198. package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +0 -168
  199. package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +0 -151
  200. package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +0 -144
  201. package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +0 -189
  202. package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +0 -226
  203. package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +0 -161
  204. package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +0 -130
  205. package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +0 -154
  206. package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +0 -127
  207. package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +0 -154
  208. package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +0 -142
  209. package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +0 -146
  210. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +0 -160
  211. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +0 -159
  212. package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +0 -144
  213. package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +0 -137
  214. package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +0 -188
  215. package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +0 -143
  216. package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +0 -131
  217. package/template/agent/skills/saas-architect/SKILL.md +0 -139
  218. package/template/agent/skills/security-engineer/SKILL.md +0 -133
  219. package/template/agent/skills/seo-specialist/SKILL.md +0 -130
  220. package/template/agent/skills/solo-founder-ops/SKILL.md +0 -56
@@ -1,135 +0,0 @@
1
- # own-clone-explicit
2
-
3
- > Use explicit `Clone` for types where copying has meaningful cost
4
-
5
- ## Why It Matters
6
-
7
- Unlike `Copy` which is implicit and "free," `Clone` requires an explicit `.clone()` call, signaling that duplication has a cost. This makes heap allocations and deep copies visible in code, helping developers reason about performance. Types with heap data (`String`, `Vec`, `Box`) should implement `Clone` but not `Copy`.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Hiding expensive operations
13
- fn process_data(data: Vec<u32>) -> Vec<u32> {
14
- let backup = data; // Moved, not copied - but unclear at call site
15
- transform(backup)
16
- }
17
-
18
- let my_data = vec![1, 2, 3, 4, 5];
19
- let result = process_data(my_data);
20
- // my_data is moved - surprise if you expected it to still exist
21
- ```
22
-
23
- ## Good
24
-
25
- ```rust
26
- fn process_data(data: Vec<u32>) -> Vec<u32> {
27
- let backup = data;
28
- transform(backup)
29
- }
30
-
31
- let my_data = vec![1, 2, 3, 4, 5];
32
- let result = process_data(my_data.clone()); // Explicit: "I know this allocates"
33
- // my_data still available
34
-
35
- // Or better - take reference if you don't need ownership
36
- fn process_data_ref(data: &[u32]) -> Vec<u32> {
37
- transform(data)
38
- }
39
- let result = process_data_ref(&my_data); // No clone needed
40
- ```
41
-
42
- ## Custom Clone Implementation
43
-
44
- For types with mixed cheap/expensive fields, implement `Clone` manually:
45
-
46
- ```rust
47
- #[derive(Debug)]
48
- struct Document {
49
- id: u64, // Cheap to copy
50
- content: String, // Expensive to clone
51
- metadata: Metadata, // Moderate cost
52
- }
53
-
54
- impl Clone for Document {
55
- fn clone(&self) -> Self {
56
- Self {
57
- id: self.id,
58
- content: self.content.clone(),
59
- metadata: self.metadata.clone(),
60
- }
61
- }
62
-
63
- // Optimization: reuse existing allocations
64
- fn clone_from(&mut self, source: &Self) {
65
- self.id = source.id;
66
- self.content.clone_from(&source.content); // Reuses capacity
67
- self.metadata.clone_from(&source.metadata);
68
- }
69
- }
70
- ```
71
-
72
- ## clone_from Optimization
73
-
74
- `clone_from` can reuse existing allocations:
75
-
76
- ```rust
77
- let mut buffer = String::with_capacity(1000);
78
-
79
- // Bad: drops old allocation, creates new one
80
- buffer = source.clone();
81
-
82
- // Good: reuses existing capacity if sufficient
83
- buffer.clone_from(&source);
84
- ```
85
-
86
- ## Derive vs Manual Clone
87
-
88
- ```rust
89
- // Derive when all fields need cloning
90
- #[derive(Clone)]
91
- struct Simple {
92
- data: Vec<u8>,
93
- name: String,
94
- }
95
-
96
- // Manual when you need special behavior
97
- struct CachedValue {
98
- value: i32,
99
- cache: RefCell<Option<ExpensiveComputation>>,
100
- }
101
-
102
- impl Clone for CachedValue {
103
- fn clone(&self) -> Self {
104
- Self {
105
- value: self.value,
106
- cache: RefCell::new(None), // Don't clone cache, let it rebuild
107
- }
108
- }
109
- }
110
- ```
111
-
112
- ## When to Avoid Clone
113
-
114
- ```rust
115
- // Instead of cloning, consider:
116
-
117
- // 1. References
118
- fn process(data: &MyType) { } // Borrow instead of clone
119
-
120
- // 2. Cow for conditional cloning
121
- fn process(data: Cow<'_, str>) { } // Clone only if mutation needed
122
-
123
- // 3. Arc for shared ownership
124
- let shared = Arc::new(expensive_data);
125
- let handle = shared.clone(); // Cheap: just increments counter
126
-
127
- // 4. Passing by value when caller is done with it
128
- fn consume(data: MyType) { } // Caller moves, no clone
129
- ```
130
-
131
- ## See Also
132
-
133
- - [own-copy-small](./own-copy-small.md) - When implicit Copy is appropriate
134
- - [own-cow-conditional](./own-cow-conditional.md) - Avoiding clones with Cow
135
- - [mem-clone-from](./mem-clone-from.md) - Optimizing repeated clones
@@ -1,124 +0,0 @@
1
- # own-copy-small
2
-
3
- > Implement `Copy` for small, simple types
4
-
5
- ## Why It Matters
6
-
7
- Types that implement `Copy` are implicitly duplicated on assignment instead of moved. This eliminates the need for explicit `.clone()` calls and makes the code more ergonomic. For small types (generally ≤16 bytes), copying is as fast or faster than moving a pointer.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Small type without Copy - requires explicit clone
13
- #[derive(Clone, Debug)]
14
- struct Point {
15
- x: f64,
16
- y: f64,
17
- }
18
-
19
- fn distance(p1: Point, p2: Point) -> f64 {
20
- ((p2.x - p1.x).powi(2) + (p2.y - p1.y).powi(2)).sqrt()
21
- }
22
-
23
- let origin = Point { x: 0.0, y: 0.0 };
24
- let target = Point { x: 3.0, y: 4.0 };
25
-
26
- let d1 = distance(origin.clone(), target.clone()); // Tedious
27
- let d2 = distance(origin.clone(), target.clone()); // Every use needs clone
28
- // origin and target still usable but verbose
29
- ```
30
-
31
- ## Good
32
-
33
- ```rust
34
- // Small type with Copy - implicit duplication
35
- #[derive(Clone, Copy, Debug)]
36
- struct Point {
37
- x: f64,
38
- y: f64,
39
- }
40
-
41
- fn distance(p1: Point, p2: Point) -> f64 {
42
- ((p2.x - p1.x).powi(2) + (p2.y - p1.y).powi(2)).sqrt()
43
- }
44
-
45
- let origin = Point { x: 0.0, y: 0.0 };
46
- let target = Point { x: 3.0, y: 4.0 };
47
-
48
- let d1 = distance(origin, target); // Implicitly copied
49
- let d2 = distance(origin, target); // Still works!
50
- // origin and target remain valid
51
- ```
52
-
53
- ## Copy Requirements
54
-
55
- A type can implement `Copy` only if:
56
- 1. All fields implement `Copy`
57
- 2. No custom `Drop` implementation
58
- 3. No heap-allocated data (`String`, `Vec`, `Box`, etc.)
59
-
60
- ```rust
61
- // ✅ Can be Copy
62
- #[derive(Clone, Copy)]
63
- struct Color {
64
- r: u8,
65
- g: u8,
66
- b: u8,
67
- a: u8,
68
- }
69
-
70
- // ❌ Cannot be Copy - contains String
71
- #[derive(Clone)]
72
- struct Person {
73
- name: String, // String is not Copy
74
- age: u32,
75
- }
76
-
77
- // ❌ Cannot be Copy - has Drop
78
- struct FileHandle {
79
- fd: i32,
80
- }
81
- impl Drop for FileHandle {
82
- fn drop(&mut self) { /* close file */ }
83
- }
84
- ```
85
-
86
- ## Size Guidelines
87
-
88
- | Size | Recommendation |
89
- |------|----------------|
90
- | ≤ 16 bytes | Implement `Copy` |
91
- | 17-64 bytes | Consider `Copy`, benchmark if critical |
92
- | > 64 bytes | Probably don't, prefer references |
93
-
94
- ```rust
95
- use std::mem::size_of;
96
-
97
- #[derive(Clone, Copy)]
98
- struct SmallId(u64); // 8 bytes ✅
99
-
100
- #[derive(Clone, Copy)]
101
- struct Rect { x: f32, y: f32, w: f32, h: f32 } // 16 bytes ✅
102
-
103
- #[derive(Clone)] // No Copy - 72 bytes
104
- struct Transform {
105
- matrix: [[f64; 3]; 3], // 72 bytes, too large
106
- }
107
- ```
108
-
109
- ## Common Copy Types
110
-
111
- Standard library types that are `Copy`:
112
- - All primitives: `i32`, `f64`, `bool`, `char`, etc.
113
- - References: `&T`, `&mut T`
114
- - Raw pointers: `*const T`, `*mut T`
115
- - Function pointers: `fn(T) -> U`
116
- - Tuples of `Copy` types: `(i32, f64)`
117
- - Arrays of `Copy` types: `[u8; 32]`
118
- - `Option<T>` where `T: Copy`
119
- - `PhantomData<T>`
120
-
121
- ## See Also
122
-
123
- - [own-clone-explicit](./own-clone-explicit.md) - When Clone without Copy is appropriate
124
- - [type-newtype-ids](./type-newtype-ids.md) - Newtype pattern often uses Copy
@@ -1,135 +0,0 @@
1
- # own-cow-conditional
2
-
3
- > Use `Cow<'a, T>` for conditional ownership
4
-
5
- ## Why It Matters
6
-
7
- `Cow` (Clone-on-Write) lets you avoid allocations when you *might* need to own data but usually don't. It holds either a borrowed reference or an owned value, cloning only when mutation is needed.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Always allocates, even when input doesn't need modification
13
- fn normalize_path(path: &str) -> String {
14
- if path.contains("//") {
15
- path.replace("//", "/") // Allocation needed
16
- } else {
17
- path.to_string() // Unnecessary allocation!
18
- }
19
- }
20
-
21
- // Always clones the error message
22
- fn format_error(code: u32) -> String {
23
- match code {
24
- 404 => "Not Found".to_string(), // Unnecessary!
25
- 500 => "Internal Error".to_string(), // Unnecessary!
26
- _ => format!("Error {}", code), // This one needs allocation
27
- }
28
- }
29
- ```
30
-
31
- ## Good
32
-
33
- ```rust
34
- use std::borrow::Cow;
35
-
36
- // Only allocates when needed
37
- fn normalize_path(path: &str) -> Cow<'_, str> {
38
- if path.contains("//") {
39
- Cow::Owned(path.replace("//", "/")) // Allocate
40
- } else {
41
- Cow::Borrowed(path) // Zero-cost borrow
42
- }
43
- }
44
-
45
- // Static strings stay borrowed
46
- fn format_error(code: u32) -> Cow<'static, str> {
47
- match code {
48
- 404 => Cow::Borrowed("Not Found"), // No allocation
49
- 500 => Cow::Borrowed("Internal Error"), // No allocation
50
- _ => Cow::Owned(format!("Error {}", code)), // Allocate only for unknown
51
- }
52
- }
53
- ```
54
-
55
- ## Real-World Example from ripgrep
56
-
57
- ```rust
58
- // https://github.com/BurntSushi/ripgrep/blob/master/crates/globset/src/pathutil.rs
59
- pub(crate) fn file_name<'a>(path: &Cow<'a, [u8]>) -> Option<Cow<'a, [u8]>> {
60
- let last_slash = path.rfind_byte(b'/').map(|i| i + 1).unwrap_or(0);
61
- match *path {
62
- Cow::Borrowed(path) => Some(Cow::Borrowed(&path[last_slash..])),
63
- Cow::Owned(ref path) => {
64
- let mut path = path.clone();
65
- path.drain_bytes(..last_slash);
66
- Some(Cow::Owned(path))
67
- }
68
- }
69
- }
70
- ```
71
-
72
- ## Clone-on-Write Pattern
73
-
74
- ```rust
75
- use std::borrow::Cow;
76
-
77
- fn process_text(text: Cow<'_, str>) -> Cow<'_, str> {
78
- if text.contains("bad_word") {
79
- // to_mut() clones if borrowed, returns &mut if owned
80
- let mut owned = text.into_owned();
81
- owned = owned.replace("bad_word", "***");
82
- Cow::Owned(owned)
83
- } else {
84
- text // Pass through unchanged
85
- }
86
- }
87
-
88
- // Usage
89
- let borrowed: Cow<str> = Cow::Borrowed("hello world");
90
- let result = process_text(borrowed); // No allocation!
91
-
92
- let with_bad: Cow<str> = Cow::Borrowed("hello bad_word");
93
- let result = process_text(with_bad); // Allocates only here
94
- ```
95
-
96
- ## Cow with Collections
97
-
98
- ```rust
99
- use std::borrow::Cow;
100
-
101
- // Mixed borrowed/owned in a collection
102
- fn collect_errors<'a>(
103
- static_errors: &[&'static str],
104
- dynamic_errors: Vec<String>,
105
- ) -> Vec<Cow<'a, str>> {
106
- let mut errors: Vec<Cow<str>> = Vec::new();
107
-
108
- // Static strings - no allocation
109
- for &e in static_errors {
110
- errors.push(Cow::Borrowed(e));
111
- }
112
-
113
- // Dynamic strings - take ownership
114
- for e in dynamic_errors {
115
- errors.push(Cow::Owned(e));
116
- }
117
-
118
- errors
119
- }
120
- ```
121
-
122
- ## When to Use Cow
123
-
124
- | Situation | Use Cow? |
125
- |-----------|----------|
126
- | Usually borrow, sometimes own | Yes |
127
- | Always need owned data | No, just use owned type |
128
- | Always borrow | No, just use reference |
129
- | Hot path, avoiding all allocations | Yes |
130
- | Returning static strings or formatted | Yes |
131
-
132
- ## See Also
133
-
134
- - [own-borrow-over-clone](own-borrow-over-clone.md) - Prefer borrowing over cloning
135
- - [mem-avoid-format](mem-avoid-format.md) - Avoid format! when possible
@@ -1,134 +0,0 @@
1
- # own-lifetime-elision
2
-
3
- > Rely on lifetime elision rules; add explicit lifetimes only when required
4
-
5
- ## Why It Matters
6
-
7
- Rust's lifetime elision rules handle most common borrowing patterns automatically. Adding explicit lifetimes where they're not needed clutters code without adding clarity. However, understanding when elision applies helps you know when explicit lifetimes are truly necessary.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Unnecessary explicit lifetimes - elision handles these
13
- fn first_word<'a>(s: &'a str) -> &'a str {
14
- s.split_whitespace().next().unwrap_or("")
15
- }
16
-
17
- fn get_name<'a>(person: &'a Person) -> &'a str {
18
- &person.name
19
- }
20
-
21
- impl<'a> Display for Wrapper<'a> {
22
- fn fmt<'b>(&'b self, f: &'b mut Formatter<'_>) -> fmt::Result {
23
- write!(f, "{}", self.0)
24
- }
25
- }
26
- ```
27
-
28
- ## Good
29
-
30
- ```rust
31
- // Let elision do its job
32
- fn first_word(s: &str) -> &str {
33
- s.split_whitespace().next().unwrap_or("")
34
- }
35
-
36
- fn get_name(person: &Person) -> &str {
37
- &person.name
38
- }
39
-
40
- impl Display for Wrapper<'_> {
41
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
42
- write!(f, "{}", self.0)
43
- }
44
- }
45
- ```
46
-
47
- ## The Three Elision Rules
48
-
49
- 1. **Each input reference gets its own lifetime:**
50
- ```rust
51
- fn foo(x: &str, y: &str)
52
- // becomes
53
- fn foo<'a, 'b>(x: &'a str, y: &'b str)
54
- ```
55
-
56
- 2. **One input reference → output gets same lifetime:**
57
- ```rust
58
- fn foo(x: &str) -> &str
59
- // becomes
60
- fn foo<'a>(x: &'a str) -> &'a str
61
- ```
62
-
63
- 3. **Method with `&self`/`&mut self` → output gets self's lifetime:**
64
- ```rust
65
- fn foo(&self, x: &str) -> &str
66
- // becomes
67
- fn foo<'a, 'b>(&'a self, x: &'b str) -> &'a str
68
- ```
69
-
70
- ## When Explicit Lifetimes ARE Required
71
-
72
- ```rust
73
- // Multiple input references, output could come from either
74
- fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
75
- if x.len() > y.len() { x } else { y }
76
- }
77
-
78
- // Struct holding references
79
- struct Parser<'input> {
80
- source: &'input str,
81
- position: usize,
82
- }
83
-
84
- // Multiple distinct lifetimes needed
85
- struct Context<'s, 'c> {
86
- source: &'s str,
87
- cache: &'c mut Cache,
88
- }
89
-
90
- // Static lifetime for constants
91
- fn get_default() -> &'static str {
92
- "default"
93
- }
94
- ```
95
-
96
- ## Anonymous Lifetime `'_`
97
-
98
- Use `'_` to let the compiler infer while being explicit about the presence of a lifetime:
99
-
100
- ```rust
101
- // In struct definitions
102
- impl Iterator for Parser<'_> {
103
- type Item = Token;
104
- fn next(&mut self) -> Option<Self::Item> { ... }
105
- }
106
-
107
- // In function signatures where it adds clarity
108
- fn parse(input: &str) -> Result<Ast<'_>, Error> { ... }
109
-
110
- // Especially useful in trait bounds
111
- fn process(data: &impl AsRef<str>) -> Cow<'_, str> { ... }
112
- ```
113
-
114
- ## Common Patterns
115
-
116
- ```rust
117
- // ✅ Elision works
118
- fn trim(s: &str) -> &str { s.trim() }
119
- fn first(v: &[i32]) -> Option<&i32> { v.first() }
120
- fn name(&self) -> &str { &self.name }
121
-
122
- // ❌ Elision fails - multiple inputs, ambiguous output
123
- fn pick(a: &str, b: &str, first: bool) -> &str // Error!
124
-
125
- // ✅ Fixed with explicit lifetime
126
- fn pick<'a>(a: &'a str, b: &'a str, first: bool) -> &'a str {
127
- if first { a } else { b }
128
- }
129
- ```
130
-
131
- ## See Also
132
-
133
- - [own-borrow-over-clone](./own-borrow-over-clone.md) - Prefer borrowing to avoid ownership issues
134
- - [api-impl-asref](./api-impl-asref.md) - Generic borrowing with AsRef
@@ -1,134 +0,0 @@
1
- # own-move-large
2
-
3
- > Move large types instead of copying; use `Box` if moves are expensive
4
-
5
- ## Why It Matters
6
-
7
- In Rust, "moving" a value means copying its bytes to a new location and invalidating the old one. For large types (hundreds of bytes), this memcpy can be expensive. Boxing large types reduces move cost to copying a single pointer (8 bytes), making moves cheap regardless of the actual data size.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Large struct moved repeatedly = expensive memcpy each time
13
- struct GameState {
14
- board: [[Cell; 100]; 100], // 10,000 cells
15
- history: [Move; 1000], // 1,000 moves
16
- players: [Player; 4], // Player data
17
- // Total: potentially tens of KB
18
- }
19
-
20
- fn process_state(state: GameState) -> GameState {
21
- // Moving ~40KB+ of data
22
- let mut new_state = state; // Memcpy here
23
- new_state.apply_rules();
24
- new_state // Memcpy on return
25
- }
26
-
27
- let state = GameState::new();
28
- let state = process_state(state); // Two large memcpys
29
- ```
30
-
31
- ## Good
32
-
33
- ```rust
34
- // Box reduces move cost to 8 bytes
35
- struct GameState {
36
- board: Box<[[Cell; 100]; 100]>, // Pointer to heap
37
- history: Vec<Move>, // Already heap-allocated
38
- players: [Player; 4],
39
- }
40
-
41
- fn process_state(mut state: GameState) -> GameState {
42
- // Moving just pointers + small inline data
43
- state.apply_rules();
44
- state // Cheap move
45
- }
46
-
47
- // Or use Box at call site for one-off cases
48
- fn process_large(state: Box<LargeStruct>) -> Box<LargeStruct> {
49
- // 8-byte move regardless of LargeStruct size
50
- state
51
- }
52
- ```
53
-
54
- ## When to Box
55
-
56
- | Type Size | Move Frequency | Recommendation |
57
- |-----------|----------------|----------------|
58
- | < 128 bytes | Any | Don't box |
59
- | 128-512 bytes | Rare | Probably don't box |
60
- | 128-512 bytes | Frequent | Consider boxing |
61
- | > 512 bytes | Any | Box or use references |
62
- | > 4KB | Any | Definitely box |
63
-
64
- ## Stack vs Heap Tradeoffs
65
-
66
- ```rust
67
- // Stack: fast allocation, limited size, moves copy bytes
68
- struct StackHeavy {
69
- data: [u8; 4096], // 4KB on stack
70
- }
71
-
72
- // Heap: allocation cost, unlimited size, moves copy pointer
73
- struct HeapLight {
74
- data: Box<[u8; 4096]>, // 8 bytes on stack, 4KB on heap
75
- }
76
-
77
- // Measure with size_of
78
- use std::mem::size_of;
79
- assert_eq!(size_of::<StackHeavy>(), 4096);
80
- assert_eq!(size_of::<HeapLight>(), 8);
81
- ```
82
-
83
- ## Alternative: References
84
-
85
- When you don't need ownership transfer, use references:
86
-
87
- ```rust
88
- // Best: no move at all
89
- fn analyze_state(state: &GameState) -> Analysis {
90
- // Borrows state, no copying
91
- compute_analysis(state)
92
- }
93
-
94
- // Mutable borrow for in-place modification
95
- fn update_state(state: &mut GameState) {
96
- state.tick();
97
- }
98
- ```
99
-
100
- ## Pattern: Builder Returns Boxed
101
-
102
- ```rust
103
- impl LargeConfig {
104
- pub fn builder() -> ConfigBuilder {
105
- ConfigBuilder::default()
106
- }
107
- }
108
-
109
- impl ConfigBuilder {
110
- // Return boxed to avoid large move
111
- pub fn build(self) -> Box<LargeConfig> {
112
- Box::new(LargeConfig {
113
- // ... fields from builder
114
- })
115
- }
116
- }
117
- ```
118
-
119
- ## Profile First
120
-
121
- Don't prematurely optimize. Use tools to identify if moves are actually a bottleneck:
122
-
123
- ```rust
124
- // Check type sizes
125
- println!("Size of GameState: {}", std::mem::size_of::<GameState>());
126
-
127
- // Profile with cargo flamegraph or perf to find hot memcpys
128
- ```
129
-
130
- ## See Also
131
-
132
- - [own-copy-small](./own-copy-small.md) - Cheap types should be Copy
133
- - [mem-box-large-variant](./mem-box-large-variant.md) - Boxing enum variants
134
- - [perf-profile-first](./perf-profile-first.md) - Measure before optimizing