agy-superpowers 5.2.2 → 5.2.4

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 (231) hide show
  1. package/README.md +47 -150
  2. package/package.json +1 -1
  3. package/template/agent/rules/CLAUDE.md +80 -0
  4. package/template/agent/rules/code-styles.md +31 -32
  5. package/template/agent/rules/debug-confirmation-policy.md +2 -0
  6. package/template/agent/rules/file-length-policy.md +2 -0
  7. package/template/agent/rules/git-policy.md +7 -0
  8. package/template/agent/rules/language-matching.md +2 -0
  9. package/template/agent/rules/scratch-scripts.md +39 -0
  10. package/template/agent/rules/superpowers.md +8 -51
  11. package/template/agent/skills/executing-plans/SKILL.md +17 -0
  12. package/template/agent/skills/systematic-debugging/SKILL.md +16 -0
  13. package/template/agent/skills/test-driven-development/SKILL.md +16 -0
  14. package/template/agent/skills/verification-before-completion/SKILL.md +22 -0
  15. package/template/agent/skills/writing-plans/SKILL.md +16 -0
  16. package/template/agent/skills/ai-integrated-product/SKILL.md +0 -57
  17. package/template/agent/skills/analytics-setup/SKILL.md +0 -51
  18. package/template/agent/skills/api-design/SKILL.md +0 -193
  19. package/template/agent/skills/app-store-optimizer/SKILL.md +0 -127
  20. package/template/agent/skills/auth-and-identity/SKILL.md +0 -167
  21. package/template/agent/skills/backend-developer/SKILL.md +0 -148
  22. package/template/agent/skills/bootstrapper-finance/SKILL.md +0 -55
  23. package/template/agent/skills/chrome-extension-developer/SKILL.md +0 -53
  24. package/template/agent/skills/community-manager/SKILL.md +0 -115
  25. package/template/agent/skills/content-marketer/SKILL.md +0 -111
  26. package/template/agent/skills/conversion-optimizer/SKILL.md +0 -142
  27. package/template/agent/skills/cto-architect/SKILL.md +0 -133
  28. package/template/agent/skills/customer-success-manager/SKILL.md +0 -126
  29. package/template/agent/skills/data-analyst/SKILL.md +0 -147
  30. package/template/agent/skills/devops-engineer/SKILL.md +0 -117
  31. package/template/agent/skills/email-infrastructure/SKILL.md +0 -164
  32. package/template/agent/skills/game-design/SKILL.md +0 -194
  33. package/template/agent/skills/game-developer/SKILL.md +0 -175
  34. package/template/agent/skills/growth-hacker/SKILL.md +0 -122
  35. package/template/agent/skills/idea-validator/SKILL.md +0 -55
  36. package/template/agent/skills/indie-legal/SKILL.md +0 -53
  37. package/template/agent/skills/influencer-marketer/SKILL.md +0 -141
  38. package/template/agent/skills/landing-page-builder/SKILL.md +0 -59
  39. package/template/agent/skills/launch-strategist/SKILL.md +0 -62
  40. package/template/agent/skills/market-researcher/SKILL.md +0 -53
  41. package/template/agent/skills/micro-saas-builder/SKILL.md +0 -56
  42. package/template/agent/skills/monetization-strategist/SKILL.md +0 -119
  43. package/template/agent/skills/paid-acquisition-specialist/SKILL.md +0 -119
  44. package/template/agent/skills/pricing-psychologist/SKILL.md +0 -58
  45. package/template/agent/skills/real-time-features/SKILL.md +0 -194
  46. package/template/agent/skills/retention-specialist/SKILL.md +0 -123
  47. package/template/agent/skills/rust-developer/SKILL.md +0 -281
  48. package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +0 -231
  49. package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +0 -124
  50. package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +0 -131
  51. package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +0 -132
  52. package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +0 -95
  53. package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +0 -141
  54. package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +0 -125
  55. package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +0 -127
  56. package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +0 -120
  57. package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +0 -131
  58. package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +0 -156
  59. package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +0 -122
  60. package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +0 -167
  61. package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +0 -134
  62. package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +0 -143
  63. package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +0 -121
  64. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +0 -143
  65. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +0 -187
  66. package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +0 -165
  67. package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +0 -177
  68. package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +0 -163
  69. package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +0 -146
  70. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +0 -142
  71. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +0 -160
  72. package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +0 -125
  73. package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +0 -162
  74. package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +0 -177
  75. package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +0 -184
  76. package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +0 -168
  77. package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +0 -182
  78. package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +0 -199
  79. package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +0 -175
  80. package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +0 -185
  81. package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +0 -203
  82. package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +0 -171
  83. package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +0 -158
  84. package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +0 -195
  85. package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +0 -171
  86. package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +0 -156
  87. package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +0 -191
  88. package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +0 -198
  89. package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +0 -154
  90. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +0 -167
  91. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +0 -169
  92. package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +0 -172
  93. package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +0 -189
  94. package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +0 -113
  95. package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +0 -147
  96. package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +0 -122
  97. package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +0 -161
  98. package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +0 -149
  99. package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +0 -138
  100. package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +0 -169
  101. package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +0 -116
  102. package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +0 -128
  103. package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +0 -136
  104. package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +0 -131
  105. package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +0 -179
  106. package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +0 -144
  107. package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +0 -152
  108. package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +0 -145
  109. package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +0 -133
  110. package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +0 -152
  111. package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +0 -124
  112. package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +0 -115
  113. package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +0 -151
  114. package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +0 -130
  115. package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +0 -155
  116. package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +0 -171
  117. package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +0 -138
  118. package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +0 -107
  119. package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +0 -154
  120. package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +0 -118
  121. package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +0 -157
  122. package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +0 -133
  123. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +0 -131
  124. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +0 -136
  125. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +0 -135
  126. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +0 -122
  127. package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +0 -172
  128. package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +0 -168
  129. package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +0 -142
  130. package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +0 -168
  131. package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +0 -147
  132. package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +0 -158
  133. package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +0 -139
  134. package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +0 -147
  135. package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +0 -149
  136. package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +0 -174
  137. package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +0 -159
  138. package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +0 -138
  139. package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +0 -142
  140. package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +0 -156
  141. package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +0 -172
  142. package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +0 -164
  143. package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +0 -99
  144. package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +0 -104
  145. package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +0 -94
  146. package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +0 -78
  147. package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +0 -76
  148. package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +0 -123
  149. package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +0 -127
  150. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +0 -129
  151. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +0 -131
  152. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +0 -142
  153. package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +0 -86
  154. package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +0 -154
  155. package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +0 -118
  156. package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +0 -92
  157. package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +0 -65
  158. package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +0 -101
  159. package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +0 -161
  160. package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +0 -187
  161. package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +0 -142
  162. package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +0 -152
  163. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +0 -141
  164. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +0 -181
  165. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +0 -160
  166. package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +0 -171
  167. package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +0 -130
  168. package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +0 -167
  169. package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +0 -144
  170. package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +0 -154
  171. package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +0 -141
  172. package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +0 -95
  173. package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +0 -135
  174. package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +0 -124
  175. package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +0 -135
  176. package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +0 -134
  177. package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +0 -134
  178. package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +0 -105
  179. package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +0 -65
  180. package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +0 -97
  181. package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +0 -122
  182. package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +0 -119
  183. package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +0 -153
  184. package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +0 -136
  185. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +0 -133
  186. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +0 -120
  187. package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +0 -137
  188. package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +0 -134
  189. package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +0 -150
  190. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +0 -123
  191. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +0 -113
  192. package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +0 -175
  193. package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +0 -149
  194. package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +0 -142
  195. package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +0 -133
  196. package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +0 -148
  197. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +0 -130
  198. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +0 -120
  199. package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +0 -155
  200. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +0 -139
  201. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +0 -135
  202. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +0 -162
  203. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +0 -186
  204. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +0 -162
  205. package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +0 -160
  206. package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +0 -151
  207. package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +0 -171
  208. package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +0 -142
  209. package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +0 -168
  210. package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +0 -151
  211. package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +0 -144
  212. package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +0 -189
  213. package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +0 -226
  214. package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +0 -161
  215. package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +0 -130
  216. package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +0 -154
  217. package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +0 -127
  218. package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +0 -154
  219. package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +0 -142
  220. package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +0 -146
  221. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +0 -160
  222. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +0 -159
  223. package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +0 -144
  224. package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +0 -137
  225. package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +0 -188
  226. package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +0 -143
  227. package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +0 -131
  228. package/template/agent/skills/saas-architect/SKILL.md +0 -139
  229. package/template/agent/skills/security-engineer/SKILL.md +0 -133
  230. package/template/agent/skills/seo-specialist/SKILL.md +0 -130
  231. package/template/agent/skills/solo-founder-ops/SKILL.md +0 -56
