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,124 +0,0 @@
1
- # anti-clone-excessive
2
-
3
- > Don't clone when borrowing works
4
-
5
- ## Why It Matters
6
-
7
- `.clone()` allocates memory and copies data. When you only need to read data, borrowing (`&T`) is free. Excessive cloning wastes memory, CPU cycles, and often indicates misunderstanding of ownership.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Cloning to pass to a function that only reads
13
- fn print_name(name: String) { // Takes ownership
14
- println!("{}", name);
15
- }
16
- let name = "Alice".to_string();
17
- print_name(name.clone()); // Unnecessary clone
18
- print_name(name); // Could have just done this
19
-
20
- // Cloning in a loop
21
- for item in items.clone() { // Clones entire Vec
22
- process(&item);
23
- }
24
-
25
- // Cloning for comparison
26
- if input.clone() == expected { // Pointless clone
27
- // ...
28
- }
29
-
30
- // Cloning struct fields
31
- fn get_name(&self) -> String {
32
- self.name.clone() // Caller might not need ownership
33
- }
34
- ```
35
-
36
- ## Good
37
-
38
- ```rust
39
- // Accept reference if only reading
40
- fn print_name(name: &str) {
41
- println!("{}", name);
42
- }
43
- let name = "Alice".to_string();
44
- print_name(&name); // Borrow, no clone
45
-
46
- // Iterate by reference
47
- for item in &items {
48
- process(item);
49
- }
50
-
51
- // Compare by reference
52
- if input == expected {
53
- // ...
54
- }
55
-
56
- // Return reference when possible
57
- fn get_name(&self) -> &str {
58
- &self.name
59
- }
60
- ```
61
-
62
- ## When to Clone
63
-
64
- ```rust
65
- // Need owned data for async move
66
- let name = name.clone();
67
- tokio::spawn(async move {
68
- process(name).await;
69
- });
70
-
71
- // Storing in a new struct
72
- struct Cache {
73
- data: String,
74
- }
75
- impl Cache {
76
- fn store(&mut self, data: &str) {
77
- self.data = data.to_string(); // Must own
78
- }
79
- }
80
-
81
- // Multiple owners (use Arc instead if frequent)
82
- let shared = data.clone();
83
- thread::spawn(move || use_data(shared));
84
- ```
85
-
86
- ## Alternatives to Clone
87
-
88
- | Instead of | Use |
89
- |------------|-----|
90
- | `s.clone()` for reading | `&s` |
91
- | `vec.clone()` for iteration | `&vec` or `vec.iter()` |
92
- | `Clone` for shared ownership | `Arc<T>` |
93
- | Clone in hot loop | Move outside loop |
94
- | `s.to_string()` from `&str` | Accept `&str` if possible |
95
-
96
- ## Pattern: Clone on Write
97
-
98
- ```rust
99
- use std::borrow::Cow;
100
-
101
- fn process(input: Cow<str>) -> Cow<str> {
102
- if needs_modification(&input) {
103
- Cow::Owned(modify(&input)) // Clone only if needed
104
- } else {
105
- input // No clone
106
- }
107
- }
108
- ```
109
-
110
- ## Detecting Excessive Clones
111
-
112
- ```toml
113
- # Cargo.toml
114
- [lints.clippy]
115
- clone_on_copy = "warn"
116
- clone_on_ref_ptr = "warn"
117
- redundant_clone = "warn"
118
- ```
119
-
120
- ## See Also
121
-
122
- - [own-borrow-over-clone](./own-borrow-over-clone.md) - Borrowing patterns
123
- - [own-cow-conditional](./own-cow-conditional.md) - Clone on write
124
- - [own-arc-shared](./own-arc-shared.md) - Shared ownership
@@ -1,131 +0,0 @@
1
- # anti-collect-intermediate
2
-
3
- > Don't collect intermediate iterators
4
-
5
- ## Why It Matters
6
-
7
- Each `.collect()` allocates a new collection. Collecting intermediate results in a chain creates unnecessary allocations and prevents iterator fusion. Keep the chain lazy; collect only at the end.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Three allocations, three passes
13
- fn process(data: Vec<i32>) -> Vec<i32> {
14
- let step1: Vec<_> = data.into_iter()
15
- .filter(|x| *x > 0)
16
- .collect();
17
-
18
- let step2: Vec<_> = step1.into_iter()
19
- .map(|x| x * 2)
20
- .collect();
21
-
22
- step2.into_iter()
23
- .filter(|x| *x < 100)
24
- .collect()
25
- }
26
-
27
- // Collecting just to check length
28
- fn has_valid_items(items: &[Item]) -> bool {
29
- let valid: Vec<_> = items.iter()
30
- .filter(|i| i.is_valid())
31
- .collect();
32
- !valid.is_empty()
33
- }
34
-
35
- // Collecting to iterate again
36
- fn sum_valid(items: &[Item]) -> i64 {
37
- let valid: Vec<_> = items.iter()
38
- .filter(|i| i.is_valid())
39
- .collect();
40
- valid.iter().map(|i| i.value).sum()
41
- }
42
- ```
43
-
44
- ## Good
45
-
46
- ```rust
47
- // Single allocation, single pass
48
- fn process(data: Vec<i32>) -> Vec<i32> {
49
- data.into_iter()
50
- .filter(|x| *x > 0)
51
- .map(|x| x * 2)
52
- .filter(|x| *x < 100)
53
- .collect()
54
- }
55
-
56
- // No allocation - iterator short-circuits
57
- fn has_valid_items(items: &[Item]) -> bool {
58
- items.iter().any(|i| i.is_valid())
59
- }
60
-
61
- // No intermediate allocation
62
- fn sum_valid(items: &[Item]) -> i64 {
63
- items.iter()
64
- .filter(|i| i.is_valid())
65
- .map(|i| i.value)
66
- .sum()
67
- }
68
- ```
69
-
70
- ## When Collection Is Needed
71
-
72
- ```rust
73
- // Need to iterate twice
74
- let valid: Vec<_> = items.iter()
75
- .filter(|i| i.is_valid())
76
- .collect();
77
- let count = valid.len();
78
- for item in &valid {
79
- process(item);
80
- }
81
-
82
- // Need to sort (requires concrete collection)
83
- let mut sorted: Vec<_> = items.iter()
84
- .filter(|i| i.is_active())
85
- .collect();
86
- sorted.sort_by_key(|i| i.priority);
87
-
88
- // Need random access
89
- let indexed: Vec<_> = items.iter().collect();
90
- let middle = indexed.get(indexed.len() / 2);
91
- ```
92
-
93
- ## Iterator Methods That Avoid Collection
94
-
95
- | Instead of Collecting to... | Use |
96
- |-----------------------------|-----|
97
- | Check if empty | `.any(|_| true)` or `.next().is_some()` |
98
- | Check if any match | `.any(predicate)` |
99
- | Check if all match | `.all(predicate)` |
100
- | Count elements | `.count()` |
101
- | Sum elements | `.sum()` |
102
- | Find first | `.find(predicate)` |
103
- | Get first | `.next()` |
104
- | Get last | `.last()` |
105
-
106
- ## Pattern: Deferred Collection
107
-
108
- ```rust
109
- // Return iterator, let caller collect if needed
110
- fn valid_items(items: &[Item]) -> impl Iterator<Item = &Item> {
111
- items.iter().filter(|i| i.is_valid())
112
- }
113
-
114
- // Caller decides
115
- let count = valid_items(&items).count(); // No collection
116
- let vec: Vec<_> = valid_items(&items).collect(); // Collection when needed
117
- ```
118
-
119
- ## Comparison
120
-
121
- | Pattern | Allocations | Passes |
122
- |---------|-------------|--------|
123
- | `.collect()` each step | N | N |
124
- | Single chain, one `.collect()` | 1 | 1 |
125
- | No collection (streaming) | 0 | 1 |
126
-
127
- ## See Also
128
-
129
- - [perf-collect-once](./perf-collect-once.md) - Single collect
130
- - [perf-iter-lazy](./perf-iter-lazy.md) - Lazy evaluation
131
- - [perf-iter-over-index](./perf-iter-over-index.md) - Iterator patterns
@@ -1,132 +0,0 @@
1
- # anti-empty-catch
2
-
3
- > Don't silently ignore errors
4
-
5
- ## Why It Matters
6
-
7
- Empty error handling (`if let Err(_) = ...`, `let _ = result`, `.ok()`) silently discards errors. Failures go unnoticed, bugs hide, and debugging becomes impossible. Every error deserves acknowledgment—even if just logging.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Silently ignores errors
13
- let _ = write_to_file(data);
14
-
15
- // Discards error completely
16
- if let Err(_) = send_notification() {
17
- // Nothing - error vanishes
18
- }
19
-
20
- // Converts Result to Option, losing error info
21
- let value = risky_operation().ok();
22
-
23
- // Match with empty arm
24
- match database.save(record) {
25
- Ok(_) => println!("saved"),
26
- Err(_) => {} // Silent failure
27
- }
28
-
29
- // Ignored in loop
30
- for item in items {
31
- let _ = process(item); // Failures unnoticed
32
- }
33
- ```
34
-
35
- ## Good
36
-
37
- ```rust
38
- // Log the error
39
- if let Err(e) = write_to_file(data) {
40
- error!("failed to write file: {}", e);
41
- }
42
-
43
- // Propagate if possible
44
- send_notification()?;
45
-
46
- // Or handle explicitly
47
- match send_notification() {
48
- Ok(_) => info!("notification sent"),
49
- Err(e) => warn!("notification failed: {}", e),
50
- }
51
-
52
- // Collect errors in batch operations
53
- let (successes, failures): (Vec<_>, Vec<_>) = items
54
- .into_iter()
55
- .map(process)
56
- .partition(Result::is_ok);
57
-
58
- if !failures.is_empty() {
59
- warn!("{} items failed to process", failures.len());
60
- }
61
-
62
- // Explicit documentation when ignoring
63
- // Intentionally ignored: cleanup failure is not critical
64
- let _ = cleanup_temp_file(); // Add comment explaining why
65
- ```
66
-
67
- ## Acceptable Ignoring (Documented)
68
-
69
- ```rust
70
- // Close errors often ignored, but document it
71
- // INTENTIONAL: TCP close errors are not actionable
72
- let _ = stream.shutdown(Shutdown::Both);
73
-
74
- // Mutex poisoning recovery
75
- // INTENTIONAL: We'll reset the state anyway
76
- let guard = mutex.lock().unwrap_or_else(|e| e.into_inner());
77
- ```
78
-
79
- ## Pattern: Collect and Report
80
-
81
- ```rust
82
- fn process_batch(items: Vec<Item>) -> BatchResult {
83
- let mut errors = Vec::new();
84
-
85
- for item in items {
86
- if let Err(e) = process_item(&item) {
87
- errors.push((item.id, e));
88
- }
89
- }
90
-
91
- if errors.is_empty() {
92
- BatchResult::AllSucceeded
93
- } else {
94
- BatchResult::PartialFailure(errors)
95
- }
96
- }
97
- ```
98
-
99
- ## Pattern: Best-Effort Operations
100
-
101
- ```rust
102
- // Metrics/telemetry can fail without affecting main flow
103
- fn report_metric(name: &str, value: f64) {
104
- if let Err(e) = metrics_client.record(name, value) {
105
- // Log but don't propagate - metrics are not critical
106
- debug!("failed to record metric {}: {}", name, e);
107
- }
108
- }
109
- ```
110
-
111
- ## Clippy Lint
112
-
113
- ```toml
114
- [lints.clippy]
115
- let_underscore_drop = "warn"
116
- ignored_unit_patterns = "warn"
117
- ```
118
-
119
- ## Decision Guide
120
-
121
- | Situation | Action |
122
- |-----------|--------|
123
- | Critical operation | `?` or handle explicitly |
124
- | Non-critical, debugging needed | Log the error |
125
- | Truly ignorable (rare) | `let _ =` with comment |
126
- | Batch operation | Collect errors, report |
127
-
128
- ## See Also
129
-
130
- - [err-result-over-panic](./err-result-over-panic.md) - Proper error handling
131
- - [err-context-chain](./err-context-chain.md) - Adding context
132
- - [anti-unwrap-abuse](./anti-unwrap-abuse.md) - Unwrap issues
@@ -1,95 +0,0 @@
1
- # anti-expect-lazy
2
-
3
- > Don't use expect for recoverable errors
4
-
5
- ## Why It Matters
6
-
7
- `.expect()` panics with a custom message, but it's still a panic. Using it for errors that could reasonably occur in production (network failures, file not found, invalid input) crashes the program instead of handling the error gracefully.
8
-
9
- Reserve `.expect()` for programming errors where panic is appropriate.
10
-
11
- ## Bad
12
-
13
- ```rust
14
- // Network failures are expected - don't panic
15
- let response = client.get(url).await.expect("failed to fetch");
16
-
17
- // Files might not exist
18
- let config = fs::read_to_string("config.toml").expect("config not found");
19
-
20
- // User input can be invalid
21
- let age: u32 = input.parse().expect("invalid age");
22
-
23
- // Database queries can fail
24
- let user = db.find_user(id).await.expect("user not found");
25
- ```
26
-
27
- ## Good
28
-
29
- ```rust
30
- // Handle recoverable errors properly
31
- let response = client.get(url).await
32
- .context("failed to fetch URL")?;
33
-
34
- // Return error if file doesn't exist
35
- let config = fs::read_to_string("config.toml")
36
- .context("failed to read config file")?;
37
-
38
- // Validate and return error
39
- let age: u32 = input.parse()
40
- .map_err(|_| Error::InvalidInput("age must be a number"))?;
41
-
42
- // Handle missing data
43
- let user = db.find_user(id).await?
44
- .ok_or(Error::NotFound("user"))?;
45
- ```
46
-
47
- ## When expect() Is Appropriate
48
-
49
- Use `.expect()` for invariants that indicate bugs:
50
-
51
- ```rust
52
- // Mutex poisoning indicates a bug elsewhere
53
- let guard = mutex.lock().expect("mutex poisoned");
54
-
55
- // Regex is known valid at compile time
56
- let re = Regex::new(r"^\d{4}$").expect("invalid regex");
57
-
58
- // Thread spawn failure is unrecoverable
59
- let handle = thread::spawn(|| work()).expect("failed to spawn thread");
60
-
61
- // Static data that must be valid
62
- let config: Config = toml::from_str(EMBEDDED_CONFIG)
63
- .expect("embedded config is invalid");
64
- ```
65
-
66
- ## Pattern: expect() vs unwrap()
67
-
68
- ```rust
69
- // unwrap: no context, hard to debug
70
- let x = option.unwrap();
71
-
72
- // expect: gives context, still panics
73
- let x = option.expect("value should exist after validation");
74
-
75
- // ?: proper error handling
76
- let x = option.ok_or(Error::MissingValue)?;
77
- ```
78
-
79
- ## Decision Guide
80
-
81
- | Situation | Use |
82
- |-----------|-----|
83
- | User input | `?` with error |
84
- | File/network I/O | `?` with error |
85
- | Database operations | `?` with error |
86
- | Parsed constants | `.expect()` |
87
- | Thread/mutex operations | `.expect()` |
88
- | After validation check | `.expect()` with explanation |
89
- | Never expected to fail | `.expect()` documenting invariant |
90
-
91
- ## See Also
92
-
93
- - [err-expect-bugs-only](./err-expect-bugs-only.md) - When to use expect
94
- - [err-no-unwrap-prod](./err-no-unwrap-prod.md) - Avoiding unwrap
95
- - [anti-unwrap-abuse](./anti-unwrap-abuse.md) - Unwrap anti-pattern
@@ -1,141 +0,0 @@
1
- # anti-format-hot-path
2
-
3
- > Don't use format! in hot paths
4
-
5
- ## Why It Matters
6
-
7
- `format!()` allocates a new `String` every call. In hot paths (loops, frequently called functions), this creates allocation churn that impacts performance. Pre-allocate, reuse buffers, or use `write!()` to an existing buffer.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // format! in loop - allocates every iteration
13
- fn log_events(events: &[Event]) {
14
- for event in events {
15
- let message = format!("[{}] {}: {}", event.level, event.source, event.message);
16
- logger.log(&message);
17
- }
18
- }
19
-
20
- // format! for building parts
21
- fn build_url(base: &str, path: &str, params: &[(&str, &str)]) -> String {
22
- let mut url = format!("{}{}", base, path);
23
- for (key, value) in params {
24
- url = format!("{}{}={}&", url, key, value); // New allocation each time
25
- }
26
- url
27
- }
28
-
29
- // format! for simple concatenation
30
- fn greet(name: &str) -> String {
31
- format!("Hello, {}!", name) // Fine for one-off, bad if called 1M times
32
- }
33
- ```
34
-
35
- ## Good
36
-
37
- ```rust
38
- use std::fmt::Write;
39
-
40
- // Reuse buffer across iterations
41
- fn log_events(events: &[Event]) {
42
- let mut buffer = String::with_capacity(256);
43
- for event in events {
44
- buffer.clear();
45
- write!(buffer, "[{}] {}: {}", event.level, event.source, event.message).unwrap();
46
- logger.log(&buffer);
47
- }
48
- }
49
-
50
- // Build incrementally in single buffer
51
- fn build_url(base: &str, path: &str, params: &[(&str, &str)]) -> String {
52
- let mut url = String::with_capacity(base.len() + path.len() + params.len() * 20);
53
- url.push_str(base);
54
- url.push_str(path);
55
- for (key, value) in params {
56
- write!(url, "{}={}&", key, value).unwrap();
57
- }
58
- url
59
- }
60
-
61
- // For truly hot paths, avoid allocation entirely
62
- fn greet_to_buf(name: &str, buffer: &mut String) {
63
- buffer.clear();
64
- buffer.push_str("Hello, ");
65
- buffer.push_str(name);
66
- buffer.push('!');
67
- }
68
- ```
69
-
70
- ## Comparison
71
-
72
- | Approach | Allocations | Performance |
73
- |----------|-------------|-------------|
74
- | `format!()` in loop | N | Slow |
75
- | `write!()` to reused buffer | 1 | Fast |
76
- | `push_str()` + `push()` | 1 | Fastest |
77
- | Pre-sized `String::with_capacity()` | 1 (no realloc) | Fast |
78
-
79
- ## When format! Is Fine
80
-
81
- ```rust
82
- // One-time initialization
83
- let config_path = format!("{}/config.toml", home_dir);
84
-
85
- // Error messages (not hot path)
86
- return Err(format!("invalid input: {}", input));
87
-
88
- // Debug output
89
- println!("Debug: {:?}", value);
90
- ```
91
-
92
- ## Pattern: Formatter Buffer Pool
93
-
94
- ```rust
95
- use std::cell::RefCell;
96
-
97
- thread_local! {
98
- static BUFFER: RefCell<String> = RefCell::new(String::with_capacity(256));
99
- }
100
-
101
- fn format_event(event: &Event) -> String {
102
- BUFFER.with(|buf| {
103
- let mut buf = buf.borrow_mut();
104
- buf.clear();
105
- write!(buf, "[{}] {}", event.level, event.message).unwrap();
106
- buf.clone() // Still one allocation per call, but no parsing
107
- })
108
- }
109
- ```
110
-
111
- ## Pattern: Display Implementation
112
-
113
- ```rust
114
- struct Event {
115
- level: Level,
116
- message: String,
117
- }
118
-
119
- impl std::fmt::Display for Event {
120
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121
- write!(f, "[{}] {}", self.level, self.message)
122
- }
123
- }
124
-
125
- // Caller controls allocation
126
- let mut buf = String::new();
127
- write!(buf, "{}", event)?;
128
- ```
129
-
130
- ## Clippy Lint
131
-
132
- ```toml
133
- [lints.clippy]
134
- format_in_format_args = "warn"
135
- ```
136
-
137
- ## See Also
138
-
139
- - [mem-avoid-format](./mem-avoid-format.md) - Avoiding format
140
- - [mem-write-over-format](./mem-write-over-format.md) - Using write!
141
- - [mem-reuse-collections](./mem-reuse-collections.md) - Buffer reuse