agy-superpowers 5.2.2 → 5.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/README.md +47 -150
  2. package/package.json +1 -1
  3. package/template/agent/rules/scratch-scripts.md +37 -0
  4. package/template/agent/rules/superpowers.md +4 -51
  5. package/template/agent/skills/ai-integrated-product/SKILL.md +0 -57
  6. package/template/agent/skills/analytics-setup/SKILL.md +0 -51
  7. package/template/agent/skills/api-design/SKILL.md +0 -193
  8. package/template/agent/skills/app-store-optimizer/SKILL.md +0 -127
  9. package/template/agent/skills/auth-and-identity/SKILL.md +0 -167
  10. package/template/agent/skills/backend-developer/SKILL.md +0 -148
  11. package/template/agent/skills/bootstrapper-finance/SKILL.md +0 -55
  12. package/template/agent/skills/chrome-extension-developer/SKILL.md +0 -53
  13. package/template/agent/skills/community-manager/SKILL.md +0 -115
  14. package/template/agent/skills/content-marketer/SKILL.md +0 -111
  15. package/template/agent/skills/conversion-optimizer/SKILL.md +0 -142
  16. package/template/agent/skills/cto-architect/SKILL.md +0 -133
  17. package/template/agent/skills/customer-success-manager/SKILL.md +0 -126
  18. package/template/agent/skills/data-analyst/SKILL.md +0 -147
  19. package/template/agent/skills/devops-engineer/SKILL.md +0 -117
  20. package/template/agent/skills/email-infrastructure/SKILL.md +0 -164
  21. package/template/agent/skills/game-design/SKILL.md +0 -194
  22. package/template/agent/skills/game-developer/SKILL.md +0 -175
  23. package/template/agent/skills/growth-hacker/SKILL.md +0 -122
  24. package/template/agent/skills/idea-validator/SKILL.md +0 -55
  25. package/template/agent/skills/indie-legal/SKILL.md +0 -53
  26. package/template/agent/skills/influencer-marketer/SKILL.md +0 -141
  27. package/template/agent/skills/landing-page-builder/SKILL.md +0 -59
  28. package/template/agent/skills/launch-strategist/SKILL.md +0 -62
  29. package/template/agent/skills/market-researcher/SKILL.md +0 -53
  30. package/template/agent/skills/micro-saas-builder/SKILL.md +0 -56
  31. package/template/agent/skills/monetization-strategist/SKILL.md +0 -119
  32. package/template/agent/skills/paid-acquisition-specialist/SKILL.md +0 -119
  33. package/template/agent/skills/pricing-psychologist/SKILL.md +0 -58
  34. package/template/agent/skills/real-time-features/SKILL.md +0 -194
  35. package/template/agent/skills/retention-specialist/SKILL.md +0 -123
  36. package/template/agent/skills/rust-developer/SKILL.md +0 -281
  37. package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +0 -231
  38. package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +0 -124
  39. package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +0 -131
  40. package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +0 -132
  41. package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +0 -95
  42. package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +0 -141
  43. package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +0 -125
  44. package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +0 -127
  45. package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +0 -120
  46. package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +0 -131
  47. package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +0 -156
  48. package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +0 -122
  49. package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +0 -167
  50. package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +0 -134
  51. package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +0 -143
  52. package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +0 -121
  53. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +0 -143
  54. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +0 -187
  55. package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +0 -165
  56. package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +0 -177
  57. package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +0 -163
  58. package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +0 -146
  59. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +0 -142
  60. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +0 -160
  61. package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +0 -125
  62. package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +0 -162
  63. package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +0 -177
  64. package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +0 -184
  65. package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +0 -168
  66. package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +0 -182
  67. package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +0 -199
  68. package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +0 -175
  69. package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +0 -185
  70. package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +0 -203
  71. package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +0 -171
  72. package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +0 -158
  73. package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +0 -195
  74. package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +0 -171
  75. package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +0 -156
  76. package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +0 -191
  77. package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +0 -198
  78. package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +0 -154
  79. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +0 -167
  80. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +0 -169
  81. package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +0 -172
  82. package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +0 -189
  83. package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +0 -113
  84. package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +0 -147
  85. package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +0 -122
  86. package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +0 -161
  87. package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +0 -149
  88. package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +0 -138
  89. package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +0 -169
  90. package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +0 -116
  91. package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +0 -128
  92. package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +0 -136
  93. package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +0 -131
  94. package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +0 -179
  95. package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +0 -144
  96. package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +0 -152
  97. package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +0 -145
  98. package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +0 -133
  99. package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +0 -152
  100. package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +0 -124
  101. package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +0 -115
  102. package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +0 -151
  103. package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +0 -130
  104. package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +0 -155
  105. package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +0 -171
  106. package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +0 -138
  107. package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +0 -107
  108. package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +0 -154
  109. package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +0 -118
  110. package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +0 -157
  111. package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +0 -133
  112. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +0 -131
  113. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +0 -136
  114. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +0 -135
  115. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +0 -122
  116. package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +0 -172
  117. package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +0 -168
  118. package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +0 -142
  119. package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +0 -168
  120. package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +0 -147
  121. package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +0 -158
  122. package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +0 -139
  123. package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +0 -147
  124. package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +0 -149
  125. package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +0 -174
  126. package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +0 -159
  127. package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +0 -138
  128. package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +0 -142
  129. package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +0 -156
  130. package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +0 -172
  131. package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +0 -164
  132. package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +0 -99
  133. package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +0 -104
  134. package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +0 -94
  135. package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +0 -78
  136. package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +0 -76
  137. package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +0 -123
  138. package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +0 -127
  139. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +0 -129
  140. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +0 -131
  141. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +0 -142
  142. package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +0 -86
  143. package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +0 -154
  144. package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +0 -118
  145. package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +0 -92
  146. package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +0 -65
  147. package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +0 -101
  148. package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +0 -161
  149. package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +0 -187
  150. package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +0 -142
  151. package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +0 -152
  152. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +0 -141
  153. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +0 -181
  154. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +0 -160
  155. package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +0 -171
  156. package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +0 -130
  157. package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +0 -167
  158. package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +0 -144
  159. package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +0 -154
  160. package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +0 -141
  161. package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +0 -95
  162. package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +0 -135
  163. package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +0 -124
  164. package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +0 -135
  165. package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +0 -134
  166. package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +0 -134
  167. package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +0 -105
  168. package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +0 -65
  169. package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +0 -97
  170. package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +0 -122
  171. package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +0 -119
  172. package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +0 -153
  173. package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +0 -136
  174. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +0 -133
  175. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +0 -120
  176. package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +0 -137
  177. package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +0 -134
  178. package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +0 -150
  179. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +0 -123
  180. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +0 -113
  181. package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +0 -175
  182. package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +0 -149
  183. package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +0 -142
  184. package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +0 -133
  185. package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +0 -148
  186. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +0 -130
  187. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +0 -120
  188. package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +0 -155
  189. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +0 -139
  190. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +0 -135
  191. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +0 -162
  192. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +0 -186
  193. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +0 -162
  194. package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +0 -160
  195. package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +0 -151
  196. package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +0 -171
  197. package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +0 -142
  198. package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +0 -168
  199. package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +0 -151
  200. package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +0 -144
  201. package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +0 -189
  202. package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +0 -226
  203. package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +0 -161
  204. package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +0 -130
  205. package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +0 -154
  206. package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +0 -127
  207. package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +0 -154
  208. package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +0 -142
  209. package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +0 -146
  210. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +0 -160
  211. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +0 -159
  212. package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +0 -144
  213. package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +0 -137
  214. package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +0 -188
  215. package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +0 -143
  216. package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +0 -131
  217. package/template/agent/skills/saas-architect/SKILL.md +0 -139
  218. package/template/agent/skills/security-engineer/SKILL.md +0 -133
  219. package/template/agent/skills/seo-specialist/SKILL.md +0 -130
  220. package/template/agent/skills/solo-founder-ops/SKILL.md +0 -56
