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,167 +0,0 @@
1
- # anti-stringly-typed
2
-
3
- > Don't use strings where enums or newtypes would provide type safety
4
-
5
- ## Why It Matters
6
-
7
- Strings are the most primitive way to represent data—they accept any value, provide no validation, and offer no IDE support. When you have a fixed set of valid values or a semantic type, use enums or newtypes. The compiler catches mistakes at compile time instead of runtime.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- fn process_order(status: &str, priority: &str) {
13
- // What are valid statuses? "pending"? "Pending"? "PENDING"?
14
- // What are valid priorities? "high"? "1"? "urgent"?
15
- match status {
16
- "pending" => { ... }
17
- "completed" => { ... }
18
- _ => panic!("unknown status"), // Runtime error
19
- }
20
- }
21
-
22
- struct User {
23
- email: String, // Any string, even "not an email"
24
- phone: String, // Any string, even "hello"
25
- user_id: String, // Could be confused with other string IDs
26
- }
27
-
28
- // Easy to make mistakes
29
- process_order("complete", "high"); // Typo: "complete" vs "completed"
30
- process_order("high", "pending"); // Swapped arguments - compiles!
31
- ```
32
-
33
- ## Good
34
-
35
- ```rust
36
- #[derive(Debug, Clone, Copy, PartialEq, Eq)]
37
- enum OrderStatus {
38
- Pending,
39
- Processing,
40
- Completed,
41
- Cancelled,
42
- }
43
-
44
- #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
45
- enum Priority {
46
- Low,
47
- Medium,
48
- High,
49
- Critical,
50
- }
51
-
52
- fn process_order(status: OrderStatus, priority: Priority) {
53
- match status {
54
- OrderStatus::Pending => { ... }
55
- OrderStatus::Processing => { ... }
56
- OrderStatus::Completed => { ... }
57
- OrderStatus::Cancelled => { ... }
58
- } // Exhaustive - compiler checks all cases
59
- }
60
-
61
- // Validated newtypes
62
- struct Email(String);
63
- struct PhoneNumber(String);
64
- struct UserId(u64);
65
-
66
- impl Email {
67
- pub fn new(s: &str) -> Result<Self, ValidationError> {
68
- if is_valid_email(s) {
69
- Ok(Email(s.to_string()))
70
- } else {
71
- Err(ValidationError::InvalidEmail)
72
- }
73
- }
74
- }
75
-
76
- struct User {
77
- email: Email, // Must be valid email
78
- phone: PhoneNumber, // Must be valid phone
79
- user_id: UserId, // Can't confuse with other IDs
80
- }
81
-
82
- // Compile errors catch mistakes
83
- process_order(OrderStatus::Completed, Priority::High); // Clear and correct
84
- process_order(Priority::High, OrderStatus::Pending); // Compile error!
85
- ```
86
-
87
- ## Parsing Strings to Types
88
-
89
- ```rust
90
- use std::str::FromStr;
91
-
92
- #[derive(Debug, Clone, Copy)]
93
- enum OrderStatus {
94
- Pending,
95
- Processing,
96
- Completed,
97
- Cancelled,
98
- }
99
-
100
- impl FromStr for OrderStatus {
101
- type Err = ParseError;
102
-
103
- fn from_str(s: &str) -> Result<Self, Self::Err> {
104
- match s.to_lowercase().as_str() {
105
- "pending" => Ok(OrderStatus::Pending),
106
- "processing" => Ok(OrderStatus::Processing),
107
- "completed" => Ok(OrderStatus::Completed),
108
- "cancelled" | "canceled" => Ok(OrderStatus::Cancelled),
109
- _ => Err(ParseError::UnknownStatus(s.to_string())),
110
- }
111
- }
112
- }
113
-
114
- // Parse at boundary, use types internally
115
- fn handle_request(status_str: &str) -> Result<(), Error> {
116
- let status: OrderStatus = status_str.parse()?; // Validate once
117
- process_order(status); // Type-safe from here
118
- Ok(())
119
- }
120
- ```
121
-
122
- ## With Serde
123
-
124
- ```rust
125
- use serde::{Serialize, Deserialize};
126
-
127
- #[derive(Debug, Clone, Serialize, Deserialize)]
128
- #[serde(rename_all = "snake_case")]
129
- enum Status {
130
- Pending,
131
- InProgress,
132
- Completed,
133
- }
134
-
135
- // JSON: {"status": "in_progress"}
136
- // Deserialization validates automatically
137
- ```
138
-
139
- ## Error Messages
140
-
141
- ```rust
142
- #[derive(Debug, Clone, Copy)]
143
- enum Color {
144
- Red,
145
- Green,
146
- Blue,
147
- }
148
-
149
- impl std::fmt::Display for Color {
150
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
151
- match self {
152
- Color::Red => write!(f, "red"),
153
- Color::Green => write!(f, "green"),
154
- Color::Blue => write!(f, "blue"),
155
- }
156
- }
157
- }
158
-
159
- // Type-safe and displayable
160
- println!("Selected color: {}", Color::Red);
161
- ```
162
-
163
- ## See Also
164
-
165
- - [api-newtype-safety](./api-newtype-safety.md) - Newtype pattern
166
- - [api-parse-dont-validate](./api-parse-dont-validate.md) - Parse at boundaries
167
- - [type-newtype-ids](./type-newtype-ids.md) - Type-safe IDs
@@ -1,134 +0,0 @@
1
- # anti-type-erasure
2
-
3
- > Don't use Box<dyn Trait> when impl Trait works
4
-
5
- ## Why It Matters
6
-
7
- `Box<dyn Trait>` (type erasure) introduces heap allocation and dynamic dispatch overhead. When you have a single concrete type or can use generics, `impl Trait` provides the same flexibility with zero overhead through monomorphization.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Unnecessary type erasure
13
- fn get_iterator() -> Box<dyn Iterator<Item = i32>> {
14
- Box::new((0..10).map(|x| x * 2))
15
- }
16
-
17
- // Boxing for no reason
18
- fn make_handler() -> Box<dyn Fn(i32) -> i32> {
19
- Box::new(|x| x + 1)
20
- }
21
-
22
- // Vec of boxed trait objects when one type would do
23
- fn get_validators() -> Vec<Box<dyn Validator>> {
24
- vec![
25
- Box::new(LengthValidator),
26
- Box::new(RegexValidator),
27
- ]
28
- }
29
- ```
30
-
31
- ## Good
32
-
33
- ```rust
34
- // impl Trait - zero overhead, inlined
35
- fn get_iterator() -> impl Iterator<Item = i32> {
36
- (0..10).map(|x| x * 2)
37
- }
38
-
39
- // impl Fn - no boxing
40
- fn make_handler() -> impl Fn(i32) -> i32 {
41
- |x| x + 1
42
- }
43
-
44
- // When mixed types are genuinely needed, Box is OK
45
- fn get_validators() -> Vec<Box<dyn Validator>> {
46
- // Actually different types at runtime - Box is appropriate
47
- config.validators.iter()
48
- .map(|v| v.create_validator())
49
- .collect()
50
- }
51
- ```
52
-
53
- ## When to Use Box<dyn Trait>
54
-
55
- Type erasure IS appropriate when:
56
-
57
- ```rust
58
- // Heterogeneous collection of different types
59
- let handlers: Vec<Box<dyn Handler>> = vec![
60
- Box::new(LogHandler),
61
- Box::new(MetricsHandler),
62
- Box::new(AuthHandler),
63
- ];
64
-
65
- // Type cannot be known at compile time
66
- fn create_from_config(config: &Config) -> Box<dyn Database> {
67
- match config.db_type {
68
- DbType::Postgres => Box::new(PostgresDb::new()),
69
- DbType::Sqlite => Box::new(SqliteDb::new()),
70
- }
71
- }
72
-
73
- // Recursive types
74
- struct Node {
75
- value: i32,
76
- children: Vec<Box<dyn NodeTrait>>,
77
- }
78
-
79
- // Breaking cycles in complex ownership
80
- struct EventLoop {
81
- handlers: Vec<Box<dyn EventHandler>>,
82
- }
83
- ```
84
-
85
- ## Comparison
86
-
87
- | Approach | Allocation | Dispatch | Binary Size |
88
- |----------|------------|----------|-------------|
89
- | `impl Trait` | Stack/inline | Static | Larger (monomorphization) |
90
- | `Box<dyn Trait>` | Heap | Dynamic | Smaller |
91
- | Generics `<T>` | Stack/inline | Static | Larger |
92
-
93
- ## impl Trait Positions
94
-
95
- ```rust
96
- // Return position - caller doesn't need to know concrete type
97
- fn process() -> impl Future<Output = Result> { }
98
-
99
- // Argument position - like generics but simpler
100
- fn handle(handler: impl Handler) { }
101
-
102
- // Can't use in trait definitions (use associated types instead)
103
- trait Processor {
104
- type Output: Display; // Not impl Display
105
- fn process(&self) -> Self::Output;
106
- }
107
- ```
108
-
109
- ## Pattern: Enum Instead of dyn
110
-
111
- ```rust
112
- // Instead of Box<dyn Shape>
113
- enum Shape {
114
- Circle { radius: f64 },
115
- Rectangle { width: f64, height: f64 },
116
- Triangle { base: f64, height: f64 },
117
- }
118
-
119
- impl Shape {
120
- fn area(&self) -> f64 {
121
- match self {
122
- Shape::Circle { radius } => PI * radius * radius,
123
- Shape::Rectangle { width, height } => width * height,
124
- Shape::Triangle { base, height } => 0.5 * base * height,
125
- }
126
- }
127
- }
128
- ```
129
-
130
- ## See Also
131
-
132
- - [anti-over-abstraction](./anti-over-abstraction.md) - Excessive generics
133
- - [type-generic-bounds](./type-generic-bounds.md) - Generic constraints
134
- - [mem-box-large-variant](./mem-box-large-variant.md) - Boxing enum variants
@@ -1,143 +0,0 @@
1
- # anti-unwrap-abuse
2
-
3
- > Don't use `.unwrap()` in production code
4
-
5
- ## Why It Matters
6
-
7
- `.unwrap()` panics on `None` or `Err`, crashing your program. In production, this means lost data, failed requests, and unhappy users. It also makes debugging harder since panic messages often lack context.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Crashes if file doesn't exist
13
- let content = std::fs::read_to_string("config.toml").unwrap();
14
-
15
- // Crashes on invalid input
16
- let num: i32 = user_input.parse().unwrap();
17
-
18
- // Crashes if key missing
19
- let value = map.get("key").unwrap();
20
-
21
- // Crashes if channel closed
22
- let msg = receiver.recv().unwrap();
23
- ```
24
-
25
- ## Good
26
-
27
- ```rust
28
- // Propagate with ?
29
- fn load_config() -> Result<Config, Error> {
30
- let content = std::fs::read_to_string("config.toml")?;
31
- Ok(toml::from_str(&content)?)
32
- }
33
-
34
- // Provide default
35
- let num: i32 = user_input.parse().unwrap_or(0);
36
-
37
- // Handle missing key
38
- let value = map.get("key").ok_or(Error::MissingKey)?;
39
-
40
- // Or use if-let
41
- if let Some(value) = map.get("key") {
42
- process(value);
43
- }
44
-
45
- // Channel with proper handling
46
- match receiver.recv() {
47
- Ok(msg) => handle(msg),
48
- Err(_) => break, // Channel closed
49
- }
50
- ```
51
-
52
- ## When unwrap() Is Acceptable
53
-
54
- ```rust
55
- // 1. Tests - panics are expected failures
56
- #[test]
57
- fn test_parse() {
58
- let result = parse("valid").unwrap(); // OK in tests
59
- assert_eq!(result, expected);
60
- }
61
-
62
- // 2. Const/static initialization (compile-time guaranteed)
63
- static REGEX: Lazy<Regex> = Lazy::new(|| {
64
- Regex::new(r"^\d+$").unwrap() // Known-valid pattern
65
- });
66
-
67
- // 3. After a check that guarantees success
68
- if map.contains_key("key") {
69
- let value = map.get("key").unwrap(); // Just checked
70
- }
71
- // Better: use if-let or entry API instead
72
-
73
- // 4. Truly impossible cases with proof comment
74
- let last = vec.pop().unwrap();
75
- // OK only if you just checked !vec.is_empty()
76
- // Better: use last() or pattern match
77
- ```
78
-
79
- ## Alternatives to unwrap()
80
-
81
- ```rust
82
- // unwrap_or - provide default
83
- let x = opt.unwrap_or(default);
84
-
85
- // unwrap_or_default - use Default trait
86
- let x = opt.unwrap_or_default();
87
-
88
- // unwrap_or_else - compute default lazily
89
- let x = opt.unwrap_or_else(|| expensive_default());
90
-
91
- // ? operator - propagate errors
92
- let x = opt.ok_or(Error::Missing)?;
93
-
94
- // if let - handle Some/Ok case
95
- if let Some(x) = opt {
96
- use_x(x);
97
- }
98
-
99
- // match - handle all cases
100
- match opt {
101
- Some(x) => use_x(x),
102
- None => handle_none(),
103
- }
104
-
105
- // map - transform if present
106
- let y = opt.map(|x| x + 1);
107
-
108
- // and_then - chain fallible operations
109
- let z = opt.and_then(|x| x.checked_add(1));
110
- ```
111
-
112
- ## expect() Is Slightly Better
113
-
114
- ```rust
115
- // unwrap() - no context
116
- let file = File::open(path).unwrap();
117
- // Panics with: "called `Result::unwrap()` on an `Err` value: Os { code: 2, ... }"
118
-
119
- // expect() - adds context
120
- let file = File::open(path)
121
- .expect("config file should exist at startup");
122
- // Panics with: "config file should exist at startup: Os { code: 2, ... }"
123
-
124
- // But still use only for invariants, not error handling
125
- ```
126
-
127
- ## Clippy Lint
128
-
129
- ```rust
130
- // Enable these lints to catch unwrap usage:
131
- #![warn(clippy::unwrap_used)]
132
- #![warn(clippy::expect_used)] // Stricter
133
-
134
- // Or per-function:
135
- #[allow(clippy::unwrap_used)]
136
- fn tests_only() { }
137
- ```
138
-
139
- ## See Also
140
-
141
- - [err-question-mark](err-question-mark.md) - Use ? for propagation
142
- - [err-result-over-panic](err-result-over-panic.md) - Return Result instead of panicking
143
- - [anti-expect-lazy](anti-expect-lazy.md) - Don't use expect for recoverable errors
@@ -1,121 +0,0 @@
1
- # anti-vec-for-slice
2
-
3
- > Don't accept &Vec<T> when &[T] works
4
-
5
- ## Why It Matters
6
-
7
- `&Vec<T>` is strictly less flexible than `&[T]`. A slice can be created from `Vec`, arrays, and other slice-like types. Accepting `&Vec<T>` forces callers to have exactly a `Vec`, preventing them from using arrays, slices, or other collections.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Forces callers to have a Vec
13
- fn sum(numbers: &Vec<i32>) -> i32 {
14
- numbers.iter().sum()
15
- }
16
-
17
- // Caller must allocate
18
- let arr = [1, 2, 3, 4, 5];
19
- sum(&arr.to_vec()); // Unnecessary allocation
20
-
21
- // Slice won't work
22
- let slice: &[i32] = &[1, 2, 3];
23
- // sum(slice); // Error: expected &Vec<i32>
24
- ```
25
-
26
- ## Good
27
-
28
- ```rust
29
- // Accept slice - works with Vec, arrays, slices
30
- fn sum(numbers: &[i32]) -> i32 {
31
- numbers.iter().sum()
32
- }
33
-
34
- // All these work
35
- sum(&[1, 2, 3, 4, 5]); // Array
36
- sum(&vec![1, 2, 3]); // Vec
37
- sum(&numbers[1..3]); // Slice of slice
38
- sum(numbers.as_slice()); // Explicit slice
39
- ```
40
-
41
- ## Deref Coercion
42
-
43
- `Vec<T>` implements `Deref<Target = [T]>`, so `&Vec<T>` automatically coerces to `&[T]`:
44
-
45
- ```rust
46
- fn takes_slice(s: &[i32]) { }
47
-
48
- let vec = vec![1, 2, 3];
49
- takes_slice(&vec); // &Vec<i32> -> &[i32] via Deref
50
- ```
51
-
52
- ## Mutable Slices
53
-
54
- Same applies to `&mut`:
55
-
56
- ```rust
57
- // Bad
58
- fn double(numbers: &mut Vec<i32>) {
59
- for n in numbers.iter_mut() {
60
- *n *= 2;
61
- }
62
- }
63
-
64
- // Good
65
- fn double(numbers: &mut [i32]) {
66
- for n in numbers.iter_mut() {
67
- *n *= 2;
68
- }
69
- }
70
- ```
71
-
72
- ## When to Accept &Vec<T>
73
-
74
- Rarely. Only when you need Vec-specific operations:
75
-
76
- ```rust
77
- fn needs_capacity(v: &Vec<i32>) -> usize {
78
- v.capacity() // Only Vec has capacity
79
- }
80
-
81
- fn might_grow(v: &mut Vec<i32>) {
82
- v.push(42); // Slice can't push
83
- }
84
- ```
85
-
86
- ## Pattern: Accepting Multiple Types
87
-
88
- ```rust
89
- // Accept anything that can be viewed as a slice
90
- fn process<T: AsRef<[u8]>>(data: T) {
91
- let bytes: &[u8] = data.as_ref();
92
- // ...
93
- }
94
-
95
- process(&[1u8, 2, 3]); // Array
96
- process(vec![1u8, 2, 3]); // Vec
97
- process(&some_vec); // &Vec
98
- process(b"bytes"); // Byte string
99
- ```
100
-
101
- ## Similar Anti-patterns
102
-
103
- | Anti-pattern | Better |
104
- |--------------|--------|
105
- | `&Vec<T>` | `&[T]` |
106
- | `&String` | `&str` |
107
- | `&PathBuf` | `&Path` |
108
- | `&Box<T>` | `&T` |
109
-
110
- ## Clippy Detection
111
-
112
- ```toml
113
- [lints.clippy]
114
- ptr_arg = "warn" # Catches &Vec, &String, &PathBuf
115
- ```
116
-
117
- ## See Also
118
-
119
- - [anti-string-for-str](./anti-string-for-str.md) - Similar for String
120
- - [own-slice-over-vec](./own-slice-over-vec.md) - Slice patterns
121
- - [api-impl-asref](./api-impl-asref.md) - AsRef pattern
@@ -1,143 +0,0 @@
1
- # api-builder-must-use
2
-
3
- > Mark builder methods with `#[must_use]` to prevent silent drops
4
-
5
- ## Why It Matters
6
-
7
- Builder pattern methods return a modified builder. Without `#[must_use]`, calling a builder method and ignoring the return value silently does nothing—the builder is dropped, and the configuration is lost. This creates confusing bugs where code appears correct but has no effect.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- struct RequestBuilder {
13
- url: String,
14
- timeout: Option<Duration>,
15
- headers: Vec<(String, String)>,
16
- }
17
-
18
- impl RequestBuilder {
19
- fn timeout(mut self, duration: Duration) -> Self {
20
- self.timeout = Some(duration);
21
- self
22
- }
23
-
24
- fn header(mut self, key: &str, value: &str) -> Self {
25
- self.headers.push((key.to_string(), value.to_string()));
26
- self
27
- }
28
- }
29
-
30
- // Bug: builder methods are ignored - no warning!
31
- let request = RequestBuilder::new("https://api.example.com");
32
- request.timeout(Duration::from_secs(30)); // Dropped silently!
33
- request.header("Authorization", "Bearer token"); // Dropped silently!
34
- let response = request.send(); // Sends with no timeout or headers
35
- ```
36
-
37
- ## Good
38
-
39
- ```rust
40
- struct RequestBuilder {
41
- url: String,
42
- timeout: Option<Duration>,
43
- headers: Vec<(String, String)>,
44
- }
45
-
46
- impl RequestBuilder {
47
- #[must_use = "builder methods return modified builder - chain or assign"]
48
- fn timeout(mut self, duration: Duration) -> Self {
49
- self.timeout = Some(duration);
50
- self
51
- }
52
-
53
- #[must_use = "builder methods return modified builder - chain or assign"]
54
- fn header(mut self, key: &str, value: &str) -> Self {
55
- self.headers.push((key.to_string(), value.to_string()));
56
- self
57
- }
58
- }
59
-
60
- // Now warns: unused return value that must be used
61
- let request = RequestBuilder::new("https://api.example.com");
62
- request.timeout(Duration::from_secs(30)); // Warning!
63
-
64
- // Correct: chain methods
65
- let response = RequestBuilder::new("https://api.example.com")
66
- .timeout(Duration::from_secs(30))
67
- .header("Authorization", "Bearer token")
68
- .send();
69
- ```
70
-
71
- ## Apply to Entire Type
72
-
73
- ```rust
74
- #[must_use = "builders do nothing unless consumed"]
75
- struct ConfigBuilder {
76
- log_level: Level,
77
- max_connections: usize,
78
- }
79
-
80
- // Now all methods returning Self warn if ignored
81
- impl ConfigBuilder {
82
- fn log_level(mut self, level: Level) -> Self {
83
- self.log_level = level;
84
- self
85
- }
86
-
87
- fn max_connections(mut self, n: usize) -> Self {
88
- self.max_connections = n;
89
- self
90
- }
91
-
92
- fn build(self) -> Config {
93
- Config {
94
- log_level: self.log_level,
95
- max_connections: self.max_connections,
96
- }
97
- }
98
- }
99
- ```
100
-
101
- ## Message Guidelines
102
-
103
- ```rust
104
- // Descriptive message helps users understand
105
- #[must_use = "builder methods return modified builder"]
106
- fn with_foo(self, foo: Foo) -> Self { ... }
107
-
108
- #[must_use = "this creates a new String and does not modify the original"]
109
- fn to_uppercase(&self) -> String { ... }
110
-
111
- #[must_use = "iterator adaptors are lazy - use .collect() to consume"]
112
- fn map<F>(self, f: F) -> Map<Self, F> { ... }
113
- ```
114
-
115
- ## Clippy Lint
116
-
117
- ```toml
118
- [lints.clippy]
119
- must_use_candidate = "warn" # Suggests where #[must_use] would help
120
- return_self_not_must_use = "warn" # Specifically for -> Self methods
121
- ```
122
-
123
- ## Standard Library Examples
124
-
125
- ```rust
126
- // std::Option - must_use on map, and, or
127
- let x: Option<i32> = Some(5);
128
- x.map(|v| v * 2); // Warning: unused return value
129
-
130
- // std::Result - must_use on the type itself
131
- #[must_use = "this `Result` may be an `Err` variant, which should be handled"]
132
- pub enum Result<T, E> { ... }
133
-
134
- // Iterator adaptors
135
- let v = vec![1, 2, 3];
136
- v.iter().map(|x| x * 2); // Warning: iterators are lazy
137
- ```
138
-
139
- ## See Also
140
-
141
- - [api-builder-pattern](./api-builder-pattern.md) - Builder pattern best practices
142
- - [api-must-use](./api-must-use.md) - General must_use guidelines
143
- - [err-result-over-panic](./err-result-over-panic.md) - Result types are must_use