clippy: enable panic-discipline lints
Assisted-by: Claude Opus 5 via Claude Code
diff --git a/.clippy.toml b/.clippy.toml
index 152ece5..ff12a93 100644
--- a/.clippy.toml
+++ b/.clippy.toml
@@ -18,9 +18,15 @@ disallowed-methods = [
{ path = "std::fs::read_dir", reason = "use fs_err::read_dir" },
{ path = "std::fs::read_link", reason = "use fs_err::read_link" },
{ path = "std::fs::set_permissions", reason = "use fs_err::set_permissions" },
+ { path = "std::string::String::from_utf8_lossy", reason = "lossy at OS boundaries — consider OsStr/Path or stay in &[u8]; if input really is text, suppress with an #[allow] and a comment" },
]
disallowed-types = [
{ path = "std::fs::File", reason = "use fs_err::File for better error messages" },
{ path = "std::fs::OpenOptions", reason = "use fs_err::OpenOptions" },
+ { path = "chrono::DateTime", reason = "use jiff::Zoned or jiff::Timestamp" },
+ { path = "chrono::NaiveDateTime", reason = "use jiff::civil::DateTime" },
+ { path = "chrono::NaiveDate", reason = "use jiff::civil::Date" },
+ { path = "chrono::NaiveTime", reason = "use jiff::civil::Time" },
+ { path = "chrono::Duration", reason = "use jiff::Span or jiff::SignedDuration" },
]
diff --git a/frork-cli/Cargo.toml b/frork-cli/Cargo.toml
index ee02148..94e44bc 100644
--- a/frork-cli/Cargo.toml
+++ b/frork-cli/Cargo.toml
@@ -24,4 +24,12 @@ tracing-subscriber = { version = "*", features = ["env-filter"] }
assert_cmd = "*"
predicates = "*"
hegeltest = "*"
-tempfile = "*"
\ No newline at end of file
+tempfile = "*"
+
+[lints.clippy]
+self_named_module_files = "warn"
+unwrap_used = "warn"
+expect_used = "warn"
+panic = "warn"
+indexing_slicing = "warn"
+arithmetic_side_effects = "warn"
diff --git a/frork-cli/src/lib.rs b/frork-cli/src/lib.rs
index 2c6ff14..4f80e5e 100644
--- a/frork-cli/src/lib.rs
+++ b/frork-cli/src/lib.rs
@@ -1,4 +1,15 @@
-#![warn(clippy::self_named_module_files)]
+// Panic discipline applies to code that handles Fennel scripts and shell
+// output; test code asserts on known-good fixtures.
+#![cfg_attr(
+ test,
+ allow(
+ clippy::unwrap_used,
+ clippy::expect_used,
+ clippy::panic,
+ clippy::indexing_slicing,
+ clippy::arithmetic_side_effects
+ )
+)]
pub mod assertions;
pub mod error;
diff --git a/frork-cli/src/main.rs b/frork-cli/src/main.rs
index aa4052c..3847e01 100644
--- a/frork-cli/src/main.rs
+++ b/frork-cli/src/main.rs
@@ -1,3 +1,16 @@
+// Panic discipline applies to code that handles Fennel scripts and shell
+// output; test code asserts on known-good fixtures.
+#![cfg_attr(
+ test,
+ allow(
+ clippy::unwrap_used,
+ clippy::expect_used,
+ clippy::panic,
+ clippy::indexing_slicing,
+ clippy::arithmetic_side_effects
+ )
+)]
+
mod assertions;
mod error;
mod utils;
diff --git a/frork-cli/src/utils.rs b/frork-cli/src/utils.rs
index 95ca14b..f47bad6 100644
--- a/frork-cli/src/utils.rs
+++ b/frork-cli/src/utils.rs
@@ -104,6 +104,8 @@ impl Utils {
}
pub fn expand_path(path: &str) -> Result<String> {
+ // The pattern is a literal, so it either always compiles or never does.
+ #[allow(clippy::unwrap_used)]
static ENV_VAR_REGEX: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"\$([A-Za-z_][A-Za-z0-9_]*)").unwrap());
@@ -118,18 +120,20 @@ impl Utils {
// Expand environment variables
let mut missing = Vec::new();
- expanded = ENV_VAR_REGEX
- .replace_all(&expanded, |caps: ®ex::Captures| {
- let var_name = caps.get(1).unwrap().as_str();
- match env::var(var_name) {
- Ok(value) => value,
- Err(_) => {
- missing.push(var_name.to_string());
- caps.get(0).unwrap().as_str().to_string()
- }
+ // Groups 0 and 1 are non-optional in the pattern, so a match
+ // guarantees both are present.
+ #[allow(clippy::unwrap_used)]
+ let replaced = ENV_VAR_REGEX.replace_all(&expanded, |caps: ®ex::Captures| {
+ let var_name = caps.get(1).unwrap().as_str();
+ match env::var(var_name) {
+ Ok(value) => value,
+ Err(_) => {
+ missing.push(var_name.to_string());
+ caps.get(0).unwrap().as_str().to_string()
}
- })
- .to_string();
+ }
+ });
+ expanded = replaced.to_string();
if !missing.is_empty() {
return Err(miette!(
@@ -171,6 +175,9 @@ impl Utils {
.output()
.map_err(|e| miette!("Failed to execute command '{}': {e}", cmd))?;
+ // `sh` hands stdout to Fennel as a string, and scripts compare it as
+ // text. Non-UTF-8 output would be unusable there either way.
+ #[allow(clippy::disallowed_methods)]
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
let status = output
.status
diff --git a/frork-cli/tests/cli.rs b/frork-cli/tests/cli.rs
index 86fcfbd..511847c 100644
--- a/frork-cli/tests/cli.rs
+++ b/frork-cli/tests/cli.rs
@@ -3,7 +3,7 @@ use assert_cmd::cargo::cargo_bin_cmd;
use predicates::str::contains;
fn cmd() -> Command {
- Command::from(cargo_bin_cmd!("frork"))
+ cargo_bin_cmd!("frork")
}
#[test]