agy-superpowers 5.2.1 → 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 (233) hide show
  1. package/README.md +47 -150
  2. package/package.json +1 -1
  3. package/template/agent/patches/skills-patches.md +23 -0
  4. package/template/agent/rules/scratch-scripts.md +37 -0
  5. package/template/agent/rules/superpowers.md +6 -50
  6. package/template/agent/skills/brainstorming/SKILL.md +4 -3
  7. package/template/agent/skills/brainstorming/visual-companion.md +2 -3
  8. package/template/agent/skills/finishing-a-development-branch/SKILL.md +11 -16
  9. package/template/agent/skills/subagent-driven-development/SKILL.md +16 -0
  10. package/template/agent/skills/subagent-driven-development/implementer-prompt.md +4 -3
  11. package/template/agent/skills/using-git-worktrees/SKILL.md +3 -2
  12. package/template/agent/skills/using-superpowers/SKILL.md +8 -6
  13. package/template/agent/skills/using-superpowers/references/copilot-tools.md +52 -0
  14. package/template/agent/skills/writing-plans/SKILL.md +5 -3
  15. package/template/agent/skills/writing-skills/SKILL.md +1 -1
  16. package/template/agent/superpowers-version.json +2 -2
  17. package/template/agent/tmp/agent-config-backup.yml +9 -0
  18. package/template/agent/skills/ai-integrated-product/SKILL.md +0 -57
  19. package/template/agent/skills/analytics-setup/SKILL.md +0 -51
  20. package/template/agent/skills/api-design/SKILL.md +0 -193
  21. package/template/agent/skills/app-store-optimizer/SKILL.md +0 -127
  22. package/template/agent/skills/auth-and-identity/SKILL.md +0 -167
  23. package/template/agent/skills/backend-developer/SKILL.md +0 -148
  24. package/template/agent/skills/bootstrapper-finance/SKILL.md +0 -55
  25. package/template/agent/skills/chrome-extension-developer/SKILL.md +0 -53
  26. package/template/agent/skills/community-manager/SKILL.md +0 -115
  27. package/template/agent/skills/content-marketer/SKILL.md +0 -111
  28. package/template/agent/skills/conversion-optimizer/SKILL.md +0 -142
  29. package/template/agent/skills/cto-architect/SKILL.md +0 -133
  30. package/template/agent/skills/customer-success-manager/SKILL.md +0 -126
  31. package/template/agent/skills/data-analyst/SKILL.md +0 -147
  32. package/template/agent/skills/devops-engineer/SKILL.md +0 -117
  33. package/template/agent/skills/email-infrastructure/SKILL.md +0 -164
  34. package/template/agent/skills/game-design/SKILL.md +0 -194
  35. package/template/agent/skills/game-developer/SKILL.md +0 -175
  36. package/template/agent/skills/growth-hacker/SKILL.md +0 -122
  37. package/template/agent/skills/idea-validator/SKILL.md +0 -55
  38. package/template/agent/skills/indie-legal/SKILL.md +0 -53
  39. package/template/agent/skills/influencer-marketer/SKILL.md +0 -141
  40. package/template/agent/skills/landing-page-builder/SKILL.md +0 -59
  41. package/template/agent/skills/launch-strategist/SKILL.md +0 -62
  42. package/template/agent/skills/market-researcher/SKILL.md +0 -53
  43. package/template/agent/skills/micro-saas-builder/SKILL.md +0 -56
  44. package/template/agent/skills/monetization-strategist/SKILL.md +0 -119
  45. package/template/agent/skills/paid-acquisition-specialist/SKILL.md +0 -119
  46. package/template/agent/skills/pricing-psychologist/SKILL.md +0 -58
  47. package/template/agent/skills/real-time-features/SKILL.md +0 -194
  48. package/template/agent/skills/retention-specialist/SKILL.md +0 -123
  49. package/template/agent/skills/rust-developer/SKILL.md +0 -281
  50. package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +0 -231
  51. package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +0 -124
  52. package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +0 -131
  53. package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +0 -132
  54. package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +0 -95
  55. package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +0 -141
  56. package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +0 -125
  57. package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +0 -127
  58. package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +0 -120
  59. package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +0 -131
  60. package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +0 -156
  61. package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +0 -122
  62. package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +0 -167
  63. package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +0 -134
  64. package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +0 -143
  65. package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +0 -121
  66. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +0 -143
  67. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +0 -187
  68. package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +0 -165
  69. package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +0 -177
  70. package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +0 -163
  71. package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +0 -146
  72. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +0 -142
  73. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +0 -160
  74. package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +0 -125
  75. package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +0 -162
  76. package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +0 -177
  77. package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +0 -184
  78. package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +0 -168
  79. package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +0 -182
  80. package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +0 -199
  81. package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +0 -175
  82. package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +0 -185
  83. package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +0 -203
  84. package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +0 -171
  85. package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +0 -158
  86. package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +0 -195
  87. package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +0 -171
  88. package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +0 -156
  89. package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +0 -191
  90. package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +0 -198
  91. package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +0 -154
  92. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +0 -167
  93. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +0 -169
  94. package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +0 -172
  95. package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +0 -189
  96. package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +0 -113
  97. package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +0 -147
  98. package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +0 -122
  99. package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +0 -161
  100. package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +0 -149
  101. package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +0 -138
  102. package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +0 -169
  103. package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +0 -116
  104. package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +0 -128
  105. package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +0 -136
  106. package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +0 -131
  107. package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +0 -179
  108. package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +0 -144
  109. package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +0 -152
  110. package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +0 -145
  111. package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +0 -133
  112. package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +0 -152
  113. package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +0 -124
  114. package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +0 -115
  115. package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +0 -151
  116. package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +0 -130
  117. package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +0 -155
  118. package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +0 -171
  119. package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +0 -138
  120. package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +0 -107
  121. package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +0 -154
  122. package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +0 -118
  123. package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +0 -157
  124. package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +0 -133
  125. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +0 -131
  126. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +0 -136
  127. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +0 -135
  128. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +0 -122
  129. package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +0 -172
  130. package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +0 -168
  131. package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +0 -142
  132. package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +0 -168
  133. package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +0 -147
  134. package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +0 -158
  135. package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +0 -139
  136. package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +0 -147
  137. package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +0 -149
  138. package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +0 -174
  139. package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +0 -159
  140. package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +0 -138
  141. package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +0 -142
  142. package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +0 -156
  143. package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +0 -172
  144. package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +0 -164
  145. package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +0 -99
  146. package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +0 -104
  147. package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +0 -94
  148. package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +0 -78
  149. package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +0 -76
  150. package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +0 -123
  151. package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +0 -127
  152. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +0 -129
  153. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +0 -131
  154. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +0 -142
  155. package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +0 -86
  156. package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +0 -154
  157. package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +0 -118
  158. package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +0 -92
  159. package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +0 -65
  160. package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +0 -101
  161. package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +0 -161
  162. package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +0 -187
  163. package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +0 -142
  164. package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +0 -152
  165. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +0 -141
  166. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +0 -181
  167. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +0 -160
  168. package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +0 -171
  169. package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +0 -130
  170. package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +0 -167
  171. package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +0 -144
  172. package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +0 -154
  173. package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +0 -141
  174. package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +0 -95
  175. package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +0 -135
  176. package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +0 -124
  177. package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +0 -135
  178. package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +0 -134
  179. package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +0 -134
  180. package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +0 -105
  181. package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +0 -65
  182. package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +0 -97
  183. package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +0 -122
  184. package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +0 -119
  185. package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +0 -153
  186. package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +0 -136
  187. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +0 -133
  188. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +0 -120
  189. package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +0 -137
  190. package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +0 -134
  191. package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +0 -150
  192. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +0 -123
  193. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +0 -113
  194. package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +0 -175
  195. package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +0 -149
  196. package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +0 -142
  197. package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +0 -133
  198. package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +0 -148
  199. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +0 -130
  200. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +0 -120
  201. package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +0 -155
  202. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +0 -139
  203. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +0 -135
  204. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +0 -162
  205. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +0 -186
  206. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +0 -162
  207. package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +0 -160
  208. package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +0 -151
  209. package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +0 -171
  210. package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +0 -142
  211. package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +0 -168
  212. package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +0 -151
  213. package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +0 -144
  214. package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +0 -189
  215. package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +0 -226
  216. package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +0 -161
  217. package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +0 -130
  218. package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +0 -154
  219. package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +0 -127
  220. package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +0 -154
  221. package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +0 -142
  222. package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +0 -146
  223. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +0 -160
  224. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +0 -159
  225. package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +0 -144
  226. package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +0 -137
  227. package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +0 -188
  228. package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +0 -143
  229. package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +0 -131
  230. package/template/agent/skills/saas-architect/SKILL.md +0 -139
  231. package/template/agent/skills/security-engineer/SKILL.md +0 -133
  232. package/template/agent/skills/seo-specialist/SKILL.md +0 -130
  233. package/template/agent/skills/solo-founder-ops/SKILL.md +0 -56
