agy-superpowers 5.1.4 → 5.1.6

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 (185) hide show
  1. package/package.json +1 -1
  2. package/template/agent/rules/debug-confirmation-policy.md +34 -0
  3. package/template/agent/rules/language-matching.md +32 -0
  4. package/template/agent/skills/rust-developer/SKILL.md +281 -0
  5. package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +231 -0
  6. package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +124 -0
  7. package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +131 -0
  8. package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +132 -0
  9. package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +95 -0
  10. package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +141 -0
  11. package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +125 -0
  12. package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +127 -0
  13. package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +120 -0
  14. package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +131 -0
  15. package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +156 -0
  16. package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +122 -0
  17. package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +167 -0
  18. package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +134 -0
  19. package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +143 -0
  20. package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +121 -0
  21. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +143 -0
  22. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +187 -0
  23. package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +165 -0
  24. package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +177 -0
  25. package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +163 -0
  26. package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +146 -0
  27. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +142 -0
  28. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +160 -0
  29. package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +125 -0
  30. package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +162 -0
  31. package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +177 -0
  32. package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +184 -0
  33. package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +168 -0
  34. package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +182 -0
  35. package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +199 -0
  36. package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +175 -0
  37. package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +185 -0
  38. package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +203 -0
  39. package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +171 -0
  40. package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +158 -0
  41. package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +195 -0
  42. package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +171 -0
  43. package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +156 -0
  44. package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +191 -0
  45. package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +198 -0
  46. package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +154 -0
  47. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +167 -0
  48. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +169 -0
  49. package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +172 -0
  50. package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +189 -0
  51. package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +113 -0
  52. package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +147 -0
  53. package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +122 -0
  54. package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +161 -0
  55. package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +149 -0
  56. package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +138 -0
  57. package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +169 -0
  58. package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +116 -0
  59. package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +128 -0
  60. package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +136 -0
  61. package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +131 -0
  62. package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +179 -0
  63. package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +144 -0
  64. package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +152 -0
  65. package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +145 -0
  66. package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +133 -0
  67. package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +152 -0
  68. package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +124 -0
  69. package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +115 -0
  70. package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +151 -0
  71. package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +130 -0
  72. package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +155 -0
  73. package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +171 -0
  74. package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +138 -0
  75. package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +107 -0
  76. package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +154 -0
  77. package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +118 -0
  78. package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +157 -0
  79. package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +133 -0
  80. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +131 -0
  81. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +136 -0
  82. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +135 -0
  83. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +122 -0
  84. package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +172 -0
  85. package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +168 -0
  86. package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +142 -0
  87. package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +168 -0
  88. package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +147 -0
  89. package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +158 -0
  90. package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +139 -0
  91. package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +147 -0
  92. package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +149 -0
  93. package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +174 -0
  94. package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +159 -0
  95. package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +138 -0
  96. package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +142 -0
  97. package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +156 -0
  98. package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +172 -0
  99. package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +164 -0
  100. package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +99 -0
  101. package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +104 -0
  102. package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +94 -0
  103. package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +78 -0
  104. package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +76 -0
  105. package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +123 -0
  106. package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +127 -0
  107. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +129 -0
  108. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +131 -0
  109. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +142 -0
  110. package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +86 -0
  111. package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +154 -0
  112. package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +118 -0
  113. package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +92 -0
  114. package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +65 -0
  115. package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +101 -0
  116. package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +161 -0
  117. package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +187 -0
  118. package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +142 -0
  119. package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +152 -0
  120. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +141 -0
  121. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +181 -0
  122. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +160 -0
  123. package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +171 -0
  124. package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +130 -0
  125. package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +167 -0
  126. package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +144 -0
  127. package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +154 -0
  128. package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +141 -0
  129. package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +95 -0
  130. package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +135 -0
  131. package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +124 -0
  132. package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +135 -0
  133. package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +134 -0
  134. package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +134 -0
  135. package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +105 -0
  136. package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +65 -0
  137. package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +97 -0
  138. package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +122 -0
  139. package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +119 -0
  140. package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +153 -0
  141. package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +136 -0
  142. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +133 -0
  143. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +120 -0
  144. package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +137 -0
  145. package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +134 -0
  146. package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +150 -0
  147. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +123 -0
  148. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +113 -0
  149. package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +175 -0
  150. package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +149 -0
  151. package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +142 -0
  152. package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +133 -0
  153. package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +148 -0
  154. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +130 -0
  155. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +120 -0
  156. package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +155 -0
  157. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +139 -0
  158. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +135 -0
  159. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +162 -0
  160. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +186 -0
  161. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +162 -0
  162. package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +160 -0
  163. package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +151 -0
  164. package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +171 -0
  165. package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +142 -0
  166. package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +168 -0
  167. package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +151 -0
  168. package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +144 -0
  169. package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +189 -0
  170. package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +226 -0
  171. package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +161 -0
  172. package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +130 -0
  173. package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +154 -0
  174. package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +127 -0
  175. package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +154 -0
  176. package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +142 -0
  177. package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +146 -0
  178. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +160 -0
  179. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +159 -0
  180. package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +144 -0
  181. package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +137 -0
  182. package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +188 -0
  183. package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +143 -0
  184. package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +131 -0
  185. package/template/agent/skills/systematic-debugging/SKILL.md +17 -0