@@ -1,146 +0,0 @@
1
- # type-never-diverge
2
-
3
- > Use `!` (never type) for functions that never return
4
-
5
- ## Why It Matters
6
-
7
- The never type `!` indicates a function will never return normally—it either loops forever, panics, or exits the process. This helps the compiler understand control flow and enables `!` to coerce to any type, making it useful in match arms and expressions.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Return type doesn't indicate non-returning
13
- fn infinite_loop() {
14
- loop {
15
- process_events();
16
- }
17
- // Implicit () return type, but never returns
18
- }
19
-
20
- // Using Option when it always panics
21
- fn unreachable_code() -> Option<()> {
22
- panic!("This should never be called");
23
- }
24
- ```
25
-
26
- ## Good
27
-
28
- ```rust
29
- // ! indicates function never returns
30
- fn infinite_loop() -> ! {
31
- loop {
32
- process_events();
33
- }
34
- }
35
-
36
- fn abort_with_error(msg: &str) -> ! {
37
- eprintln!("Fatal error: {}", msg);
38
- std::process::exit(1);
39
- }
40
-
41
- fn panic_handler() -> ! {
42
- panic!("Unexpected state");
43
- }
44
- ```
45
-
46
- ## Coercion to Any Type
47
-
48
- ```rust
49
- // ! coerces to any type
50
- fn get_value(opt: Option<i32>) -> i32 {
51
- match opt {
52
- Some(v) => v,
53
- None => panic!("No value"), // panic! returns !, coerces to i32
54
- }
55
- }
56
-
57
- // Useful in Result handling
58
- fn must_get_config() -> Config {
59
- match load_config() {
60
- Ok(c) => c,
61
- Err(e) => {
62
- log_error(&e);
63
- std::process::exit(1) // Returns !, coerces to Config
64
- }
65
- }
66
- }
67
- ```
68
-
69
- ## Standard Library Examples
70
-
71
- ```rust
72
- // std::process::exit
73
- pub fn exit(code: i32) -> !
74
-
75
- // panic! macro
76
- // Expands to an expression of type !
77
-
78
- // std::hint::unreachable_unchecked
79
- pub unsafe fn unreachable_unchecked() -> !
80
-
81
- // loop {} with no break
82
- fn forever() -> ! {
83
- loop {}
84
- }
85
- ```
86
-
87
- ## In Match Expressions
88
-
89
- ```rust
90
- enum State {
91
- Running,
92
- Stopped,
93
- Error,
94
- }
95
-
96
- fn get_status(state: &State) -> &str {
97
- match state {
98
- State::Running => "running",
99
- State::Stopped => "stopped",
100
- State::Error => unreachable!(), // ! coerces to &str
101
- }
102
- }
103
-
104
- // With Result
105
- fn process(r: Result<Data, Error>) -> Data {
106
- match r {
107
- Ok(d) => d,
108
- Err(e) => panic!("Unexpected error: {}", e), // ! coerces to Data
109
- }
110
- }
111
- ```
112
-
113
- ## Diverging Closures
114
-
115
- ```rust
116
- // Closures that never return
117
- let handler: fn() -> ! = || {
118
- panic!("Handler called");
119
- };
120
-
121
- // In thread spawn
122
- std::thread::spawn(|| -> ! {
123
- loop {
124
- process_work();
125
- }
126
- });
127
- ```
128
-
129
- ## Current Limitations (Nightly)
130
-
131
- ```rust
132
- // Full ! type is nightly
133
- #![feature(never_type)]
134
-
135
- // Can use ! as type parameter
136
- type NeverResult = Result<(), !>; // Can never be Err
137
-
138
- // On stable, use std::convert::Infallible
139
- type StableNeverResult = Result<(), std::convert::Infallible>;
140
- ```
141
-
142
- ## See Also
143
-
144
- - [err-result-over-panic](./err-result-over-panic.md) - When to panic vs return Result
145
- - [type-result-fallible](./type-result-fallible.md) - Result for errors
146
- - [opt-cold-unlikely](./opt-cold-unlikely.md) - Marking unlikely paths
@@ -1,160 +0,0 @@
1
- # type-newtype-ids
2
-
3
- > Wrap IDs in newtypes: `UserId(u64)`
4
-
5
- ## Why It Matters
6
-
7
- Using raw integers for IDs is error-prone. It's easy to accidentally pass a `user_id` where a `post_id` is expected. Newtypes make these mix-ups compile-time errors instead of runtime bugs.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- fn get_user_posts(user_id: u64, post_id: u64) -> Vec<Post> {
13
- // Which is which? Easy to swap by accident
14
- }
15
-
16
- // Oops! Arguments swapped - compiles fine, wrong at runtime
17
- let posts = get_user_posts(post_id, user_id);
18
-
19
- // Even worse with multiple IDs
20
- fn transfer(from: u64, to: u64, amount: u64) {
21
- // from/to can easily be swapped
22
- }
23
- ```
24
-
25
- ## Good
26
-
27
- ```rust
28
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
29
- pub struct UserId(pub u64);
30
-
31
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
32
- pub struct PostId(pub u64);
33
-
34
- fn get_user_posts(user_id: UserId, post_id: PostId) -> Vec<Post> {
35
- // Types are distinct
36
- }
37
-
38
- // This won't compile - types don't match
39
- // let posts = get_user_posts(post_id, user_id); // ERROR!
40
-
41
- // Correct usage
42
- let posts = get_user_posts(UserId(1), PostId(42));
43
- ```
44
-
45
- ## Derive Common Traits
46
-
47
- ```rust
48
- #[derive(
49
- Debug, // For printing
50
- Clone, // For copying
51
- Copy, // For implicit copies (if small)
52
- PartialEq, // For == comparison
53
- Eq, // For HashMap keys
54
- Hash, // For HashMap keys
55
- PartialOrd, // For sorting (optional)
56
- Ord, // For BTreeMap keys (optional)
57
- )]
58
- pub struct UserId(pub u64);
59
- ```
60
-
61
- ## Add Useful Methods
62
-
63
- ```rust
64
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
65
- pub struct UserId(u64);
66
-
67
- impl UserId {
68
- pub const fn new(id: u64) -> Self {
69
- Self(id)
70
- }
71
-
72
- pub const fn get(self) -> u64 {
73
- self.0
74
- }
75
-
76
- // For database queries
77
- pub fn as_i64(self) -> i64 {
78
- self.0 as i64
79
- }
80
- }
81
-
82
- impl From<u64> for UserId {
83
- fn from(id: u64) -> Self {
84
- Self(id)
85
- }
86
- }
87
-
88
- impl std::fmt::Display for UserId {
89
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90
- write!(f, "user:{}", self.0)
91
- }
92
- }
93
- ```
94
-
95
- ## With Serde
96
-
97
- ```rust
98
- use serde::{Deserialize, Serialize};
99
-
100
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
101
- #[serde(transparent)] // Serializes as just the inner value
102
- pub struct UserId(pub u64);
103
-
104
- // JSON: {"user_id": 123} not {"user_id": {"0": 123}}
105
- ```
106
-
107
- ## String IDs (UUIDs, etc.)
108
-
109
- ```rust
110
- #[derive(Debug, Clone, PartialEq, Eq, Hash)]
111
- pub struct SessionId(String);
112
-
113
- impl SessionId {
114
- pub fn new() -> Self {
115
- Self(uuid::Uuid::new_v4().to_string())
116
- }
117
-
118
- pub fn parse(s: &str) -> Result<Self, ParseError> {
119
- // Validate format
120
- uuid::Uuid::parse_str(s)?;
121
- Ok(Self(s.to_string()))
122
- }
123
-
124
- pub fn as_str(&self) -> &str {
125
- &self.0
126
- }
127
- }
128
- ```
129
-
130
- ## Multiple Related IDs
131
-
132
- ```rust
133
- // Macro for consistent ID types
134
- macro_rules! define_id {
135
- ($name:ident) => {
136
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
137
- pub struct $name(pub u64);
138
-
139
- impl $name {
140
- pub const fn new(id: u64) -> Self { Self(id) }
141
- pub const fn get(self) -> u64 { self.0 }
142
- }
143
-
144
- impl From<u64> for $name {
145
- fn from(id: u64) -> Self { Self(id) }
146
- }
147
- };
148
- }
149
-
150
- define_id!(UserId);
151
- define_id!(PostId);
152
- define_id!(CommentId);
153
- define_id!(TeamId);
154
- ```
155
-
156
- ## See Also
157
-
158
- - [api-newtype-safety](api-newtype-safety.md) - Newtypes for type safety
159
- - [type-newtype-validated](type-newtype-validated.md) - Newtypes for validated data
160
- - [api-parse-dont-validate](api-parse-dont-validate.md) - Parse into validated types
@@ -1,159 +0,0 @@
1
- # type-newtype-validated
2
-
3
- > Use newtypes to enforce validation at construction time
4
-
5
- ## Why It Matters
6
-
7
- A validated newtype guarantees its inner value is always valid. Once you have an `Email`, you know it passed validation—no re-checking needed. This "parse, don't validate" pattern catches errors at boundaries and makes invalid states unrepresentable.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Validation scattered throughout code
13
- fn send_email(to: &str, body: &str) -> Result<(), Error> {
14
- if !is_valid_email(to) { // Must check every time
15
- return Err(Error::InvalidEmail);
16
- }
17
- // ...
18
- }
19
-
20
- fn add_recipient(list: &mut Vec<String>, email: &str) -> Result<(), Error> {
21
- if !is_valid_email(email) { // Check again
22
- return Err(Error::InvalidEmail);
23
- }
24
- list.push(email.to_string());
25
- Ok(())
26
- }
27
- ```
28
-
29
- ## Good
30
-
31
- ```rust
32
- #[derive(Debug, Clone, PartialEq, Eq, Hash)]
33
- pub struct Email(String);
34
-
35
- impl Email {
36
- pub fn new(s: &str) -> Result<Self, EmailError> {
37
- if is_valid_email(s) {
38
- Ok(Email(s.to_string()))
39
- } else {
40
- Err(EmailError::Invalid(s.to_string()))
41
- }
42
- }
43
-
44
- pub fn as_str(&self) -> &str {
45
- &self.0
46
- }
47
- }
48
-
49
- // No validation needed - Email is always valid
50
- fn send_email(to: &Email, body: &str) -> Result<(), Error> {
51
- // to is guaranteed valid
52
- send_to_address(to.as_str(), body)
53
- }
54
-
55
- fn add_recipient(list: &mut Vec<Email>, email: Email) {
56
- // email is guaranteed valid
57
- list.push(email);
58
- }
59
- ```
60
-
61
- ## Common Validated Types
62
-
63
- ```rust
64
- // URLs
65
- pub struct Url(url::Url);
66
-
67
- impl Url {
68
- pub fn parse(s: &str) -> Result<Self, UrlError> {
69
- url::Url::parse(s)
70
- .map(Url)
71
- .map_err(UrlError::from)
72
- }
73
- }
74
-
75
- // Non-empty strings
76
- pub struct NonEmptyString(String);
77
-
78
- impl NonEmptyString {
79
- pub fn new(s: String) -> Option<Self> {
80
- if s.is_empty() {
81
- None
82
- } else {
83
- Some(NonEmptyString(s))
84
- }
85
- }
86
- }
87
-
88
- // Positive numbers
89
- pub struct PositiveI32(i32);
90
-
91
- impl PositiveI32 {
92
- pub fn new(n: i32) -> Option<Self> {
93
- if n > 0 {
94
- Some(PositiveI32(n))
95
- } else {
96
- None
97
- }
98
- }
99
-
100
- pub fn get(&self) -> i32 {
101
- self.0
102
- }
103
- }
104
-
105
- // Bounded ranges
106
- pub struct Percentage(f64);
107
-
108
- impl Percentage {
109
- pub fn new(value: f64) -> Result<Self, RangeError> {
110
- if (0.0..=100.0).contains(&value) {
111
- Ok(Percentage(value))
112
- } else {
113
- Err(RangeError::OutOfBounds)
114
- }
115
- }
116
- }
117
- ```
118
-
119
- ## With Serde
120
-
121
- ```rust
122
- use serde::{Deserialize, Serialize};
123
-
124
- #[derive(Debug, Clone, Serialize)]
125
- pub struct Email(String);
126
-
127
- impl<'de> Deserialize<'de> for Email {
128
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
129
- where
130
- D: serde::Deserializer<'de>,
131
- {
132
- let s = String::deserialize(deserializer)?;
133
- Email::new(&s).map_err(serde::de::Error::custom)
134
- }
135
- }
136
-
137
- // JSON deserialization automatically validates
138
- let email: Email = serde_json::from_str(r#""user@example.com""#)?;
139
- ```
140
-
141
- ## Compile-Time Validation
142
-
143
- ```rust
144
- // For values known at compile time
145
- macro_rules! email {
146
- ($s:literal) => {{
147
- const _: () = assert!(is_valid_email_const($s));
148
- Email::new_unchecked($s)
149
- }};
150
- }
151
-
152
- let admin = email!("admin@example.com"); // Validated at compile time
153
- ```
154
-
155
- ## See Also
156
-
157
- - [api-parse-dont-validate](./api-parse-dont-validate.md) - Parse at boundaries
158
- - [api-newtype-safety](./api-newtype-safety.md) - Type-safe distinctions
159
- - [type-newtype-ids](./type-newtype-ids.md) - ID newtypes
@@ -1,144 +0,0 @@
1
- # type-no-stringly
2
-
3
- > Avoid stringly-typed APIs; use enums, newtypes, or validated types
4
-
5
- ## Why It Matters
6
-
7
- Strings accept any value—typos, wrong formats, invalid data all compile fine. Enums, newtypes, and validated types catch errors at compile time or construction time, not runtime. They also provide better IDE support, documentation, and make invalid states unrepresentable.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Status as string - easy to get wrong
13
- fn set_status(status: &str) {
14
- match status {
15
- "pending" => { ... }
16
- "active" => { ... }
17
- "completed" => { ... }
18
- _ => panic!("Unknown status"), // Runtime error
19
- }
20
- }
21
-
22
- // Easy to misuse
23
- set_status("pending"); // OK
24
- set_status("Pending"); // Runtime error - wrong case
25
- set_status("aktive"); // Runtime error - typo
26
- set_status("done"); // Runtime error - wrong word
27
-
28
- // Configuration as strings
29
- fn configure(key: &str, value: &str) {
30
- // No type safety, no validation
31
- }
32
- ```
33
-
34
- ## Good
35
-
36
- ```rust
37
- // Status as enum - compile-time safety
38
- enum Status {
39
- Pending,
40
- Active,
41
- Completed,
42
- }
43
-
44
- fn set_status(status: Status) {
45
- match status {
46
- Status::Pending => { ... }
47
- Status::Active => { ... }
48
- Status::Completed => { ... }
49
- } // Exhaustive - compiler checks all cases
50
- }
51
-
52
- // Can only pass valid values
53
- set_status(Status::Pending); // OK
54
- set_status(Status::Aktivev); // Compile error - typo caught!
55
-
56
- // Configuration with typed builder
57
- struct Config {
58
- timeout: Duration,
59
- retries: u32,
60
- mode: Mode,
61
- }
62
-
63
- enum Mode { Fast, Safe, Balanced }
64
- ```
65
-
66
- ## Parsing at Boundaries
67
-
68
- ```rust
69
- use std::str::FromStr;
70
-
71
- #[derive(Debug, Clone, Copy)]
72
- enum Priority {
73
- Low,
74
- Medium,
75
- High,
76
- }
77
-
78
- impl FromStr for Priority {
79
- type Err = ParseError;
80
-
81
- fn from_str(s: &str) -> Result<Self, Self::Err> {
82
- match s.to_lowercase().as_str() {
83
- "low" => Ok(Priority::Low),
84
- "medium" | "med" => Ok(Priority::Medium),
85
- "high" => Ok(Priority::High),
86
- _ => Err(ParseError::UnknownPriority(s.to_string())),
87
- }
88
- }
89
- }
90
-
91
- // Parse once at boundary
92
- fn handle_request(priority_str: &str) -> Result<(), Error> {
93
- let priority: Priority = priority_str.parse()?;
94
- // From here, priority is type-safe
95
- process(priority);
96
- Ok(())
97
- }
98
- ```
99
-
100
- ## Validated Newtypes
101
-
102
- ```rust
103
- // Instead of string for email
104
- struct Email(String);
105
-
106
- impl Email {
107
- fn new(s: &str) -> Result<Self, ValidationError> {
108
- if is_valid_email(s) {
109
- Ok(Email(s.to_string()))
110
- } else {
111
- Err(ValidationError::InvalidEmail)
112
- }
113
- }
114
- }
115
-
116
- // Instead of string for UUID
117
- struct UserId(uuid::Uuid);
118
-
119
- // Instead of string for paths
120
- struct ConfigPath(PathBuf);
121
- ```
122
-
123
- ## With Serde
124
-
125
- ```rust
126
- use serde::{Deserialize, Serialize};
127
-
128
- #[derive(Debug, Serialize, Deserialize)]
129
- #[serde(rename_all = "snake_case")]
130
- enum EventType {
131
- UserCreated,
132
- UserDeleted,
133
- UserUpdated,
134
- }
135
-
136
- // JSON: {"type": "user_created", ...}
137
- // Automatically validated during deserialization
138
- ```
139
-
140
- ## See Also
141
-
142
- - [anti-stringly-typed](./anti-stringly-typed.md) - Anti-pattern details
143
- - [type-newtype-validated](./type-newtype-validated.md) - Validated newtypes
144
- - [type-enum-states](./type-enum-states.md) - Enums for states