@@ -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
@@ -1,125 +0,0 @@
1
- # anti-index-over-iter
2
-
3
- > Don't use indexing when iterators work
4
-
5
- ## Why It Matters
6
-
7
- Manual indexing (`for i in 0..len`) requires bounds checks on every access, prevents SIMD optimization, and introduces off-by-one error risks. Iterators eliminate these issues and are more idiomatic Rust.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Manual indexing - bounds checked every access
13
- fn sum_squares(data: &[i32]) -> i64 {
14
- let mut result = 0i64;
15
- for i in 0..data.len() {
16
- result += (data[i] as i64) * (data[i] as i64);
17
- }
18
- result
19
- }
20
-
21
- // Index-based with multiple arrays
22
- fn dot_product(a: &[f64], b: &[f64]) -> f64 {
23
- let mut sum = 0.0;
24
- for i in 0..a.len().min(b.len()) {
25
- sum += a[i] * b[i];
26
- }
27
- sum
28
- }
29
-
30
- // Mutation with indices
31
- fn normalize(data: &mut [f64]) {
32
- let max = data.iter().cloned().fold(0.0, f64::max);
33
- for i in 0..data.len() {
34
- data[i] /= max;
35
- }
36
- }
37
- ```
38
-
39
- ## Good
40
-
41
- ```rust
42
- // Iterator - no bounds checks, SIMD-friendly
43
- fn sum_squares(data: &[i32]) -> i64 {
44
- data.iter()
45
- .map(|&x| (x as i64) * (x as i64))
46
- .sum()
47
- }
48
-
49
- // Zip - handles length mismatch automatically
50
- fn dot_product(a: &[f64], b: &[f64]) -> f64 {
51
- a.iter()
52
- .zip(b.iter())
53
- .map(|(&x, &y)| x * y)
54
- .sum()
55
- }
56
-
57
- // Mutable iteration
58
- fn normalize(data: &mut [f64]) {
59
- let max = data.iter().cloned().fold(0.0, f64::max);
60
- for x in data.iter_mut() {
61
- *x /= max;
62
- }
63
- }
64
- ```
65
-
66
- ## When Indices Are Needed
67
-
68
- Sometimes you genuinely need indices:
69
-
70
- ```rust
71
- // Need index in output
72
- for (i, item) in items.iter().enumerate() {
73
- println!("{}: {}", i, item);
74
- }
75
-
76
- // Non-sequential access
77
- for i in (0..len).step_by(2) {
78
- swap(&mut data[i], &mut data[i + 1]);
79
- }
80
-
81
- // Multi-dimensional iteration
82
- for i in 0..rows {
83
- for j in 0..cols {
84
- matrix[i][j] = i * cols + j;
85
- }
86
- }
87
- ```
88
-
89
- ## Comparison
90
-
91
- | Pattern | Bounds Checks | SIMD | Safety |
92
- |---------|---------------|------|--------|
93
- | `for i in 0..len { data[i] }` | Every access | Limited | Off-by-one risk |
94
- | `for x in &data` | None | Good | Safe |
95
- | `for x in data.iter()` | None | Good | Safe |
96
- | `data.iter().enumerate()` | None | Good | Safe |
97
-
98
- ## Common Conversions
99
-
100
- | Index Pattern | Iterator Pattern |
101
- |---------------|------------------|
102
- | `for i in 0..v.len()` | `for x in &v` |
103
- | `v[0]` | `v.first()` |
104
- | `v[v.len()-1]` | `v.last()` |
105
- | `for i in 0..a.len() { a[i] + b[i] }` | `a.iter().zip(&b)` |
106
- | `for i in 0..v.len() { v[i] *= 2 }` | `for x in &mut v { *x *= 2 }` |
107
-
108
- ## Performance Note
109
-
110
- ```rust
111
- // Iterator version can auto-vectorize
112
- let sum: i32 = data.iter().sum();
113
-
114
- // Manual indexing prevents vectorization
115
- let mut sum = 0;
116
- for i in 0..data.len() {
117
- sum += data[i];
118
- }
119
- ```
120
-
121
- ## See Also
122
-
123
- - [perf-iter-over-index](./perf-iter-over-index.md) - Performance details
124
- - [opt-bounds-check](./opt-bounds-check.md) - Bounds check elimination
125
- - [perf-iter-lazy](./perf-iter-lazy.md) - Lazy iterators