@@ -0,0 +1,137 @@
1
+ # type-option-nullable
2
+
3
+ > Use `Option<T>` for values that might not exist
4
+
5
+ ## Why It Matters
6
+
7
+ `Option<T>` explicitly represents "value or nothing" in the type system. Unlike null pointers or sentinel values, you can't accidentally use a missing value—the compiler forces you to handle the `None` case. This eliminates null pointer exceptions at compile time.
8
+
9
+ ## Bad
10
+
11
+ ```rust
12
+ // Sentinel values - easy to forget to check
13
+ fn find_user(id: u64) -> User {
14
+ // Returns "empty" user if not found - caller might not check
15
+ users.get(&id).cloned().unwrap_or(User::empty())
16
+ }
17
+
18
+ // Nullable-style with raw pointers
19
+ fn find_user(id: u64) -> *const User {
20
+ // Null if not found - unsafe, no compiler help
21
+ }
22
+
23
+ // Error-prone usage
24
+ let user = find_user(42);
25
+ println!("{}", user.name); // Might be empty user - silent bug
26
+ ```
27
+
28
+ ## Good
29
+
30
+ ```rust
31
+ // Option makes absence explicit
32
+ fn find_user(id: u64) -> Option<User> {
33
+ users.get(&id).cloned()
34
+ }
35
+
36
+ // Must handle the None case
37
+ let user = find_user(42);
38
+ match user {
39
+ Some(u) => println!("{}", u.name),
40
+ None => println!("User not found"),
41
+ }
42
+
43
+ // Or use combinators
44
+ let name = find_user(42)
45
+ .map(|u| u.name)
46
+ .unwrap_or_else(|| "Unknown".to_string());
47
+ ```
48
+
49
+ ## Common Option Patterns
50
+
51
+ ```rust
52
+ // if let for single case
53
+ if let Some(user) = find_user(id) {
54
+ process(user);
55
+ }
56
+
57
+ // Chaining with map
58
+ let upper_name = find_user(id)
59
+ .map(|u| u.name)
60
+ .map(|n| n.to_uppercase());
61
+
62
+ // Providing defaults
63
+ let user = find_user(id).unwrap_or_default();
64
+ let user = find_user(id).unwrap_or_else(|| User::guest());
65
+
66
+ // ? operator for propagation
67
+ fn get_user_email(id: u64) -> Option<String> {
68
+ let user = find_user(id)?;
69
+ Some(user.email)
70
+ }
71
+
72
+ // and_then for chained optionals
73
+ fn get_user_country(id: u64) -> Option<String> {
74
+ find_user(id)
75
+ .and_then(|u| u.address)
76
+ .and_then(|a| a.country)
77
+ }
78
+ ```
79
+
80
+ ## Struct Fields
81
+
82
+ ```rust
83
+ struct User {
84
+ name: String,
85
+ email: String,
86
+ phone: Option<String>, // Optional field
87
+ avatar_url: Option<Url>, // Optional field
88
+ }
89
+
90
+ impl User {
91
+ fn display_phone(&self) -> &str {
92
+ self.phone.as_deref().unwrap_or("Not provided")
93
+ }
94
+ }
95
+ ```
96
+
97
+ ## Option vs Result
98
+
99
+ ```rust
100
+ // Option: value might not exist (no error context)
101
+ fn find(key: &str) -> Option<Value> { ... }
102
+
103
+ // Result: operation might fail (with error context)
104
+ fn parse(input: &str) -> Result<Value, ParseError> { ... }
105
+
106
+ // Convert Option to Result
107
+ let value = find("key").ok_or(Error::NotFound)?;
108
+
109
+ // Convert Result to Option
110
+ let value = parse("input").ok(); // Discards error
111
+ ```
112
+
113
+ ## Option References
114
+
115
+ ```rust
116
+ // Option<&T> for optional borrows
117
+ fn get(&self, key: &str) -> Option<&Value> {
118
+ self.map.get(key)
119
+ }
120
+
121
+ // as_ref() to borrow Option contents
122
+ let opt: Option<String> = Some("hello".to_string());
123
+ let opt_ref: Option<&String> = opt.as_ref();
124
+ let opt_str: Option<&str> = opt.as_deref();
125
+
126
+ // as_mut() for mutable borrow
127
+ let mut opt = Some(vec![1, 2, 3]);
128
+ if let Some(v) = opt.as_mut() {
129
+ v.push(4);
130
+ }
131
+ ```
132
+
133
+ ## See Also
134
+
135
+ - [type-result-fallible](./type-result-fallible.md) - Result for errors
136
+ - [type-enum-states](./type-enum-states.md) - Enums for states
137
+ - [err-no-unwrap-prod](./err-no-unwrap-prod.md) - Handling Option safely
@@ -0,0 +1,188 @@
1
+ # type-phantom-marker
2
+
3
+ > Use `PhantomData` to express type relationships without runtime cost
4
+
5
+ ## Why It Matters
6
+
7
+ Sometimes your type needs to be parameterized by a type that doesn't appear in any field—for variance, drop order, or semantic purposes. `PhantomData<T>` tells the compiler your type is "associated with" `T` without storing any `T` data. It has zero runtime cost.
8
+
9
+ ## Bad
10
+
11
+ ```rust
12
+ // Type parameter unused - compiler error
13
+ struct Handle<T> {
14
+ id: u64,
15
+ // Error: parameter `T` is never used
16
+ }
17
+
18
+ // Workaround with unnecessary storage
19
+ struct Handle<T> {
20
+ id: u64,
21
+ _type: Option<T>, // Wastes memory, requires T: Default
22
+ }
23
+ ```
24
+
25
+ ## Good
26
+
27
+ ```rust
28
+ use std::marker::PhantomData;
29
+
30
+ struct Handle<T> {
31
+ id: u64,
32
+ _marker: PhantomData<T>, // Zero-size, tells compiler about T
33
+ }
34
+
35
+ impl<T> Handle<T> {
36
+ fn new(id: u64) -> Self {
37
+ Handle {
38
+ id,
39
+ _marker: PhantomData,
40
+ }
41
+ }
42
+ }
43
+
44
+ // Different Handle types are incompatible
45
+ struct User;
46
+ struct Order;
47
+
48
+ fn process_user(h: Handle<User>) { ... }
49
+
50
+ let user_handle = Handle::<User>::new(1);
51
+ let order_handle = Handle::<Order>::new(2);
52
+
53
+ process_user(user_handle); // OK
54
+ process_user(order_handle); // Error: expected Handle<User>, found Handle<Order>
55
+ ```
56
+
57
+ ## Expressing Ownership
58
+
59
+ ```rust
60
+ use std::marker::PhantomData;
61
+
62
+ // Owns T conceptually (like Box<T>)
63
+ struct Container<T> {
64
+ ptr: *mut T,
65
+ _marker: PhantomData<T>, // Acts like we own a T
66
+ }
67
+
68
+ // Drop will be called on T when Container drops
69
+ impl<T> Drop for Container<T> {
70
+ fn drop(&mut self) {
71
+ unsafe {
72
+ std::ptr::drop_in_place(self.ptr);
73
+ }
74
+ }
75
+ }
76
+ ```
77
+
78
+ ## Expressing Borrowing
79
+
80
+ ```rust
81
+ use std::marker::PhantomData;
82
+
83
+ // Borrows T for lifetime 'a
84
+ struct Ref<'a, T> {
85
+ ptr: *const T,
86
+ _marker: PhantomData<&'a T>, // Acts like &'a T
87
+ }
88
+
89
+ // Compiler tracks lifetime correctly
90
+ impl<'a, T> Ref<'a, T> {
91
+ fn get(&self) -> &'a T {
92
+ unsafe { &*self.ptr }
93
+ }
94
+ }
95
+ ```
96
+
97
+ ## Type-Level State Machine
98
+
99
+ ```rust
100
+ use std::marker::PhantomData;
101
+
102
+ // States as zero-size types
103
+ struct Unlocked;
104
+ struct Locked;
105
+
106
+ struct Door<State> {
107
+ _state: PhantomData<State>,
108
+ }
109
+
110
+ impl Door<Unlocked> {
111
+ fn lock(self) -> Door<Locked> {
112
+ println!("Locking...");
113
+ Door { _state: PhantomData }
114
+ }
115
+
116
+ fn open(&self) {
117
+ println!("Opening...");
118
+ }
119
+ }
120
+
121
+ impl Door<Locked> {
122
+ fn unlock(self) -> Door<Unlocked> {
123
+ println!("Unlocking...");
124
+ Door { _state: PhantomData }
125
+ }
126
+
127
+ // Can't call open() on Locked door - method doesn't exist
128
+ }
129
+
130
+ fn example() {
131
+ let door: Door<Unlocked> = Door { _state: PhantomData };
132
+ door.open(); // OK
133
+ let locked = door.lock();
134
+ // locked.open(); // Error: no method `open` for Door<Locked>
135
+ let unlocked = locked.unlock();
136
+ unlocked.open(); // OK
137
+ }
138
+ ```
139
+
140
+ ## Variance Control
141
+
142
+ ```rust
143
+ use std::marker::PhantomData;
144
+
145
+ // Covariant in T (PhantomData<T>)
146
+ struct Producer<T> {
147
+ _marker: PhantomData<T>, // Covariant
148
+ }
149
+
150
+ // Contravariant in T (PhantomData<fn(T)>)
151
+ struct Consumer<T> {
152
+ _marker: PhantomData<fn(T)>, // Contravariant
153
+ }
154
+
155
+ // Invariant in T (PhantomData<fn(T) -> T>)
156
+ struct Both<T> {
157
+ _marker: PhantomData<fn(T) -> T>, // Invariant
158
+ }
159
+ ```
160
+
161
+ ## Common Uses
162
+
163
+ ```rust
164
+ // 1. FFI handles with type safety
165
+ struct FileHandle<T: FileType> {
166
+ fd: i32,
167
+ _marker: PhantomData<T>,
168
+ }
169
+
170
+ // 2. Generic iterators
171
+ struct Iter<'a, T> {
172
+ ptr: *const T,
173
+ end: *const T,
174
+ _marker: PhantomData<&'a T>,
175
+ }
176
+
177
+ // 3. Allocator-aware types
178
+ struct Vec<T, A: Allocator = Global> {
179
+ buf: RawVec<T, A>,
180
+ len: usize,
181
+ }
182
+ ```
183
+
184
+ ## See Also
185
+
186
+ - [api-typestate](./api-typestate.md) - State machine pattern
187
+ - [api-newtype-safety](./api-newtype-safety.md) - Type-safe wrappers
188
+ - [type-newtype-ids](./type-newtype-ids.md) - ID types
@@ -0,0 +1,143 @@
1
+ # type-repr-transparent
2
+
3
+ > Use `#[repr(transparent)]` for newtypes in FFI contexts
4
+
5
+ ## Why It Matters
6
+
7
+ `#[repr(transparent)]` guarantees a newtype has the same memory layout as its inner type. This is essential for FFI where you need type safety in Rust but must match C ABI layouts. Without it, the compiler may add padding or change layout.
8
+
9
+ ## Bad
10
+
11
+ ```rust
12
+ // No layout guarantee - might not match inner type in FFI
13
+ struct Handle(u64);
14
+
15
+ // Passing to C code might fail
16
+ extern "C" {
17
+ fn process_handle(h: Handle); // May not work correctly
18
+ }
19
+
20
+ // Wrapping C type without layout guarantee
21
+ struct SafePointer(*mut c_void);
22
+ ```
23
+
24
+ ## Good
25
+
26
+ ```rust
27
+ // Guaranteed same layout as inner type
28
+ #[repr(transparent)]
29
+ struct Handle(u64);
30
+
31
+ // Safe for FFI
32
+ extern "C" {
33
+ fn process_handle(h: Handle); // Works - same layout as u64
34
+ }
35
+
36
+ // FFI pointer wrapper
37
+ #[repr(transparent)]
38
+ struct SafePointer(*mut c_void);
39
+
40
+ impl SafePointer {
41
+ // Safe Rust API around raw pointer
42
+ pub fn new(ptr: *mut c_void) -> Option<Self> {
43
+ if ptr.is_null() {
44
+ None
45
+ } else {
46
+ Some(SafePointer(ptr))
47
+ }
48
+ }
49
+ }
50
+ ```
51
+
52
+ ## What repr(transparent) Guarantees
53
+
54
+ ```rust
55
+ use std::mem::{size_of, align_of};
56
+
57
+ #[repr(transparent)]
58
+ struct Meters(f64);
59
+
60
+ // Same size
61
+ assert_eq!(size_of::<Meters>(), size_of::<f64>());
62
+
63
+ // Same alignment
64
+ assert_eq!(align_of::<Meters>(), align_of::<f64>());
65
+
66
+ // Same ABI - can pass where f64 expected
67
+ extern "C" fn measure(distance: Meters) { ... }
68
+ ```
69
+
70
+ ## With PhantomData
71
+
72
+ ```rust
73
+ use std::marker::PhantomData;
74
+
75
+ // PhantomData is zero-sized, doesn't affect layout
76
+ #[repr(transparent)]
77
+ struct TypedHandle<T> {
78
+ raw: u64,
79
+ _marker: PhantomData<T>, // Zero-sized, ignored for layout
80
+ }
81
+
82
+ // Still same layout as u64
83
+ assert_eq!(size_of::<TypedHandle<String>>(), size_of::<u64>());
84
+ ```
85
+
86
+ ## NonZero Wrappers
87
+
88
+ ```rust
89
+ use std::num::NonZeroU64;
90
+
91
+ #[repr(transparent)]
92
+ struct NonZeroHandle(NonZeroU64);
93
+
94
+ // Inherits null-pointer optimization
95
+ assert_eq!(size_of::<Option<NonZeroHandle>>(), size_of::<u64>());
96
+ ```
97
+
98
+ ## FFI Pattern
99
+
100
+ ```rust
101
+ mod ffi {
102
+ use std::os::raw::c_int;
103
+
104
+ #[repr(transparent)]
105
+ pub struct FileDescriptor(c_int);
106
+
107
+ extern "C" {
108
+ pub fn open(path: *const i8, flags: c_int) -> FileDescriptor;
109
+ pub fn close(fd: FileDescriptor) -> c_int;
110
+ pub fn read(fd: FileDescriptor, buf: *mut u8, len: usize) -> isize;
111
+ }
112
+ }
113
+
114
+ // Safe wrapper
115
+ pub struct File {
116
+ fd: ffi::FileDescriptor,
117
+ }
118
+
119
+ impl File {
120
+ pub fn open(path: &str) -> std::io::Result<Self> {
121
+ let c_path = std::ffi::CString::new(path)?;
122
+ let fd = unsafe { ffi::open(c_path.as_ptr(), 0) };
123
+ // ... error handling
124
+ Ok(File { fd })
125
+ }
126
+ }
127
+ ```
128
+
129
+ ## When to Use
130
+
131
+ | Scenario | Use `#[repr(transparent)]`? |
132
+ |----------|----------------------------|
133
+ | FFI newtype wrappers | Yes |
134
+ | Type-safe handles | Yes |
135
+ | NonZero optimization | Yes |
136
+ | Pure Rust newtypes | Optional (doesn't hurt) |
137
+ | Multi-field structs | N/A (only for single-field) |
138
+
139
+ ## See Also
140
+
141
+ - [type-newtype-ids](./type-newtype-ids.md) - Newtype pattern
142
+ - [type-phantom-marker](./type-phantom-marker.md) - PhantomData usage
143
+ - [api-newtype-safety](./api-newtype-safety.md) - Type-safe newtypes
@@ -0,0 +1,131 @@
1
+ # type-result-fallible
2
+
3
+ > Use `Result<T, E>` for operations that can fail
4
+
5
+ ## Why It Matters
6
+
7
+ `Result<T, E>` makes failure explicit in the type system. Callers must acknowledge and handle potential errors—they can't accidentally ignore failures. The `?` operator makes error propagation ergonomic while maintaining explicit error handling.
8
+
9
+ ## Bad
10
+
11
+ ```rust
12
+ // Returning Option loses error context
13
+ fn read_config(path: &str) -> Option<Config> {
14
+ let content = std::fs::read_to_string(path).ok()?; // Why did it fail?
15
+ toml::from_str(&content).ok() // Parse error lost
16
+ }
17
+
18
+ // Panicking on errors
19
+ fn read_config(path: &str) -> Config {
20
+ let content = std::fs::read_to_string(path).unwrap(); // Crashes
21
+ toml::from_str(&content).unwrap() // Crashes
22
+ }
23
+
24
+ // Sentinel values
25
+ fn divide(a: i32, b: i32) -> i32 {
26
+ if b == 0 { return -1; } // Magic value, easy to miss
27
+ a / b
28
+ }
29
+ ```
30
+
31
+ ## Good
32
+
33
+ ```rust
34
+ // Result with clear error type
35
+ fn read_config(path: &str) -> Result<Config, ConfigError> {
36
+ let content = std::fs::read_to_string(path)
37
+ .map_err(ConfigError::IoError)?;
38
+ toml::from_str(&content)
39
+ .map_err(ConfigError::ParseError)
40
+ }
41
+
42
+ fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {
43
+ if b == 0 {
44
+ return Err(DivisionError::DivideByZero);
45
+ }
46
+ Ok(a / b)
47
+ }
48
+
49
+ // Caller must handle
50
+ match divide(10, 0) {
51
+ Ok(result) => println!("Result: {}", result),
52
+ Err(e) => println!("Error: {}", e),
53
+ }
54
+ ```
55
+
56
+ ## The ? Operator
57
+
58
+ ```rust
59
+ fn process_file(path: &str) -> Result<ProcessedData, Error> {
60
+ let content = std::fs::read_to_string(path)?; // Propagates Err
61
+ let parsed: RawData = serde_json::from_str(&content)?;
62
+ let validated = validate(parsed)?;
63
+ let processed = transform(validated)?;
64
+ Ok(processed)
65
+ }
66
+
67
+ // Equivalent to:
68
+ fn process_file(path: &str) -> Result<ProcessedData, Error> {
69
+ let content = match std::fs::read_to_string(path) {
70
+ Ok(c) => c,
71
+ Err(e) => return Err(e.into()),
72
+ };
73
+ // ... etc
74
+ }
75
+ ```
76
+
77
+ ## Result Combinators
78
+
79
+ ```rust
80
+ let result: Result<i32, Error> = Ok(42);
81
+
82
+ // map: transform success value
83
+ let doubled = result.map(|n| n * 2); // Ok(84)
84
+
85
+ // map_err: transform error
86
+ let with_context = result.map_err(|e| format!("Failed: {}", e));
87
+
88
+ // and_then: chain fallible operations
89
+ let processed = result.and_then(|n| {
90
+ if n > 0 { Ok(n * 2) } else { Err(Error::Negative) }
91
+ });
92
+
93
+ // unwrap_or: provide default on error
94
+ let value = result.unwrap_or(0);
95
+
96
+ // ok(): convert to Option, discarding error
97
+ let maybe_value: Option<i32> = result.ok();
98
+ ```
99
+
100
+ ## Defining Error Types
101
+
102
+ ```rust
103
+ use thiserror::Error;
104
+
105
+ #[derive(Error, Debug)]
106
+ pub enum ConfigError {
107
+ #[error("failed to read file: {0}")]
108
+ Io(#[from] std::io::Error),
109
+
110
+ #[error("failed to parse config: {0}")]
111
+ Parse(#[from] toml::de::Error),
112
+
113
+ #[error("missing required field: {0}")]
114
+ MissingField(String),
115
+ }
116
+
117
+ fn load_config(path: &str) -> Result<Config, ConfigError> {
118
+ let content = std::fs::read_to_string(path)?; // Io error
119
+ let config: Config = toml::from_str(&content)?; // Parse error
120
+ if config.name.is_empty() {
121
+ return Err(ConfigError::MissingField("name".into()));
122
+ }
123
+ Ok(config)
124
+ }
125
+ ```
126
+
127
+ ## See Also
128
+
129
+ - [err-thiserror-lib](./err-thiserror-lib.md) - Defining error types
130
+ - [err-question-mark](./err-question-mark.md) - Using ? operator
131
+ - [type-option-nullable](./type-option-nullable.md) - Option vs Result
@@ -167,6 +167,23 @@ You MUST complete each phase before proceeding to the next.
167
167
  - Ask for help
168
168
  - Research more
169
169
 
170
+ ### Confirmation Gate: Present Analysis Before Fixing
171
+
172
+ <HARD-GATE>
173
+ You MUST present your complete analysis to the user and get explicit confirmation
174
+ BEFORE proceeding to Phase 4 (Implementation).
175
+
176
+ **Present a summary containing:**
177
+ 1. **Root Cause** — from Phase 1
178
+ 2. **Pattern Analysis** — key differences found in Phase 2
179
+ 3. **Hypothesis** — your confirmed theory from Phase 3
180
+ 4. **Proposed Fix** — what you plan to change (files, functions, approach)
181
+
182
+ Then ask: "Bạn đồng ý với phân tích và hướng fix này không?"
183
+
184
+ Wait for user confirmation. Do NOT proceed to Phase 4 until confirmed.
185
+ </HARD-GATE>
186
+
170
187
  ### Phase 4: Implementation
171
188
 
172
189
  **Fix the root cause, not the symptom:**