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,145 +0,0 @@
1
- # err-doc-errors
2
-
3
- > Document error conditions with `# Errors` section in doc comments
4
-
5
- ## Why It Matters
6
-
7
- Users of your API need to know what can go wrong and why. The `# Errors` documentation section is the standard Rust convention for describing when a function returns `Err`. Good error documentation helps callers handle errors appropriately and understand the contract of your API.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- /// Loads a configuration from the specified path.
13
- pub fn load_config(path: &Path) -> Result<Config, ConfigError> {
14
- // No documentation of error conditions
15
- // Caller must read source code to understand what can fail
16
- }
17
-
18
- /// Parses and validates the input string.
19
- ///
20
- /// Returns the parsed value. // What about errors?
21
- pub fn parse_input(input: &str) -> Result<Value, ParseError> {
22
- // ...
23
- }
24
- ```
25
-
26
- ## Good
27
-
28
- ```rust
29
- /// Loads a configuration from the specified path.
30
- ///
31
- /// # Errors
32
- ///
33
- /// Returns an error if:
34
- /// - The file at `path` does not exist or cannot be read
35
- /// - The file contents are not valid TOML
36
- /// - Required configuration keys are missing
37
- /// - Configuration values are out of valid ranges
38
- ///
39
- /// # Examples
40
- ///
41
- /// ```
42
- /// # use mylib::{load_config, ConfigError};
43
- /// # fn main() -> Result<(), ConfigError> {
44
- /// let config = load_config("app.toml")?;
45
- /// # Ok(())
46
- /// # }
47
- /// ```
48
- pub fn load_config(path: &Path) -> Result<Config, ConfigError> {
49
- // ...
50
- }
51
-
52
- /// Parses and validates the input string as a positive integer.
53
- ///
54
- /// # Errors
55
- ///
56
- /// Returns [`ParseError::Empty`] if the input is empty.
57
- /// Returns [`ParseError::InvalidFormat`] if the input contains non-digit characters.
58
- /// Returns [`ParseError::Overflow`] if the value exceeds `i64::MAX`.
59
- /// Returns [`ParseError::NotPositive`] if the value is zero or negative.
60
- pub fn parse_positive_int(input: &str) -> Result<i64, ParseError> {
61
- // ...
62
- }
63
- ```
64
-
65
- ## Linking to Error Variants
66
-
67
- ```rust
68
- /// Attempts to connect to the database.
69
- ///
70
- /// # Errors
71
- ///
72
- /// This function will return an error if:
73
- ///
74
- /// - [`DbError::ConnectionFailed`] - The database server is unreachable
75
- /// - [`DbError::AuthenticationFailed`] - Invalid credentials
76
- /// - [`DbError::Timeout`] - Connection attempt exceeded timeout
77
- /// - [`DbError::TlsError`] - TLS handshake failed
78
- ///
79
- /// See [`DbError`] for more details on each variant.
80
- pub fn connect(config: &DbConfig) -> Result<Connection, DbError> {
81
- // ...
82
- }
83
- ```
84
-
85
- ## Panic vs Error Documentation
86
-
87
- ```rust
88
- /// Divides two numbers.
89
- ///
90
- /// # Errors
91
- ///
92
- /// Returns [`MathError::DivisionByZero`] if `divisor` is zero.
93
- ///
94
- /// # Panics
95
- ///
96
- /// Panics if called from a non-main thread (debug builds only).
97
- pub fn divide(dividend: i64, divisor: i64) -> Result<i64, MathError> {
98
- // ...
99
- }
100
- ```
101
-
102
- ## Error Section Format Options
103
-
104
- ```rust
105
- // Style 1: Bullet list (good for multiple conditions)
106
- /// # Errors
107
- ///
108
- /// Returns an error if:
109
- /// - The file does not exist
110
- /// - The file cannot be read
111
- /// - The content is invalid UTF-8
112
-
113
- // Style 2: Returns statements (good for mapping to variants)
114
- /// # Errors
115
- ///
116
- /// Returns [`Error::NotFound`] if the item doesn't exist.
117
- /// Returns [`Error::PermissionDenied`] if access is forbidden.
118
-
119
- // Style 3: Prose (good for complex conditions)
120
- /// # Errors
121
- ///
122
- /// This function returns an error when the input fails validation.
123
- /// Validation includes checking that all required fields are present,
124
- /// that numeric fields are within allowed ranges, and that string
125
- /// fields match their expected formats.
126
- ```
127
-
128
- ## Clippy Lint
129
-
130
- ```toml
131
- # Cargo.toml - require error documentation
132
- [lints.clippy]
133
- missing_errors_doc = "warn"
134
- ```
135
-
136
- ```rust
137
- // This will warn without # Errors section
138
- pub fn might_fail() -> Result<(), Error> { Ok(()) }
139
- ```
140
-
141
- ## See Also
142
-
143
- - [doc-examples-section](./doc-examples-section.md) - Examples in documentation
144
- - [err-thiserror-lib](./err-thiserror-lib.md) - Defining error types
145
- - [api-must-use](./api-must-use.md) - Marking Results as must_use
@@ -1,133 +0,0 @@
1
- # err-expect-bugs-only
2
-
3
- > Use `expect()` only for invariants that indicate bugs, not user errors
4
-
5
- ## Why It Matters
6
-
7
- `expect()` is better than `unwrap()` because it provides context, but it still panics. Reserve it for situations where failure indicates a bug in your code—a violated invariant, not a user error or external failure. The message should explain why the invariant should hold, helping future developers understand and fix the bug.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // User input can legitimately fail - don't expect
13
- fn parse_user_input(input: &str) -> Config {
14
- serde_json::from_str(input)
15
- .expect("Invalid JSON") // User error, not a bug!
16
- }
17
-
18
- // Network can fail - don't expect
19
- fn fetch_data(url: &str) -> Data {
20
- reqwest::get(url)
21
- .expect("Network request failed") // External failure!
22
- .json()
23
- .expect("Invalid response")
24
- }
25
-
26
- // File might not exist - don't expect
27
- fn load_config() -> Config {
28
- let content = fs::read_to_string("config.json")
29
- .expect("Config file missing"); // Environment issue!
30
- }
31
- ```
32
-
33
- ## Good
34
-
35
- ```rust
36
- // Invariant: after insert, key exists
37
- fn cache_and_get(&mut self, key: String, value: Value) -> &Value {
38
- self.cache.insert(key.clone(), value);
39
- self.cache.get(&key)
40
- .expect("BUG: key must exist immediately after insert")
41
- }
42
-
43
- // Invariant: regex is compile-time constant
44
- fn create_parser() -> Regex {
45
- Regex::new(r"^\d{4}-\d{2}-\d{2}$")
46
- .expect("BUG: date regex is invalid - this is a compile-time constant")
47
- }
48
-
49
- // Invariant: already validated
50
- fn process_validated(data: ValidatedData) -> Result<Output, ProcessError> {
51
- let value = data.required_field
52
- .expect("BUG: ValidatedData guarantees required_field is Some");
53
- // ...
54
- }
55
-
56
- // Invariant: type system guarantees
57
- fn get_first<T>(vec: Vec<T>) -> T
58
- where
59
- Vec<T>: NonEmpty, // Hypothetical trait
60
- {
61
- vec.into_iter().next()
62
- .expect("BUG: NonEmpty Vec cannot be empty")
63
- }
64
- ```
65
-
66
- ## expect() Message Guidelines
67
-
68
- Messages should:
69
- 1. Start with "BUG:" or similar to indicate it's an invariant
70
- 2. Explain WHY the invariant should hold
71
- 3. Help developers fix the issue
72
-
73
- ```rust
74
- // ❌ Bad messages
75
- .expect("failed") // No context
76
- .expect("should not be None") // Doesn't explain why
77
- .expect("Invalid state") // Vague
78
-
79
- // ✅ Good messages
80
- .expect("BUG: HashMap entry exists after insert")
81
- .expect("BUG: validated input must parse - validation is broken")
82
- .expect("BUG: static regex compilation failed - regex syntax error in source")
83
- ```
84
-
85
- ## Pattern: Validate Once, expect() After
86
-
87
- ```rust
88
- struct ValidatedEmail(String);
89
-
90
- impl ValidatedEmail {
91
- pub fn new(email: &str) -> Result<Self, EmailError> {
92
- // Validation happens here, returns Result
93
- if !is_valid_email(email) {
94
- return Err(EmailError::Invalid);
95
- }
96
- Ok(ValidatedEmail(email.to_string()))
97
- }
98
-
99
- pub fn domain(&self) -> &str {
100
- // After validation, expect() is fine
101
- self.0.split('@').nth(1)
102
- .expect("BUG: ValidatedEmail must contain @")
103
- }
104
- }
105
- ```
106
-
107
- ## Alternatives When expect() Is Wrong
108
-
109
- ```rust
110
- // Don't: expect on user data
111
- let port: u16 = input.parse().expect("Invalid port");
112
-
113
- // Do: Return Result
114
- let port: u16 = input.parse().map_err(|_| ConfigError::InvalidPort)?;
115
-
116
- // Do: Provide default
117
- let port: u16 = input.parse().unwrap_or(8080);
118
-
119
- // Do: Handle explicitly
120
- let port: u16 = match input.parse() {
121
- Ok(p) => p,
122
- Err(_) => {
123
- log::warn!("Invalid port '{}', using default", input);
124
- 8080
125
- }
126
- };
127
- ```
128
-
129
- ## See Also
130
-
131
- - [err-no-unwrap-prod](./err-no-unwrap-prod.md) - Avoiding unwrap in production
132
- - [err-result-over-panic](./err-result-over-panic.md) - When to return Result
133
- - [api-parse-dont-validate](./api-parse-dont-validate.md) - Type-driven validation
@@ -1,152 +0,0 @@
1
- # err-from-impl
2
-
3
- > Implement `From<E>` for error conversions to enable `?` operator
4
-
5
- ## Why It Matters
6
-
7
- The `?` operator automatically converts errors using `From` trait. By implementing `From<SourceError> for YourError`, you enable seamless error propagation without explicit `.map_err()` calls. This makes error handling code cleaner and ensures consistent error wrapping throughout your codebase.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- #[derive(Debug)]
13
- enum AppError {
14
- Io(std::io::Error),
15
- Parse(serde_json::Error),
16
- Database(diesel::result::Error),
17
- }
18
-
19
- fn load_config(path: &str) -> Result<Config, AppError> {
20
- let content = std::fs::read_to_string(path)
21
- .map_err(|e| AppError::Io(e))?; // Manual conversion everywhere
22
-
23
- let config: Config = serde_json::from_str(&content)
24
- .map_err(|e| AppError::Parse(e))?; // Repeated boilerplate
25
-
26
- save_to_db(&config)
27
- .map_err(|e| AppError::Database(e))?; // Gets tedious
28
-
29
- Ok(config)
30
- }
31
- ```
32
-
33
- ## Good
34
-
35
- ```rust
36
- #[derive(Debug)]
37
- enum AppError {
38
- Io(std::io::Error),
39
- Parse(serde_json::Error),
40
- Database(diesel::result::Error),
41
- }
42
-
43
- // Implement From for each source error type
44
- impl From<std::io::Error> for AppError {
45
- fn from(err: std::io::Error) -> Self {
46
- AppError::Io(err)
47
- }
48
- }
49
-
50
- impl From<serde_json::Error> for AppError {
51
- fn from(err: serde_json::Error) -> Self {
52
- AppError::Parse(err)
53
- }
54
- }
55
-
56
- impl From<diesel::result::Error> for AppError {
57
- fn from(err: diesel::result::Error) -> Self {
58
- AppError::Database(err)
59
- }
60
- }
61
-
62
- fn load_config(path: &str) -> Result<Config, AppError> {
63
- let content = std::fs::read_to_string(path)?; // Auto-converts
64
- let config: Config = serde_json::from_str(&content)?; // Clean!
65
- save_to_db(&config)?;
66
- Ok(config)
67
- }
68
- ```
69
-
70
- ## Use thiserror for Automatic From
71
-
72
- ```rust
73
- use thiserror::Error;
74
-
75
- #[derive(Error, Debug)]
76
- enum AppError {
77
- #[error("IO error: {0}")]
78
- Io(#[from] std::io::Error), // Auto-generates From impl
79
-
80
- #[error("Parse error: {0}")]
81
- Parse(#[from] serde_json::Error), // #[from] does the work
82
-
83
- #[error("Database error: {0}")]
84
- Database(#[from] diesel::result::Error),
85
- }
86
-
87
- // Now ? just works
88
- fn load_config(path: &str) -> Result<Config, AppError> {
89
- let content = std::fs::read_to_string(path)?;
90
- let config: Config = serde_json::from_str(&content)?;
91
- save_to_db(&config)?;
92
- Ok(config)
93
- }
94
- ```
95
-
96
- ## From with Context
97
-
98
- Sometimes you need to add context during conversion:
99
-
100
- ```rust
101
- #[derive(Error, Debug)]
102
- enum ConfigError {
103
- #[error("Failed to read config from '{path}': {source}")]
104
- ReadFailed {
105
- path: String,
106
- #[source]
107
- source: std::io::Error,
108
- },
109
- }
110
-
111
- // Can't use #[from] when you need extra context
112
- fn load_config(path: &str) -> Result<Config, ConfigError> {
113
- let content = std::fs::read_to_string(path)
114
- .map_err(|source| ConfigError::ReadFailed {
115
- path: path.to_string(),
116
- source,
117
- })?;
118
- // ...
119
- }
120
-
121
- // Or use anyhow for ad-hoc context
122
- use anyhow::{Context, Result};
123
-
124
- fn load_config(path: &str) -> Result<Config> {
125
- let content = std::fs::read_to_string(path)
126
- .with_context(|| format!("Failed to read config from '{}'", path))?;
127
- // ...
128
- }
129
- ```
130
-
131
- ## Blanket From Implementations
132
-
133
- Be careful with blanket implementations:
134
-
135
- ```rust
136
- // ❌ Too broad - conflicts with other From impls
137
- impl<E: std::error::Error> From<E> for AppError {
138
- fn from(err: E) -> Self {
139
- AppError::Other(err.to_string())
140
- }
141
- }
142
-
143
- // ✅ Specific implementations
144
- impl From<std::io::Error> for AppError { ... }
145
- impl From<ParseIntError> for AppError { ... }
146
- ```
147
-
148
- ## See Also
149
-
150
- - [err-thiserror-lib](./err-thiserror-lib.md) - Using thiserror for libraries
151
- - [err-source-chain](./err-source-chain.md) - Preserving error chains
152
- - [err-question-mark](./err-question-mark.md) - The ? operator
@@ -1,124 +0,0 @@
1
- # err-lowercase-msg
2
-
3
- > Start error messages lowercase, no trailing punctuation
4
-
5
- ## Why It Matters
6
-
7
- Error messages are often chained, logged, or displayed with additional context. Consistent formatting—lowercase start, no trailing period—allows clean composition: "failed to load config: invalid JSON: unexpected token". Mixed case and punctuation create awkward output: "Failed to load config.: Invalid JSON.: Unexpected token.".
8
-
9
- ## Bad
10
-
11
- ```rust
12
- use thiserror::Error;
13
-
14
- #[derive(Error, Debug)]
15
- enum ConfigError {
16
- #[error("Failed to read config file.")] // Capital F, trailing period
17
- ReadFailed(#[from] std::io::Error),
18
-
19
- #[error("Invalid JSON format!")] // Capital I, exclamation
20
- ParseFailed(#[from] serde_json::Error),
21
-
22
- #[error("The requested key was not found")] // Reads like a sentence
23
- KeyNotFound(String),
24
- }
25
-
26
- // Chained output: "Config load error: Failed to read config file.: No such file"
27
- // Awkward capitalization and punctuation
28
- ```
29
-
30
- ## Good
31
-
32
- ```rust
33
- use thiserror::Error;
34
-
35
- #[derive(Error, Debug)]
36
- enum ConfigError {
37
- #[error("failed to read config file")] // lowercase, no period
38
- ReadFailed(#[from] std::io::Error),
39
-
40
- #[error("invalid JSON format")] // lowercase, no period
41
- ParseFailed(#[from] serde_json::Error),
42
-
43
- #[error("key not found: {0}")] // lowercase, data at end
44
- KeyNotFound(String),
45
- }
46
-
47
- // Chained output: "config load error: failed to read config file: no such file"
48
- // Clean, consistent
49
- ```
50
-
51
- ## Rust Standard Library Convention
52
-
53
- The standard library follows this convention:
54
-
55
- ```rust
56
- // std::io::Error messages
57
- "entity not found"
58
- "permission denied"
59
- "connection refused"
60
-
61
- // std::num::ParseIntError
62
- "invalid digit found in string"
63
-
64
- // std::str::Utf8Error
65
- "invalid utf-8 sequence"
66
- ```
67
-
68
- ## Formatting Guidelines
69
-
70
- | Do | Don't |
71
- |----|-------|
72
- | `"failed to parse config"` | `"Failed to parse config."` |
73
- | `"invalid input: expected number"` | `"Invalid input - expected a number!"` |
74
- | `"connection timed out after {0}s"` | `"Connection Timed Out After {0} seconds."` |
75
- | `"key '{0}' not found"` | `"Key Not Found: {0}"` |
76
-
77
- ## Context Addition Pattern
78
-
79
- ```rust
80
- use anyhow::{Context, Result};
81
-
82
- fn load_user(id: u64) -> Result<User> {
83
- let data = fetch(id)
84
- .with_context(|| format!("failed to fetch user {}", id))?;
85
-
86
- parse_user(data)
87
- .with_context(|| "failed to parse user data")?
88
- }
89
-
90
- // Output: "failed to fetch user 42: connection refused"
91
- // All lowercase, clean chain
92
- ```
93
-
94
- ## Display vs Debug
95
-
96
- ```rust
97
- #[derive(Error, Debug)]
98
- #[error("invalid configuration")] // Display: for users/logs
99
- pub struct ConfigError {
100
- path: PathBuf,
101
- source: io::Error,
102
- }
103
-
104
- // Debug output (for developers) can have more detail
105
- // Display output (for users) should be clean
106
- ```
107
-
108
- ## When to Use Capitals
109
-
110
- ```rust
111
- // Proper nouns / acronyms keep their case
112
- #[error("invalid JSON syntax")] // JSON is an acronym
113
- #[error("OAuth token expired")] // OAuth is a proper noun
114
- #[error("HTTP request failed")] // HTTP is an acronym
115
-
116
- // Error codes can be uppercase
117
- #[error("error code E0001: invalid input")]
118
- ```
119
-
120
- ## See Also
121
-
122
- - [err-thiserror-lib](./err-thiserror-lib.md) - Error definition with thiserror
123
- - [err-context-chain](./err-context-chain.md) - Adding context to errors
124
- - [doc-examples-section](./doc-examples-section.md) - Documentation conventions
@@ -1,115 +0,0 @@
1
- # err-no-unwrap-prod
2
-
3
- > Avoid `unwrap()` in production code; use `?`, `expect()`, or handle errors
4
-
5
- ## Why It Matters
6
-
7
- `unwrap()` panics on `None` or `Err` without any context about what went wrong. In production, this creates cryptic crash messages that are hard to debug. Either propagate errors with `?`, use `expect()` with a message explaining the invariant, or handle the error explicitly.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- fn process_request(req: Request) -> Response {
13
- let user_id = req.headers.get("X-User-Id").unwrap(); // Why did it fail?
14
- let user = database.find_user(user_id).unwrap(); // Which operation?
15
- let data = user.preferences.get("theme").unwrap(); // No context
16
-
17
- Response::new(data)
18
- }
19
-
20
- // Crash message: "called `Option::unwrap()` on a `None` value"
21
- // Where? Why? No idea.
22
- ```
23
-
24
- ## Good
25
-
26
- ```rust
27
- // Option 1: Propagate with ?
28
- fn process_request(req: Request) -> Result<Response, AppError> {
29
- let user_id = req.headers
30
- .get("X-User-Id")
31
- .ok_or(AppError::MissingHeader("X-User-Id"))?;
32
-
33
- let user = database.find_user(user_id)?;
34
-
35
- let data = user.preferences
36
- .get("theme")
37
- .ok_or(AppError::MissingPreference("theme"))?;
38
-
39
- Ok(Response::new(data))
40
- }
41
-
42
- // Option 2: expect() for invariants (not user input)
43
- fn get_config_value(&self, key: &str) -> &str {
44
- self.config
45
- .get(key)
46
- .expect("BUG: required config key missing after validation")
47
- }
48
-
49
- // Option 3: Provide defaults
50
- fn get_theme(user: &User) -> &str {
51
- user.preferences
52
- .get("theme")
53
- .unwrap_or(&"default")
54
- }
55
-
56
- // Option 4: Match for complex handling
57
- fn process_optional(value: Option<Data>) -> ProcessedData {
58
- match value {
59
- Some(data) => process(data),
60
- None => {
61
- log::warn!("No data provided, using fallback");
62
- ProcessedData::default()
63
- }
64
- }
65
- }
66
- ```
67
-
68
- ## `expect()` vs `unwrap()`
69
-
70
- ```rust
71
- // Bad: no context
72
- let port = config.get("port").unwrap();
73
-
74
- // Better: explains the invariant
75
- let port = config.get("port")
76
- .expect("config must contain 'port' after validation");
77
-
78
- // Best: propagate if it's not truly an invariant
79
- let port = config.get("port")
80
- .ok_or_else(|| ConfigError::MissingKey("port"))?;
81
- ```
82
-
83
- ## Alternatives to unwrap()
84
-
85
- | Situation | Use Instead |
86
- |-----------|-------------|
87
- | Can propagate error | `?` operator |
88
- | Has sensible default | `unwrap_or()`, `unwrap_or_default()` |
89
- | Default requires computation | `unwrap_or_else(\|\| ...)` |
90
- | Internal invariant | `expect("explanation")` |
91
- | Need to handle both cases | `match` or `if let` |
92
-
93
- ## Clippy Lints
94
-
95
- ```toml
96
- # Cargo.toml
97
- [lints.clippy]
98
- unwrap_used = "warn" # Warn on unwrap()
99
- expect_used = "warn" # Also warn on expect() (stricter)
100
- ```
101
-
102
- ```rust
103
- // Allow in specific places where it's justified
104
- #[allow(clippy::unwrap_used)]
105
- fn definitely_safe() {
106
- // Unwrap is safe here because...
107
- let x = Some(5).unwrap();
108
- }
109
- ```
110
-
111
- ## See Also
112
-
113
- - [err-result-over-panic](./err-result-over-panic.md) - Return Result instead of panicking
114
- - [err-expect-bugs-only](./err-expect-bugs-only.md) - When expect() is appropriate
115
- - [anti-unwrap-abuse](./anti-unwrap-abuse.md) - Patterns for avoiding unwrap