@@ -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
@@ -1,105 +0,0 @@
1
- # own-mutex-interior
2
-
3
- > Use `Mutex<T>` for interior mutability across threads
4
-
5
- ## Why It Matters
6
-
7
- When you need shared mutable state across threads, `Mutex<T>` provides safe interior mutability with synchronization. Unlike `RefCell`, `Mutex` is `Send + Sync` and uses OS-level locking to ensure only one thread can access the data at a time.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- use std::cell::RefCell;
13
- use std::sync::Arc;
14
-
15
- // RefCell is !Sync - this won't compile
16
- let shared = Arc::new(RefCell::new(vec![]));
17
-
18
- // ERROR: RefCell cannot be shared between threads safely
19
- std::thread::spawn({
20
- let shared = shared.clone();
21
- move || shared.borrow_mut().push(1)
22
- });
23
- ```
24
-
25
- ## Good
26
-
27
- ```rust
28
- use std::sync::{Arc, Mutex};
29
-
30
- let shared = Arc::new(Mutex::new(vec![]));
31
-
32
- let handles: Vec<_> = (0..10).map(|i| {
33
- let shared = shared.clone();
34
- std::thread::spawn(move || {
35
- let mut data = shared.lock().unwrap();
36
- data.push(i);
37
- })
38
- }).collect();
39
-
40
- for handle in handles {
41
- handle.join().unwrap();
42
- }
43
-
44
- println!("{:?}", shared.lock().unwrap()); // All values present
45
- ```
46
-
47
- ## Mutex Poisoning
48
-
49
- If a thread panics while holding a lock, the mutex becomes "poisoned":
50
-
51
- ```rust
52
- use std::sync::{Arc, Mutex};
53
-
54
- let mutex = Arc::new(Mutex::new(0));
55
-
56
- // Handle poisoning gracefully
57
- match mutex.lock() {
58
- Ok(guard) => println!("Value: {}", *guard),
59
- Err(poisoned) => {
60
- // Recover the data anyway
61
- let guard = poisoned.into_inner();
62
- println!("Recovered value: {}", *guard);
63
- }
64
- }
65
-
66
- // Or ignore poisoning (use with caution)
67
- let guard = mutex.lock().unwrap_or_else(|e| e.into_inner());
68
- ```
69
-
70
- ## Prefer parking_lot::Mutex
71
-
72
- For better performance, consider `parking_lot::Mutex`:
73
-
74
- ```rust
75
- use parking_lot::Mutex;
76
- use std::sync::Arc;
77
-
78
- let shared = Arc::new(Mutex::new(vec![]));
79
-
80
- // No poisoning, no Result to unwrap
81
- let mut data = shared.lock();
82
- data.push(42);
83
- // Lock automatically released when guard drops
84
- ```
85
-
86
- Benefits of `parking_lot`:
87
- - No poisoning (returns guard directly)
88
- - Smaller size (1 byte vs 40+ bytes)
89
- - Better performance under contention
90
- - Fair locking option available
91
-
92
- ## When to Use What
93
-
94
- | Type | Threading | Overhead | Use Case |
95
- |------|-----------|----------|----------|
96
- | `RefCell<T>` | Single | Minimal | Interior mutability, same thread |
97
- | `Mutex<T>` | Multi | Locking | Shared mutable state across threads |
98
- | `RwLock<T>` | Multi | Locking | Many readers, few writers |
99
- | `parking_lot::Mutex` | Multi | Less | Drop-in std::Mutex replacement |
100
-
101
- ## See Also
102
-
103
- - [own-rwlock-readers](./own-rwlock-readers.md) - When reads dominate writes
104
- - [own-refcell-interior](./own-refcell-interior.md) - Single-threaded alternative
105
- - [async-no-lock-await](./async-no-lock-await.md) - Avoiding locks across await points
@@ -1,65 +0,0 @@
1
- # own-rc-single-thread
2
-
3
- > Use `Rc<T>` for shared ownership in single-threaded contexts
4
-
5
- ## Why It Matters
6
-
7
- `Rc<T>` (Reference Counted) provides shared ownership without the atomic overhead of `Arc<T>`. In single-threaded code, `Rc` is faster because it uses non-atomic reference counting. Using `Arc` when you don't need thread-safety wastes CPU cycles on unnecessary synchronization.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- use std::sync::Arc;
13
-
14
- // Single-threaded application using Arc unnecessarily
15
- fn build_tree() -> Arc<Node> {
16
- let root = Arc::new(Node::new("root"));
17
- let child1 = Arc::new(Node::new("child1"));
18
- let child2 = Arc::new(Node::new("child2"));
19
-
20
- // All in same thread, but paying atomic overhead
21
- root.add_child(child1.clone());
22
- root.add_child(child2.clone());
23
- root
24
- }
25
- ```
26
-
27
- Atomic operations have measurable overhead even without contention.
28
-
29
- ## Good
30
-
31
- ```rust
32
- use std::rc::Rc;
33
-
34
- // Single-threaded: use Rc for zero atomic overhead
35
- fn build_tree() -> Rc<Node> {
36
- let root = Rc::new(Node::new("root"));
37
- let child1 = Rc::new(Node::new("child1"));
38
- let child2 = Rc::new(Node::new("child2"));
39
-
40
- root.add_child(child1.clone());
41
- root.add_child(child2.clone());
42
- root
43
- }
44
-
45
- // Compiler enforces single-thread: Rc is !Send + !Sync
46
- // Attempting to send across threads = compile error
47
- ```
48
-
49
- ## Decision Guide
50
-
51
- | Scenario | Use |
52
- |----------|-----|
53
- | Single-threaded, shared ownership | `Rc<T>` |
54
- | Multi-threaded, shared ownership | `Arc<T>` |
55
- | Single owner, might need multiple later | Start with `Rc`, upgrade if needed |
56
- | Library code, unknown threading model | `Arc<T>` (safer default) |
57
-
58
- ## Evidence
59
-
60
- The Rust standard library itself uses `Rc` extensively in single-threaded contexts like the `std::rc` module documentation examples.
61
-
62
- ## See Also
63
-
64
- - [own-arc-shared](./own-arc-shared.md) - When you need thread-safe sharing
65
- - [own-refcell-interior](./own-refcell-interior.md) - Combining Rc with interior mutability