agy-superpowers 5.2.1 → 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.
- package/README.md +47 -150
- package/package.json +1 -1
- package/template/agent/patches/skills-patches.md +23 -0
- package/template/agent/rules/scratch-scripts.md +37 -0
- package/template/agent/rules/superpowers.md +6 -50
- package/template/agent/skills/brainstorming/SKILL.md +4 -3
- package/template/agent/skills/brainstorming/visual-companion.md +2 -3
- package/template/agent/skills/finishing-a-development-branch/SKILL.md +11 -16
- package/template/agent/skills/subagent-driven-development/SKILL.md +16 -0
- package/template/agent/skills/subagent-driven-development/implementer-prompt.md +4 -3
- package/template/agent/skills/using-git-worktrees/SKILL.md +3 -2
- package/template/agent/skills/using-superpowers/SKILL.md +8 -6
- package/template/agent/skills/using-superpowers/references/copilot-tools.md +52 -0
- package/template/agent/skills/writing-plans/SKILL.md +5 -3
- package/template/agent/skills/writing-skills/SKILL.md +1 -1
- package/template/agent/superpowers-version.json +2 -2
- package/template/agent/tmp/agent-config-backup.yml +9 -0
- package/template/agent/skills/ai-integrated-product/SKILL.md +0 -57
- package/template/agent/skills/analytics-setup/SKILL.md +0 -51
- package/template/agent/skills/api-design/SKILL.md +0 -193
- package/template/agent/skills/app-store-optimizer/SKILL.md +0 -127
- package/template/agent/skills/auth-and-identity/SKILL.md +0 -167
- package/template/agent/skills/backend-developer/SKILL.md +0 -148
- package/template/agent/skills/bootstrapper-finance/SKILL.md +0 -55
- package/template/agent/skills/chrome-extension-developer/SKILL.md +0 -53
- package/template/agent/skills/community-manager/SKILL.md +0 -115
- package/template/agent/skills/content-marketer/SKILL.md +0 -111
- package/template/agent/skills/conversion-optimizer/SKILL.md +0 -142
- package/template/agent/skills/cto-architect/SKILL.md +0 -133
- package/template/agent/skills/customer-success-manager/SKILL.md +0 -126
- package/template/agent/skills/data-analyst/SKILL.md +0 -147
- package/template/agent/skills/devops-engineer/SKILL.md +0 -117
- package/template/agent/skills/email-infrastructure/SKILL.md +0 -164
- package/template/agent/skills/game-design/SKILL.md +0 -194
- package/template/agent/skills/game-developer/SKILL.md +0 -175
- package/template/agent/skills/growth-hacker/SKILL.md +0 -122
- package/template/agent/skills/idea-validator/SKILL.md +0 -55
- package/template/agent/skills/indie-legal/SKILL.md +0 -53
- package/template/agent/skills/influencer-marketer/SKILL.md +0 -141
- package/template/agent/skills/landing-page-builder/SKILL.md +0 -59
- package/template/agent/skills/launch-strategist/SKILL.md +0 -62
- package/template/agent/skills/market-researcher/SKILL.md +0 -53
- package/template/agent/skills/micro-saas-builder/SKILL.md +0 -56
- package/template/agent/skills/monetization-strategist/SKILL.md +0 -119
- package/template/agent/skills/paid-acquisition-specialist/SKILL.md +0 -119
- package/template/agent/skills/pricing-psychologist/SKILL.md +0 -58
- package/template/agent/skills/real-time-features/SKILL.md +0 -194
- package/template/agent/skills/retention-specialist/SKILL.md +0 -123
- package/template/agent/skills/rust-developer/SKILL.md +0 -281
- package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +0 -231
- package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +0 -124
- package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +0 -131
- package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +0 -132
- package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +0 -95
- package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +0 -141
- package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +0 -125
- package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +0 -127
- package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +0 -120
- package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +0 -131
- package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +0 -156
- package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +0 -122
- package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +0 -167
- package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +0 -134
- package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +0 -143
- package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +0 -121
- package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +0 -143
- package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +0 -187
- package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +0 -165
- package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +0 -177
- package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +0 -163
- package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +0 -146
- package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +0 -160
- package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +0 -125
- package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +0 -162
- package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +0 -177
- package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +0 -184
- package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +0 -168
- package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +0 -182
- package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +0 -199
- package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +0 -175
- package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +0 -185
- package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +0 -203
- package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +0 -171
- package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +0 -158
- package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +0 -195
- package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +0 -171
- package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +0 -156
- package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +0 -191
- package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +0 -198
- package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +0 -167
- package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +0 -169
- package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +0 -172
- package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +0 -189
- package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +0 -113
- package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +0 -147
- package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +0 -122
- package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +0 -161
- package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +0 -149
- package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +0 -138
- package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +0 -169
- package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +0 -116
- package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +0 -128
- package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +0 -136
- package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +0 -131
- package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +0 -179
- package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +0 -144
- package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +0 -152
- package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +0 -145
- package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +0 -133
- package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +0 -152
- package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +0 -124
- package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +0 -115
- package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +0 -151
- package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +0 -130
- package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +0 -155
- package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +0 -171
- package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +0 -138
- package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +0 -107
- package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +0 -118
- package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +0 -157
- package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +0 -133
- package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +0 -131
- package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +0 -136
- package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +0 -135
- package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +0 -122
- package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +0 -172
- package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +0 -168
- package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +0 -168
- package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +0 -147
- package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +0 -158
- package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +0 -139
- package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +0 -147
- package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +0 -149
- package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +0 -174
- package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +0 -159
- package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +0 -138
- package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +0 -156
- package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +0 -172
- package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +0 -164
- package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +0 -99
- package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +0 -104
- package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +0 -94
- package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +0 -78
- package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +0 -76
- package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +0 -123
- package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +0 -127
- package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +0 -129
- package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +0 -131
- package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +0 -86
- package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +0 -118
- package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +0 -92
- package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +0 -65
- package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +0 -101
- package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +0 -161
- package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +0 -187
- package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +0 -152
- package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +0 -141
- package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +0 -181
- package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +0 -160
- package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +0 -171
- package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +0 -130
- package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +0 -167
- package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +0 -144
- package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +0 -141
- package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +0 -95
- package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +0 -135
- package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +0 -124
- package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +0 -135
- package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +0 -134
- package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +0 -134
- package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +0 -105
- package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +0 -65
- package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +0 -97
- package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +0 -122
- package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +0 -119
- package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +0 -153
- package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +0 -136
- package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +0 -133
- package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +0 -120
- package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +0 -137
- package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +0 -134
- package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +0 -150
- package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +0 -123
- package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +0 -113
- package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +0 -175
- package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +0 -149
- package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +0 -133
- package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +0 -148
- package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +0 -130
- package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +0 -120
- package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +0 -155
- package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +0 -139
- package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +0 -135
- package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +0 -162
- package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +0 -186
- package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +0 -162
- package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +0 -160
- package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +0 -151
- package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +0 -171
- package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +0 -168
- package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +0 -151
- package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +0 -144
- package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +0 -189
- package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +0 -226
- package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +0 -161
- package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +0 -130
- package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +0 -127
- package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +0 -146
- package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +0 -160
- package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +0 -159
- package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +0 -144
- package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +0 -137
- package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +0 -188
- package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +0 -143
- package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +0 -131
- package/template/agent/skills/saas-architect/SKILL.md +0 -139
- package/template/agent/skills/security-engineer/SKILL.md +0 -133
- package/template/agent/skills/seo-specialist/SKILL.md +0 -130
- package/template/agent/skills/solo-founder-ops/SKILL.md +0 -56
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
# err-result-over-panic
|
|
2
|
-
|
|
3
|
-
> Return `Result<T, E>` instead of panicking for recoverable errors
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Panics unwind the stack and crash the thread (or program). They're unrecoverable from the caller's perspective. `Result<T, E>` gives callers the ability to decide how to handle errors—retry, fallback, propagate, or log. Libraries should almost never panic; applications should minimize panics to truly unrecoverable situations.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
fn parse_config(path: &str) -> Config {
|
|
13
|
-
let content = std::fs::read_to_string(path)
|
|
14
|
-
.expect("Failed to read config"); // Crashes on missing file
|
|
15
|
-
|
|
16
|
-
serde_json::from_str(&content)
|
|
17
|
-
.expect("Invalid config format") // Crashes on bad JSON
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
fn divide(a: i32, b: i32) -> i32 {
|
|
21
|
-
if b == 0 {
|
|
22
|
-
panic!("Division by zero!"); // Crashes the program
|
|
23
|
-
}
|
|
24
|
-
a / b
|
|
25
|
-
}
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Caller has no chance to recover or provide a fallback.
|
|
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: {0}")]
|
|
38
|
-
Io(#[from] std::io::Error),
|
|
39
|
-
#[error("Invalid config format: {0}")]
|
|
40
|
-
Parse(#[from] serde_json::Error),
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
fn parse_config(path: &str) -> Result<Config, ConfigError> {
|
|
44
|
-
let content = std::fs::read_to_string(path)?;
|
|
45
|
-
let config = serde_json::from_str(&content)?;
|
|
46
|
-
Ok(config)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
fn divide(a: i32, b: i32) -> Result<i32, &'static str> {
|
|
50
|
-
if b == 0 {
|
|
51
|
-
return Err("Division by zero");
|
|
52
|
-
}
|
|
53
|
-
Ok(a / b)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Caller decides how to handle
|
|
57
|
-
match parse_config("app.json") {
|
|
58
|
-
Ok(config) => run_app(config),
|
|
59
|
-
Err(e) => {
|
|
60
|
-
eprintln!("Using default config: {}", e);
|
|
61
|
-
run_app(Config::default())
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
## When Panic IS Appropriate
|
|
67
|
-
|
|
68
|
-
```rust
|
|
69
|
-
// 1. Bug in the program (invariant violation)
|
|
70
|
-
fn get_cached_value(&self, key: &str) -> &Value {
|
|
71
|
-
self.cache.get(key).expect("BUG: key was verified to exist")
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// 2. Setup/initialization that can't reasonably fail
|
|
75
|
-
fn main() {
|
|
76
|
-
let config = Config::load().expect("Failed to load required config");
|
|
77
|
-
// Can't run without config, panic is reasonable
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// 3. Tests
|
|
81
|
-
#[test]
|
|
82
|
-
fn test_parse() {
|
|
83
|
-
let result = parse("valid input").unwrap(); // unwrap OK in tests
|
|
84
|
-
assert_eq!(result, expected);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// 4. Examples and prototypes
|
|
88
|
-
fn main() {
|
|
89
|
-
// Quick prototype, panic is fine
|
|
90
|
-
let data = fetch_data().unwrap();
|
|
91
|
-
}
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## Panic vs Result Decision Guide
|
|
95
|
-
|
|
96
|
-
| Situation | Use |
|
|
97
|
-
|-----------|-----|
|
|
98
|
-
| File not found | `Result` |
|
|
99
|
-
| Network error | `Result` |
|
|
100
|
-
| Invalid user input | `Result` |
|
|
101
|
-
| Parse error | `Result` |
|
|
102
|
-
| Index out of bounds (from user data) | `Result` |
|
|
103
|
-
| Index out of bounds (internal bug) | Panic |
|
|
104
|
-
| Violated internal invariant | Panic |
|
|
105
|
-
| Unimplemented code path | Panic (`unimplemented!()`) |
|
|
106
|
-
| Impossible state reached | Panic (`unreachable!()`) |
|
|
107
|
-
|
|
108
|
-
## Library vs Application
|
|
109
|
-
|
|
110
|
-
```rust
|
|
111
|
-
// Library: NEVER panic on user input
|
|
112
|
-
pub fn parse(input: &str) -> Result<Ast, ParseError> {
|
|
113
|
-
// Always return Result
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Application: Can panic at top level for critical failures
|
|
117
|
-
fn main() {
|
|
118
|
-
if let Err(e) = run() {
|
|
119
|
-
eprintln!("Fatal error: {}", e);
|
|
120
|
-
std::process::exit(1);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
## See Also
|
|
126
|
-
|
|
127
|
-
- [err-thiserror-lib](./err-thiserror-lib.md) - Define error types for libraries
|
|
128
|
-
- [err-anyhow-app](./err-anyhow-app.md) - Ergonomic errors for applications
|
|
129
|
-
- [err-no-unwrap-prod](./err-no-unwrap-prod.md) - Avoid unwrap in production code
|
|
130
|
-
- [anti-unwrap-abuse](./anti-unwrap-abuse.md) - When unwrap is acceptable
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
# err-source-chain
|
|
2
|
-
|
|
3
|
-
> Preserve error chains with `#[source]` or `source()` method
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Errors often have underlying causes. Preserving the error chain (via `source()` method) allows logging frameworks and error reporters to show the full context: "config parse failed → JSON syntax error at line 5 → unexpected token". Without chaining, you lose valuable debugging information.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
#[derive(Debug)]
|
|
13
|
-
enum ConfigError {
|
|
14
|
-
ParseFailed(String), // Lost the original serde_json::Error
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
fn load_config(path: &str) -> Result<Config, ConfigError> {
|
|
18
|
-
let content = std::fs::read_to_string(path)
|
|
19
|
-
.map_err(|e| ConfigError::ParseFailed(e.to_string()))?; // Chain lost!
|
|
20
|
-
|
|
21
|
-
serde_json::from_str(&content)
|
|
22
|
-
.map_err(|e| ConfigError::ParseFailed(e.to_string()))? // No source
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Error output: "Parse failed: invalid type: ..."
|
|
26
|
-
// Missing: which file? what line? what was the parent error?
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Good
|
|
30
|
-
|
|
31
|
-
```rust
|
|
32
|
-
use thiserror::Error;
|
|
33
|
-
|
|
34
|
-
#[derive(Error, Debug)]
|
|
35
|
-
enum ConfigError {
|
|
36
|
-
#[error("Failed to read config file '{path}'")]
|
|
37
|
-
ReadFailed {
|
|
38
|
-
path: String,
|
|
39
|
-
#[source] // Preserves the error chain
|
|
40
|
-
source: std::io::Error,
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
#[error("Failed to parse config file '{path}'")]
|
|
44
|
-
ParseFailed {
|
|
45
|
-
path: String,
|
|
46
|
-
#[source] // Original parse error preserved
|
|
47
|
-
source: serde_json::Error,
|
|
48
|
-
},
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
fn load_config(path: &str) -> Result<Config, ConfigError> {
|
|
52
|
-
let content = std::fs::read_to_string(path)
|
|
53
|
-
.map_err(|source| ConfigError::ReadFailed {
|
|
54
|
-
path: path.to_string(),
|
|
55
|
-
source, // Chain preserved
|
|
56
|
-
})?;
|
|
57
|
-
|
|
58
|
-
serde_json::from_str(&content)
|
|
59
|
-
.map_err(|source| ConfigError::ParseFailed {
|
|
60
|
-
path: path.to_string(),
|
|
61
|
-
source,
|
|
62
|
-
})
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
## Manual source() Implementation
|
|
67
|
-
|
|
68
|
-
```rust
|
|
69
|
-
use std::error::Error;
|
|
70
|
-
|
|
71
|
-
#[derive(Debug)]
|
|
72
|
-
struct MyError {
|
|
73
|
-
message: String,
|
|
74
|
-
source: Option<Box<dyn Error + Send + Sync>>,
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
impl std::fmt::Display for MyError {
|
|
78
|
-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
79
|
-
write!(f, "{}", self.message)
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
impl Error for MyError {
|
|
84
|
-
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
|
85
|
-
self.source.as_ref().map(|e| e.as_ref() as &(dyn Error + 'static))
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
## Walking the Error Chain
|
|
91
|
-
|
|
92
|
-
```rust
|
|
93
|
-
fn print_error_chain(error: &dyn std::error::Error) {
|
|
94
|
-
eprintln!("Error: {}", error);
|
|
95
|
-
|
|
96
|
-
let mut source = error.source();
|
|
97
|
-
while let Some(err) = source {
|
|
98
|
-
eprintln!("Caused by: {}", err);
|
|
99
|
-
source = err.source();
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// With anyhow, use {:?} for full chain
|
|
104
|
-
let result: anyhow::Result<()> = do_something();
|
|
105
|
-
if let Err(e) = result {
|
|
106
|
-
eprintln!("{:?}", e); // Prints full chain with backtraces
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## anyhow Context
|
|
111
|
-
|
|
112
|
-
```rust
|
|
113
|
-
use anyhow::{Context, Result};
|
|
114
|
-
|
|
115
|
-
fn load_config(path: &str) -> Result<Config> {
|
|
116
|
-
let content = std::fs::read_to_string(path)
|
|
117
|
-
.with_context(|| format!("Failed to read '{}'", path))?;
|
|
118
|
-
|
|
119
|
-
let config: Config = serde_json::from_str(&content)
|
|
120
|
-
.with_context(|| format!("Failed to parse '{}'", path))?;
|
|
121
|
-
|
|
122
|
-
Ok(config)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Output:
|
|
126
|
-
// Error: Failed to parse 'config.json'
|
|
127
|
-
// Caused by: expected `:` at line 5 column 10
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
## #[from] vs #[source]
|
|
131
|
-
|
|
132
|
-
```rust
|
|
133
|
-
use thiserror::Error;
|
|
134
|
-
|
|
135
|
-
#[derive(Error, Debug)]
|
|
136
|
-
enum MyError {
|
|
137
|
-
// #[from] = implements From + sets source
|
|
138
|
-
#[error("IO error")]
|
|
139
|
-
Io(#[from] std::io::Error),
|
|
140
|
-
|
|
141
|
-
// #[source] = only sets source (no From impl)
|
|
142
|
-
#[error("Parse error in file '{path}'")]
|
|
143
|
-
Parse {
|
|
144
|
-
path: String,
|
|
145
|
-
#[source]
|
|
146
|
-
source: serde_json::Error,
|
|
147
|
-
},
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
## See Also
|
|
152
|
-
|
|
153
|
-
- [err-thiserror-lib](./err-thiserror-lib.md) - thiserror for error definitions
|
|
154
|
-
- [err-context-chain](./err-context-chain.md) - Adding context to errors
|
|
155
|
-
- [err-from-impl](./err-from-impl.md) - From implementations for ?
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
# err-thiserror-lib
|
|
2
|
-
|
|
3
|
-
> Use `thiserror` for library error types
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Libraries should expose typed, matchable errors so users can handle specific error conditions. `thiserror` generates `Error` trait implementations with minimal boilerplate, creating ergonomic error types that are easy to match against.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
// String errors - not matchable
|
|
13
|
-
fn parse(input: &str) -> Result<Data, String> {
|
|
14
|
-
Err("parse error".to_string())
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Box<dyn Error> - not matchable
|
|
18
|
-
fn load(path: &Path) -> Result<Data, Box<dyn std::error::Error>> {
|
|
19
|
-
Err(Box::new(std::io::Error::new(std::io::ErrorKind::NotFound, "file not found")))
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Manual implementation - verbose
|
|
23
|
-
#[derive(Debug)]
|
|
24
|
-
enum MyError {
|
|
25
|
-
Io(std::io::Error),
|
|
26
|
-
Parse(String),
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
impl std::fmt::Display for MyError {
|
|
30
|
-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
31
|
-
match self {
|
|
32
|
-
MyError::Io(e) => write!(f, "io error: {}", e),
|
|
33
|
-
MyError::Parse(s) => write!(f, "parse error: {}", s),
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
impl std::error::Error for MyError {
|
|
39
|
-
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
|
40
|
-
match self {
|
|
41
|
-
MyError::Io(e) => Some(e),
|
|
42
|
-
MyError::Parse(_) => None,
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Good
|
|
49
|
-
|
|
50
|
-
```rust
|
|
51
|
-
use thiserror::Error;
|
|
52
|
-
|
|
53
|
-
#[derive(Error, Debug)]
|
|
54
|
-
pub enum ParseError {
|
|
55
|
-
#[error("invalid syntax at line {line}: {message}")]
|
|
56
|
-
Syntax { line: usize, message: String },
|
|
57
|
-
|
|
58
|
-
#[error("unexpected end of file")]
|
|
59
|
-
UnexpectedEof,
|
|
60
|
-
|
|
61
|
-
#[error("invalid utf-8 encoding")]
|
|
62
|
-
Utf8(#[from] std::str::Utf8Error),
|
|
63
|
-
|
|
64
|
-
#[error("io error reading input")]
|
|
65
|
-
Io(#[from] std::io::Error),
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Usage
|
|
69
|
-
fn parse(input: &str) -> Result<Ast, ParseError> {
|
|
70
|
-
if input.is_empty() {
|
|
71
|
-
return Err(ParseError::UnexpectedEof);
|
|
72
|
-
}
|
|
73
|
-
// ...
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Users can match specific errors
|
|
77
|
-
match parse(input) {
|
|
78
|
-
Ok(ast) => process(ast),
|
|
79
|
-
Err(ParseError::Syntax { line, message }) => {
|
|
80
|
-
eprintln!("Syntax error on line {}: {}", line, message);
|
|
81
|
-
}
|
|
82
|
-
Err(ParseError::UnexpectedEof) => {
|
|
83
|
-
eprintln!("File ended unexpectedly");
|
|
84
|
-
}
|
|
85
|
-
Err(e) => eprintln!("Error: {}", e),
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
## Key Attributes
|
|
90
|
-
|
|
91
|
-
```rust
|
|
92
|
-
use thiserror::Error;
|
|
93
|
-
|
|
94
|
-
#[derive(Error, Debug)]
|
|
95
|
-
pub enum MyError {
|
|
96
|
-
// Simple message
|
|
97
|
-
#[error("operation failed")]
|
|
98
|
-
Failed,
|
|
99
|
-
|
|
100
|
-
// Interpolated fields
|
|
101
|
-
#[error("invalid value: {0}")]
|
|
102
|
-
InvalidValue(String),
|
|
103
|
-
|
|
104
|
-
// Named fields
|
|
105
|
-
#[error("connection to {host}:{port} failed")]
|
|
106
|
-
Connection { host: String, port: u16 },
|
|
107
|
-
|
|
108
|
-
// Automatic From impl with #[from]
|
|
109
|
-
#[error("database error")]
|
|
110
|
-
Database(#[from] sqlx::Error),
|
|
111
|
-
|
|
112
|
-
// Source without From (manual conversion needed)
|
|
113
|
-
#[error("validation failed")]
|
|
114
|
-
Validation {
|
|
115
|
-
#[source]
|
|
116
|
-
cause: ValidationError,
|
|
117
|
-
field: String,
|
|
118
|
-
},
|
|
119
|
-
|
|
120
|
-
// Transparent - delegates Display and source to inner
|
|
121
|
-
#[error(transparent)]
|
|
122
|
-
Other(#[from] anyhow::Error),
|
|
123
|
-
}
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
## Error Chaining
|
|
127
|
-
|
|
128
|
-
```rust
|
|
129
|
-
use thiserror::Error;
|
|
130
|
-
|
|
131
|
-
#[derive(Error, Debug)]
|
|
132
|
-
pub enum ConfigError {
|
|
133
|
-
#[error("failed to read config file")]
|
|
134
|
-
Read(#[source] std::io::Error),
|
|
135
|
-
|
|
136
|
-
#[error("failed to parse config")]
|
|
137
|
-
Parse(#[source] toml::de::Error),
|
|
138
|
-
|
|
139
|
-
#[error("invalid config value for '{key}'")]
|
|
140
|
-
InvalidValue {
|
|
141
|
-
key: String,
|
|
142
|
-
#[source]
|
|
143
|
-
cause: ValueError,
|
|
144
|
-
},
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Error chain is preserved
|
|
148
|
-
fn load_config(path: &Path) -> Result<Config, ConfigError> {
|
|
149
|
-
let content = std::fs::read_to_string(path)
|
|
150
|
-
.map_err(ConfigError::Read)?;
|
|
151
|
-
|
|
152
|
-
let config: Config = toml::from_str(&content)
|
|
153
|
-
.map_err(ConfigError::Parse)?;
|
|
154
|
-
|
|
155
|
-
Ok(config)
|
|
156
|
-
}
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
## Library vs Application
|
|
160
|
-
|
|
161
|
-
| Context | Crate | Why |
|
|
162
|
-
|---------|-------|-----|
|
|
163
|
-
| Library | `thiserror` | Typed errors users can match |
|
|
164
|
-
| Application | `anyhow` | Easy error handling with context |
|
|
165
|
-
| Both | `thiserror` for public API, `anyhow` internally | Best of both |
|
|
166
|
-
|
|
167
|
-
## See Also
|
|
168
|
-
|
|
169
|
-
- [err-anyhow-app](err-anyhow-app.md) - Use anyhow for applications
|
|
170
|
-
- [err-from-impl](err-from-impl.md) - Use #[from] for automatic conversion
|
|
171
|
-
- [err-source-chain](err-source-chain.md) - Use #[source] to chain errors
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
# lint-cargo-metadata
|
|
2
|
-
|
|
3
|
-
> Enable clippy::cargo for published crates
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
The `clippy::cargo` lint group checks Cargo.toml for issues that affect publishing and dependency management. For crates intended for crates.io, these checks help ensure a professional, well-configured package.
|
|
8
|
-
|
|
9
|
-
## Configuration
|
|
10
|
-
|
|
11
|
-
```toml
|
|
12
|
-
# Cargo.toml
|
|
13
|
-
[lints.clippy]
|
|
14
|
-
cargo = "warn"
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Or in code:
|
|
18
|
-
|
|
19
|
-
```rust
|
|
20
|
-
#![warn(clippy::cargo)]
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## What It Catches
|
|
24
|
-
|
|
25
|
-
### Missing Metadata
|
|
26
|
-
|
|
27
|
-
```toml
|
|
28
|
-
# WARN: missing package.description
|
|
29
|
-
# WARN: missing package.license or package.license-file
|
|
30
|
-
# WARN: missing package.repository
|
|
31
|
-
[package]
|
|
32
|
-
name = "my-crate"
|
|
33
|
-
version = "0.1.0"
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### Dependency Issues
|
|
37
|
-
|
|
38
|
-
```toml
|
|
39
|
-
# WARN: feature used but not defined
|
|
40
|
-
# WARN: dependency version not specified
|
|
41
|
-
[dependencies]
|
|
42
|
-
serde = "*" # Bad: any version
|
|
43
|
-
tokio = { git = "..." } # WARN for published crates
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### Feature Issues
|
|
47
|
-
|
|
48
|
-
```toml
|
|
49
|
-
# WARN: negative_feature_names
|
|
50
|
-
[features]
|
|
51
|
-
no-std = [] # Should be: std = [] (opt-out vs opt-in)
|
|
52
|
-
|
|
53
|
-
# WARN: redundant_feature_names
|
|
54
|
-
[features]
|
|
55
|
-
default = ["feature-a"]
|
|
56
|
-
feature-a = [] # Feature name matches crate name
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## Notable Lints
|
|
60
|
-
|
|
61
|
-
| Lint | Issue |
|
|
62
|
-
|------|-------|
|
|
63
|
-
| `cargo_common_metadata` | Missing description/license/repository |
|
|
64
|
-
| `multiple_crate_versions` | Same crate at different versions |
|
|
65
|
-
| `negative_feature_names` | Features like `no-std` instead of `std` |
|
|
66
|
-
| `redundant_feature_names` | Feature same as crate name |
|
|
67
|
-
| `wildcard_dependencies` | Using `*` for version |
|
|
68
|
-
|
|
69
|
-
## Complete Cargo.toml
|
|
70
|
-
|
|
71
|
-
```toml
|
|
72
|
-
[package]
|
|
73
|
-
name = "my-crate"
|
|
74
|
-
version = "0.1.0"
|
|
75
|
-
edition = "2021"
|
|
76
|
-
rust-version = "1.70"
|
|
77
|
-
|
|
78
|
-
# Required for cargo lint satisfaction
|
|
79
|
-
description = "A short description of what this crate does"
|
|
80
|
-
license = "MIT OR Apache-2.0"
|
|
81
|
-
repository = "https://github.com/user/my-crate"
|
|
82
|
-
|
|
83
|
-
# Recommended
|
|
84
|
-
documentation = "https://docs.rs/my-crate"
|
|
85
|
-
readme = "README.md"
|
|
86
|
-
keywords = ["keyword1", "keyword2"]
|
|
87
|
-
categories = ["category-slug"]
|
|
88
|
-
|
|
89
|
-
[dependencies]
|
|
90
|
-
# Specific versions, not wildcards
|
|
91
|
-
serde = "1.0"
|
|
92
|
-
tokio = { version = "1.0", features = ["full"] }
|
|
93
|
-
|
|
94
|
-
[features]
|
|
95
|
-
default = ["std"]
|
|
96
|
-
std = [] # Opt-out, not no-std opt-in
|
|
97
|
-
|
|
98
|
-
[lints.clippy]
|
|
99
|
-
cargo = "warn"
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Multiple Crate Versions
|
|
103
|
-
|
|
104
|
-
```
|
|
105
|
-
# WARN: multiple versions of `syn` in dependency tree
|
|
106
|
-
# syn v1.0.109
|
|
107
|
-
# syn v2.0.48
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
Fix by updating dependencies or using `[patch]`:
|
|
111
|
-
|
|
112
|
-
```toml
|
|
113
|
-
[patch.crates-io]
|
|
114
|
-
old-dep = { git = "...", branch = "syn-2" }
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
## When to Disable
|
|
118
|
-
|
|
119
|
-
For internal/unpublished crates:
|
|
120
|
-
|
|
121
|
-
```toml
|
|
122
|
-
[lints.clippy]
|
|
123
|
-
cargo = "allow" # Not publishing, metadata not needed
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
Or selectively:
|
|
127
|
-
|
|
128
|
-
```toml
|
|
129
|
-
[lints.clippy]
|
|
130
|
-
cargo = "warn"
|
|
131
|
-
multiple_crate_versions = "allow" # Acceptable in this project
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## See Also
|
|
135
|
-
|
|
136
|
-
- [doc-cargo-metadata](./doc-cargo-metadata.md) - Cargo.toml metadata
|
|
137
|
-
- [proj-workspace-deps](./proj-workspace-deps.md) - Workspace dependencies
|
|
138
|
-
- [lint-deny-correctness](./lint-deny-correctness.md) - Correctness lints
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
# lint-deny-correctness
|
|
2
|
-
|
|
3
|
-
> `#![deny(clippy::correctness)]`
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Clippy's correctness lints catch code that is outright wrong - logic errors, undefined behavior, or code that doesn't do what you think. These should always be errors, not warnings.
|
|
8
|
-
|
|
9
|
-
## Setup
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
// At the top of lib.rs or main.rs
|
|
13
|
-
#![deny(clippy::correctness)]
|
|
14
|
-
|
|
15
|
-
// Or in Cargo.toml for workspace-wide
|
|
16
|
-
[lints.clippy]
|
|
17
|
-
correctness = "deny"
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## What It Catches
|
|
21
|
-
|
|
22
|
-
```rust
|
|
23
|
-
// Infinite loop (iter::repeat without take)
|
|
24
|
-
for x in std::iter::repeat(1) { // ERROR: infinite iterator
|
|
25
|
-
println!("{}", x);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Comparison to NaN (always false)
|
|
29
|
-
if x == f64::NAN { // ERROR: NaN != NaN always
|
|
30
|
-
// This never executes
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Use after free patterns
|
|
34
|
-
let r;
|
|
35
|
-
{
|
|
36
|
-
let x = 5;
|
|
37
|
-
r = &x; // ERROR: x dropped here
|
|
38
|
-
}
|
|
39
|
-
println!("{}", r);
|
|
40
|
-
|
|
41
|
-
// Wrong equality check
|
|
42
|
-
if x = 5 { // ERROR: assignment in condition (should be ==)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Useless comparisons
|
|
46
|
-
if x >= 0 && x < 0 { // ERROR: impossible condition
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Important Correctness Lints
|
|
51
|
-
|
|
52
|
-
```rust
|
|
53
|
-
// approx_constant - using imprecise PI, E values
|
|
54
|
-
let pi = 3.14; // Use std::f64::consts::PI
|
|
55
|
-
|
|
56
|
-
// invalid_regex - regex that won't compile
|
|
57
|
-
let re = Regex::new("["); // Invalid regex
|
|
58
|
-
|
|
59
|
-
// iter_next_loop - using .next() in for loop incorrectly
|
|
60
|
-
for x in iter.next() { // Should be: for x in iter
|
|
61
|
-
|
|
62
|
-
// never_loop - loop that never actually loops
|
|
63
|
-
loop {
|
|
64
|
-
break; // Always breaks immediately
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// nonsensical_open_options - impossible file options
|
|
68
|
-
File::options().read(false).write(false).open("f");
|
|
69
|
-
|
|
70
|
-
// unit_cmp - comparing unit type ()
|
|
71
|
-
if foo() == bar() { } // Both return (), always true
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Full Recommended Lints
|
|
75
|
-
|
|
76
|
-
```rust
|
|
77
|
-
#![deny(clippy::correctness)]
|
|
78
|
-
#![warn(clippy::suspicious)]
|
|
79
|
-
#![warn(clippy::style)]
|
|
80
|
-
#![warn(clippy::complexity)]
|
|
81
|
-
#![warn(clippy::perf)]
|
|
82
|
-
|
|
83
|
-
// For published crates
|
|
84
|
-
#![warn(missing_docs)]
|
|
85
|
-
#![warn(clippy::cargo)]
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Running Clippy
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
# Basic check
|
|
92
|
-
cargo clippy
|
|
93
|
-
|
|
94
|
-
# With all warnings as errors
|
|
95
|
-
cargo clippy -- -D warnings
|
|
96
|
-
|
|
97
|
-
# Check specific lint category
|
|
98
|
-
cargo clippy -- -W clippy::correctness
|
|
99
|
-
|
|
100
|
-
# In CI (fail on warnings)
|
|
101
|
-
cargo clippy -- -D warnings -D clippy::correctness
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
## See Also
|
|
105
|
-
|
|
106
|
-
- [lint-warn-suspicious](lint-warn-suspicious.md) - Warn on suspicious code
|
|
107
|
-
- [lint-warn-perf](lint-warn-perf.md) - Warn on performance issues
|