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,127 +0,0 @@
1
- # anti-lock-across-await
2
-
3
- > Don't hold locks across await points
4
-
5
- ## Why It Matters
6
-
7
- Holding a `Mutex` or `RwLock` guard across an `.await` causes the lock to be held while the task is suspended. Other tasks waiting for the lock block indefinitely. With `std::sync::Mutex`, this is even worse—it can deadlock the entire runtime.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- use std::sync::Mutex;
13
- use tokio::sync::Mutex as AsyncMutex;
14
-
15
- // DEADLOCK RISK: std::sync::Mutex held across await
16
- async fn bad_std_mutex(data: &Mutex<Vec<i32>>) {
17
- let mut guard = data.lock().unwrap();
18
- do_async_work().await; // Lock held during await!
19
- guard.push(42);
20
- }
21
-
22
- // BLOCKS OTHER TASKS: tokio Mutex held across await
23
- async fn bad_async_mutex(data: &AsyncMutex<Vec<i32>>) {
24
- let mut guard = data.lock().await;
25
- slow_network_call().await; // Lock held for entire call!
26
- guard.push(42);
27
- }
28
- ```
29
-
30
- ## Good
31
-
32
- ```rust
33
- use std::sync::Mutex;
34
- use tokio::sync::Mutex as AsyncMutex;
35
-
36
- // Release lock before await
37
- async fn good_approach(data: &Mutex<Vec<i32>>) {
38
- let value = {
39
- let guard = data.lock().unwrap();
40
- guard.last().copied() // Extract what you need
41
- }; // Lock released here
42
-
43
- let result = do_async_work(value).await;
44
-
45
- {
46
- let mut guard = data.lock().unwrap();
47
- guard.push(result);
48
- }
49
- }
50
-
51
- // Minimize lock scope with async mutex
52
- async fn good_async_mutex(data: &AsyncMutex<Vec<i32>>, item: i32) {
53
- // Quick lock, quick release
54
- data.lock().await.push(item);
55
-
56
- // Async work without lock
57
- let result = slow_network_call().await;
58
-
59
- // Quick lock again
60
- data.lock().await.push(result);
61
- }
62
- ```
63
-
64
- ## Pattern: Clone Before Await
65
-
66
- ```rust
67
- async fn process(data: &AsyncMutex<Config>) -> Result<()> {
68
- // Clone inside lock scope
69
- let config = data.lock().await.clone();
70
-
71
- // Now use config freely across awaits
72
- let result = fetch_data(&config.url).await?;
73
- process_result(&config, result).await?;
74
-
75
- Ok(())
76
- }
77
- ```
78
-
79
- ## Pattern: Restructure to Avoid Lock
80
-
81
- ```rust
82
- // Instead of locking a shared map
83
- struct Service {
84
- data: AsyncMutex<HashMap<String, Data>>,
85
- }
86
-
87
- // Use channels or owned data
88
- struct BetterService {
89
- // Each task owns its data via channels
90
- sender: mpsc::Sender<Request>,
91
- }
92
-
93
- impl BetterService {
94
- async fn request(&self, key: String) -> Data {
95
- let (tx, rx) = oneshot::channel();
96
- self.sender.send(Request { key, respond: tx }).await?;
97
- rx.await?
98
- }
99
- }
100
- ```
101
-
102
- ## What Can Cross Await
103
-
104
- | Type | Safe Across Await? |
105
- |------|--------------------|
106
- | `std::sync::Mutex` guard | **NO** - can deadlock |
107
- | `std::sync::RwLock` guard | **NO** - can deadlock |
108
- | `tokio::sync::Mutex` guard | Allowed but blocks tasks |
109
- | `tokio::sync::RwLock` guard | Allowed but blocks tasks |
110
- | Owned values | Yes |
111
- | `Arc<T>` | Yes |
112
- | References | Depends on lifetime |
113
-
114
- ## Detection
115
-
116
- ```toml
117
- # Cargo.toml
118
- [lints.clippy]
119
- await_holding_lock = "deny"
120
- await_holding_refcell_ref = "deny"
121
- ```
122
-
123
- ## See Also
124
-
125
- - [async-no-lock-await](./async-no-lock-await.md) - Async lock patterns
126
- - [async-clone-before-await](./async-clone-before-await.md) - Clone pattern
127
- - [own-mutex-interior](./own-mutex-interior.md) - Mutex usage
@@ -1,120 +0,0 @@
1
- # anti-over-abstraction
2
-
3
- > Don't over-abstract with excessive generics
4
-
5
- ## Why It Matters
6
-
7
- Generics and traits are powerful but come at a cost: compile times, binary size, and cognitive load. Over-abstraction—making everything generic "for flexibility"—often adds complexity without benefit. Start concrete; generalize when you have real use cases.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Overly generic for a simple function
13
- fn add<T, U, R>(a: T, b: U) -> R
14
- where
15
- T: Into<R>,
16
- U: Into<R>,
17
- R: std::ops::Add<Output = R>,
18
- {
19
- a.into() + b.into()
20
- }
21
-
22
- // Just call add(1, 2) - why make it this complex?
23
-
24
- // Trait explosion
25
- trait Readable {}
26
- trait Writable {}
27
- trait ReadWritable: Readable + Writable {}
28
- trait AsyncReadable {}
29
- trait AsyncWritable {}
30
- trait AsyncReadWritable: AsyncReadable + AsyncWritable {}
31
-
32
- // Abstract factory pattern (Java flashback)
33
- trait Factory<T> {
34
- fn create(&self) -> T;
35
- }
36
- trait FactoryFactory<F: Factory<T>, T> {
37
- fn create_factory(&self) -> F;
38
- }
39
- ```
40
-
41
- ## Good
42
-
43
- ```rust
44
- // Concrete implementation - clear and simple
45
- fn add_i32(a: i32, b: i32) -> i32 {
46
- a + b
47
- }
48
-
49
- // Generic when actually needed (e.g., library code)
50
- fn add<T: std::ops::Add<Output = T>>(a: T, b: T) -> T {
51
- a + b
52
- }
53
-
54
- // Simple traits for actual polymorphism needs
55
- trait Storage {
56
- fn save(&self, key: &str, value: &[u8]) -> Result<(), Error>;
57
- fn load(&self, key: &str) -> Result<Vec<u8>, Error>;
58
- }
59
-
60
- // Concrete types first
61
- struct FileStorage { path: PathBuf }
62
- struct MemoryStorage { data: HashMap<String, Vec<u8>> }
63
- ```
64
-
65
- ## Signs of Over-Abstraction
66
-
67
- | Sign | Symptom |
68
- |------|---------|
69
- | Single implementation | Generic trait with only one impl |
70
- | Type parameter soup | `T, U, V, W` everywhere |
71
- | Marker traits | Traits with no methods |
72
- | Deep trait bounds | `where T: A + B + C + D + E` |
73
- | Phantom generics | Type parameters not used meaningfully |
74
-
75
- ## When to Generalize
76
-
77
- Generalize when:
78
- - You have 2+ concrete types that share behavior
79
- - You're writing library code for public consumption
80
- - Performance requires static dispatch
81
- - The abstraction simplifies the API
82
-
83
- Don't generalize when:
84
- - You "might need it later" (YAGNI)
85
- - Only one type will ever implement it
86
- - It makes code harder to understand
87
-
88
- ## Rule of Three
89
-
90
- Wait until you have three similar concrete implementations before abstracting:
91
-
92
- ```rust
93
- // Version 1: Just FileStorage
94
- struct FileStorage { /* ... */ }
95
-
96
- // Version 2: Added MemoryStorage, similar interface
97
- struct MemoryStorage { /* ... */ }
98
-
99
- // Version 3: Now Redis too - time to abstract
100
- trait Storage {
101
- fn save(&self, key: &str, value: &[u8]) -> Result<()>;
102
- fn load(&self, key: &str) -> Result<Vec<u8>>;
103
- }
104
- ```
105
-
106
- ## Prefer Concrete Types in Private Code
107
-
108
- ```rust
109
- // Internal function - concrete type is fine
110
- fn process_orders(db: &PostgresDb, orders: Vec<Order>) { }
111
-
112
- // Public API - might benefit from abstraction
113
- pub fn process_orders<S: Storage>(storage: &S, orders: Vec<Order>) { }
114
- ```
115
-
116
- ## See Also
117
-
118
- - [type-generic-bounds](./type-generic-bounds.md) - Minimal bounds
119
- - [api-sealed-trait](./api-sealed-trait.md) - Controlled extension
120
- - [anti-type-erasure](./anti-type-erasure.md) - When Box<dyn> is wrong
@@ -1,131 +0,0 @@
1
- # anti-panic-expected
2
-
3
- > Don't panic on expected or recoverable errors
4
-
5
- ## Why It Matters
6
-
7
- Panics crash the program. They're for unrecoverable situations—bugs, corrupted state, invariant violations. Using panic for expected conditions (network failures, file not found, invalid input) makes programs fragile and forces callers to catch panics or die.
8
-
9
- Use `Result` for recoverable errors.
10
-
11
- ## Bad
12
-
13
- ```rust
14
- // Network failures are expected
15
- fn fetch_data(url: &str) -> Data {
16
- let response = reqwest::blocking::get(url)
17
- .expect("network error"); // Crashes on timeout
18
- response.json().expect("invalid json") // Crashes on bad response
19
- }
20
-
21
- // User input is often invalid
22
- fn parse_config(input: &str) -> Config {
23
- toml::from_str(input).expect("invalid config") // Crashes on typo
24
- }
25
-
26
- // Files may not exist
27
- fn load_settings() -> Settings {
28
- let content = fs::read_to_string("settings.json")
29
- .expect("settings not found"); // Crashes if missing
30
- serde_json::from_str(&content).expect("invalid settings")
31
- }
32
-
33
- // Custom panic for validation
34
- fn process_age(age: i32) {
35
- if age < 0 {
36
- panic!("age cannot be negative"); // Should return error
37
- }
38
- }
39
- ```
40
-
41
- ## Good
42
-
43
- ```rust
44
- // Return errors for expected failures
45
- fn fetch_data(url: &str) -> Result<Data, FetchError> {
46
- let response = reqwest::blocking::get(url)
47
- .context("failed to connect")?;
48
- let data = response.json()
49
- .context("failed to parse response")?;
50
- Ok(data)
51
- }
52
-
53
- // Validate and return Result
54
- fn parse_config(input: &str) -> Result<Config, ConfigError> {
55
- toml::from_str(input).map_err(ConfigError::Parse)
56
- }
57
-
58
- // Handle missing files gracefully
59
- fn load_settings() -> Result<Settings, SettingsError> {
60
- let content = fs::read_to_string("settings.json")?;
61
- let settings = serde_json::from_str(&content)?;
62
- Ok(settings)
63
- }
64
-
65
- // Return error for validation failure
66
- fn process_age(age: i32) -> Result<(), ValidationError> {
67
- if age < 0 {
68
- return Err(ValidationError::NegativeAge);
69
- }
70
- Ok(())
71
- }
72
- ```
73
-
74
- ## When to Panic
75
-
76
- Panic IS appropriate for:
77
-
78
- ```rust
79
- // Bug detection - invariant violated
80
- fn get_unchecked(&self, index: usize) -> &T {
81
- assert!(index < self.len(), "index out of bounds - this is a bug");
82
- unsafe { self.data.get_unchecked(index) }
83
- }
84
-
85
- // Unrecoverable state
86
- fn init() {
87
- if !CAN_PROCEED {
88
- panic!("system requirements not met");
89
- }
90
- }
91
-
92
- // Tests
93
- #[test]
94
- fn test_fails() {
95
- panic!("expected panic in test");
96
- }
97
- ```
98
-
99
- ## Decision Guide
100
-
101
- | Condition | Action |
102
- |-----------|--------|
103
- | Invalid user input | Return `Err` |
104
- | Network failure | Return `Err` |
105
- | File not found | Return `Err` |
106
- | Malformed data | Return `Err` |
107
- | Bug/impossible state | `panic!` or `unreachable!` |
108
- | Failed assertion in test | `panic!` |
109
- | Unrecoverable init failure | `panic!` |
110
-
111
- ## Anti-pattern: panic! for Control Flow
112
-
113
- ```rust
114
- // BAD: Using panic for control flow
115
- fn find_or_die(items: &[Item], id: u64) -> &Item {
116
- items.iter()
117
- .find(|i| i.id == id)
118
- .unwrap_or_else(|| panic!("item {} not found", id))
119
- }
120
-
121
- // GOOD: Return Option or Result
122
- fn find(items: &[Item], id: u64) -> Option<&Item> {
123
- items.iter().find(|i| i.id == id)
124
- }
125
- ```
126
-
127
- ## See Also
128
-
129
- - [err-result-over-panic](./err-result-over-panic.md) - Use Result
130
- - [anti-unwrap-abuse](./anti-unwrap-abuse.md) - Unwrap anti-pattern
131
- - [err-expect-bugs-only](./err-expect-bugs-only.md) - When to expect
@@ -1,156 +0,0 @@
1
- # anti-premature-optimize
2
-
3
- > Don't optimize before profiling
4
-
5
- ## Why It Matters
6
-
7
- Premature optimization wastes time, complicates code, and often targets the wrong bottlenecks. Most code isn't performance-critical; the hot 10% matters. Profile first, then optimize the actual bottlenecks with data-driven decisions.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // "Optimizing" without measurement
13
- fn sum(data: &[i32]) -> i32 {
14
- // Using unsafe "for performance" without profiling
15
- unsafe {
16
- let mut sum = 0;
17
- for i in 0..data.len() {
18
- sum += *data.get_unchecked(i);
19
- }
20
- sum
21
- }
22
- }
23
-
24
- // Complex caching with no evidence it's needed
25
- lazy_static! {
26
- static ref CACHE: RwLock<HashMap<String, Arc<Result>>> =
27
- RwLock::new(HashMap::new());
28
- }
29
-
30
- // Hand-rolled data structures "for speed"
31
- struct MyVec<T> {
32
- ptr: *mut T,
33
- len: usize,
34
- cap: usize,
35
- }
36
- ```
37
-
38
- ## Good
39
-
40
- ```rust
41
- // Simple, idiomatic - let compiler optimize
42
- fn sum(data: &[i32]) -> i32 {
43
- data.iter().sum()
44
- }
45
-
46
- // Profile, then optimize if needed
47
- fn sum_optimized(data: &[i32]) -> i32 {
48
- // After profiling showed this is a bottleneck,
49
- // we measured that manual SIMD gives 3x speedup
50
- #[cfg(target_arch = "x86_64")]
51
- {
52
- // SIMD implementation with benchmark data
53
- }
54
- #[cfg(not(target_arch = "x86_64"))]
55
- {
56
- data.iter().sum()
57
- }
58
- }
59
-
60
- // Use standard library - it's well-optimized
61
- let cache: HashMap<String, Result> = HashMap::new();
62
- ```
63
-
64
- ## Profiling Workflow
65
-
66
- ```bash
67
- # 1. Write correct code first
68
- cargo build --release
69
-
70
- # 2. Profile with real workloads
71
- cargo flamegraph --bin my_app -- --real-args
72
- # or
73
- cargo bench
74
-
75
- # 3. Identify hotspots (top 10% of time)
76
-
77
- # 4. Measure before optimizing
78
- # 5. Optimize ONE thing
79
- # 6. Measure after - verify improvement
80
- # 7. Repeat if still slow
81
- ```
82
-
83
- ## Optimization Principles
84
-
85
- | Do | Don't |
86
- |----|-------|
87
- | Profile first | Guess at bottlenecks |
88
- | Optimize hotspots | Optimize everything |
89
- | Measure improvement | Assume it's faster |
90
- | Keep it simple | Add complexity speculatively |
91
- | Trust the compiler | Outsmart the compiler |
92
-
93
- ## When to Optimize
94
-
95
- ```rust
96
- // AFTER profiling shows this is 40% of runtime
97
- #[inline]
98
- fn hot_function(data: &[u8]) -> u64 {
99
- // Optimized implementation justified by benchmarks
100
- }
101
-
102
- // Clear, measurable benefit documented
103
- /// Pre-allocated buffer for repeated formatting.
104
- /// Benchmarks show 3x speedup for >1000 calls/sec workloads.
105
- struct FormatterPool {
106
- buffers: Vec<String>,
107
- }
108
- ```
109
-
110
- ## Common Premature Optimizations
111
-
112
- | Premature | Reality |
113
- |-----------|---------|
114
- | `#[inline(always)]` everywhere | Compiler usually knows better |
115
- | `unsafe` for bounds check removal | Iterator does this safely |
116
- | Custom allocator | Default is usually fine |
117
- | Object pooling | Allocator is fast enough |
118
- | Manual SIMD | Auto-vectorization works |
119
-
120
- ## Profile Tools
121
-
122
- ```bash
123
- # Sampling profiler
124
- perf record ./target/release/app && perf report
125
-
126
- # Flamegraph
127
- cargo install flamegraph
128
- cargo flamegraph
129
-
130
- # Criterion benchmarks
131
- cargo bench
132
-
133
- # Memory profiling
134
- valgrind --tool=massif ./target/release/app
135
- ```
136
-
137
- ## Document Optimizations
138
-
139
- ```rust
140
- /// Lookup table for fast character classification.
141
- ///
142
- /// # Performance
143
- ///
144
- /// Benchmarked with criterion (benchmarks/char_class.rs):
145
- /// - Table lookup: 2.3ns/op
146
- /// - Match statement: 8.7ns/op
147
- ///
148
- /// Justified for hot path in parser (called 10M+ times).
149
- static CHAR_CLASS: [CharClass; 256] = [/* ... */];
150
- ```
151
-
152
- ## See Also
153
-
154
- - [perf-profile-first](./perf-profile-first.md) - Profile before optimize
155
- - [test-criterion-bench](./test-criterion-bench.md) - Benchmarking
156
- - [opt-inline-small](./opt-inline-small.md) - Inline guidelines
@@ -1,122 +0,0 @@
1
- # anti-string-for-str
2
-
3
- > Don't accept &String when &str works
4
-
5
- ## Why It Matters
6
-
7
- `&String` is strictly less flexible than `&str`. A `&str` can be created from `String`, `&str`, literals, and slices. A `&String` requires exactly a `String`. This forces callers to allocate when they might not need to.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Forces callers to have a String
13
- fn greet(name: &String) {
14
- println!("Hello, {}", name);
15
- }
16
-
17
- // Caller must allocate
18
- greet(&"Alice".to_string()); // Unnecessary allocation
19
- greet(&name); // Only works if name is String
20
-
21
- // In struct
22
- struct Config {
23
- name: String,
24
- }
25
-
26
- impl Config {
27
- fn set_name(&mut self, name: &String) { // Too restrictive
28
- self.name = name.clone();
29
- }
30
- }
31
- ```
32
-
33
- ## Good
34
-
35
- ```rust
36
- // Accept &str - works with String, &str, literals
37
- fn greet(name: &str) {
38
- println!("Hello, {}", name);
39
- }
40
-
41
- // All these work
42
- greet("Alice"); // String literal
43
- greet(&name); // &String coerces to &str
44
- greet(name.as_str()); // Explicit &str
45
-
46
- // In struct
47
- impl Config {
48
- fn set_name(&mut self, name: &str) {
49
- self.name = name.to_string();
50
- }
51
-
52
- // Or accept owned String if caller usually has one
53
- fn set_name_owned(&mut self, name: String) {
54
- self.name = name;
55
- }
56
-
57
- // Or be generic
58
- fn set_name_into(&mut self, name: impl Into<String>) {
59
- self.name = name.into();
60
- }
61
- }
62
- ```
63
-
64
- ## Deref Coercion
65
-
66
- `String` implements `Deref<Target = str>`, so `&String` automatically coerces to `&str`:
67
-
68
- ```rust
69
- fn takes_str(s: &str) { }
70
-
71
- let owned = String::from("hello");
72
- takes_str(&owned); // &String -> &str via Deref
73
- ```
74
-
75
- ## When to Accept &String
76
-
77
- Rarely. Maybe if you need `String`-specific methods:
78
-
79
- ```rust
80
- fn needs_capacity(s: &String) -> usize {
81
- s.capacity() // Only String has capacity()
82
- }
83
- ```
84
-
85
- But usually you'd take `&str` and let the caller manage the `String`.
86
-
87
- ## Pattern: Flexible APIs
88
-
89
- ```rust
90
- // Most flexible: accept anything that can become &str
91
- fn process(input: impl AsRef<str>) {
92
- let s: &str = input.as_ref();
93
- // ...
94
- }
95
-
96
- process("literal");
97
- process(String::from("owned"));
98
- process(&some_string);
99
- ```
100
-
101
- ## Similar Anti-patterns
102
-
103
- | Anti-pattern | Better |
104
- |--------------|--------|
105
- | `&String` | `&str` |
106
- | `&Vec<T>` | `&[T]` |
107
- | `&Box<T>` | `&T` |
108
- | `&PathBuf` | `&Path` |
109
- | `&OsString` | `&OsStr` |
110
-
111
- ## Clippy Detection
112
-
113
- ```toml
114
- [lints.clippy]
115
- ptr_arg = "warn" # Catches &String, &Vec, &PathBuf
116
- ```
117
-
118
- ## See Also
119
-
120
- - [anti-vec-for-slice](./anti-vec-for-slice.md) - Similar pattern for Vec
121
- - [own-slice-over-vec](./own-slice-over-vec.md) - Slice patterns
122
- - [api-impl-asref](./api-impl-asref.md) - AsRef pattern