From 5a56bfde7a750bfe14d450870de3ddfa6ddcaaf1 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 15 Mar 2026 22:49:01 +0000 Subject: [PATCH 1/8] docs: add variable and closure parameter naming guidelines https://claude.ai/code/session_01X9XkBJTA4nYi6gVT71iA1g --- .github/copilot-instructions.md | 1 + AGENTS.md | 1 + CLAUDE.md | 1 + CONTRIBUTING.md | 76 +++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index e88f90b5..cebde460 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -8,6 +8,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c - Version releases are the only exception: just the version number (e.g. `0.21.1`) - Prefer merged imports - Use descriptive generic names (`Size`, `Report`), not single letters +- Use descriptive variable and closure parameter names by default — single letters are only allowed in: comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, test fixtures, and macro-generated variables - Prefer `where` clauses for multiple trait bounds - Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated - Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]` diff --git a/AGENTS.md b/AGENTS.md index e88f90b5..cebde460 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,6 +8,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c - Version releases are the only exception: just the version number (e.g. `0.21.1`) - Prefer merged imports - Use descriptive generic names (`Size`, `Report`), not single letters +- Use descriptive variable and closure parameter names by default — single letters are only allowed in: comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, test fixtures, and macro-generated variables - Prefer `where` clauses for multiple trait bounds - Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated - Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]` diff --git a/CLAUDE.md b/CLAUDE.md index e88f90b5..cebde460 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,6 +8,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c - Version releases are the only exception: just the version number (e.g. `0.21.1`) - Prefer merged imports - Use descriptive generic names (`Size`, `Report`), not single letters +- Use descriptive variable and closure parameter names by default — single letters are only allowed in: comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, test fixtures, and macro-generated variables - Prefer `where` clauses for multiple trait bounds - Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated - Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 96dc7660..3723ece9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -95,6 +95,82 @@ Use **descriptive names** for type parameters, not single letters: Single-letter generics are acceptable only in very short, self-contained trait impls. +### Variable and Closure Parameter Naming + +Use **descriptive names** for variables and closure parameters by default. Single-letter names are permitted only in the specific cases listed below. + +#### When single-letter names are allowed + +- **Comparison closures:** `|a, b|` in `sort_by`, `cmp`, or similar two-argument comparison callbacks — this is idiomatic Rust. + + ```rust + sort_reflection_by(&mut tree, |a, b| a.name.cmp(&b.name)); + ``` + +- **Trivial single-expression closures:** A closure whose body is a single field access, method call, or wrapper may use a single letter when the type and purpose are obvious from context. + + ```rust + .map(|n| n.as_str()) + .all(|b| b.is_ascii_digit()) + .pipe(|x| vec![x]) + ``` + +- **Fold accumulators:** `acc` (or `a`) for the accumulator and a single letter for the element in trivial folds. + + ```rust + .fold(PathBuf::new(), |acc, x| acc.join(x)) + ``` + +- **Test fixtures:** `let a`, `let b`, `let c` for interchangeable specimens in equality or comparison tests. + + ```rust + let a = HardlinkList::new().add(1, "/x").add(2, "/y"); + let b = HardlinkList::new().add(2, "/y").add(1, "/x"); + assert_eq!(a, b); + ``` + +- **Macro-generated variables:** Single-letter names inside macro bodies (e.g., `let a = include_str!($a_path)`) where the name mirrors a macro parameter. + +#### When single-letter names are NOT allowed + +- **Multi-line closures:** If the closure body spans multiple lines or contains logic beyond a single expression, use a descriptive name. + + ```rust + // Good + .map(|tree_row| { + let columns = build_columns(tree_row); + format_row(&columns) + }) + + // Bad + .map(|t| { + let columns = build_columns(t); + format_row(&columns) + }) + ``` + +- **`let` bindings in non-test code:** Always use descriptive names. + + ```rust + // Good + let metadata = entry.metadata()?; + // Bad + let m = entry.metadata()?; + ``` + +- **Function and method parameters:** Always use descriptive names. + +- **Closures with non-obvious context:** If the type or purpose is not immediately clear from the surrounding method chain, use a descriptive name. + + ```rust + // Good — not obvious what the closure receives + .filter_map(|entry| match entry { ... }) + .for_each(|child| child.par_sort_by(compare)) + + // Bad — reader must look up what .filter receives + .filter(|x| x.get_mount_point() == mount_point) + ``` + ### Trait Bounds Prefer `where` clauses over inline bounds when there are multiple constraints: From 30cb79a45c0ae42fab97303bfddd64815871c3fa Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 15 Mar 2026 23:12:45 +0000 Subject: [PATCH 2/8] docs: address PR review feedback on naming guidelines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove misleading `n` and `b` examples from trivial closures (not truly trivial; `n` implies number, `b` was fabricated) - Remove `(or `a`)` from fold accumulators — `acc` is the standard name - Clarify test fixtures require identical roles (not `actual`/`expected`) - Delete macro-generated variables bullet (misidentified reason) - Update AI instruction summaries to match https://claude.ai/code/session_01X9XkBJTA4nYi6gVT71iA1g --- .github/copilot-instructions.md | 2 +- AGENTS.md | 2 +- CLAUDE.md | 2 +- CONTRIBUTING.md | 8 ++------ 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index cebde460..3712d319 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -8,7 +8,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c - Version releases are the only exception: just the version number (e.g. `0.21.1`) - Prefer merged imports - Use descriptive generic names (`Size`, `Report`), not single letters -- Use descriptive variable and closure parameter names by default — single letters are only allowed in: comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, test fixtures, and macro-generated variables +- Use descriptive variable and closure parameter names by default — single letters are only allowed in: comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) - Prefer `where` clauses for multiple trait bounds - Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated - Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]` diff --git a/AGENTS.md b/AGENTS.md index cebde460..3712d319 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,7 +8,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c - Version releases are the only exception: just the version number (e.g. `0.21.1`) - Prefer merged imports - Use descriptive generic names (`Size`, `Report`), not single letters -- Use descriptive variable and closure parameter names by default — single letters are only allowed in: comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, test fixtures, and macro-generated variables +- Use descriptive variable and closure parameter names by default — single letters are only allowed in: comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) - Prefer `where` clauses for multiple trait bounds - Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated - Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]` diff --git a/CLAUDE.md b/CLAUDE.md index cebde460..3712d319 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,7 +8,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c - Version releases are the only exception: just the version number (e.g. `0.21.1`) - Prefer merged imports - Use descriptive generic names (`Size`, `Report`), not single letters -- Use descriptive variable and closure parameter names by default — single letters are only allowed in: comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, test fixtures, and macro-generated variables +- Use descriptive variable and closure parameter names by default — single letters are only allowed in: comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) - Prefer `where` clauses for multiple trait bounds - Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated - Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3723ece9..da90a689 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -110,18 +110,16 @@ Use **descriptive names** for variables and closure parameters by default. Singl - **Trivial single-expression closures:** A closure whose body is a single field access, method call, or wrapper may use a single letter when the type and purpose are obvious from context. ```rust - .map(|n| n.as_str()) - .all(|b| b.is_ascii_digit()) .pipe(|x| vec![x]) ``` -- **Fold accumulators:** `acc` (or `a`) for the accumulator and a single letter for the element in trivial folds. +- **Fold accumulators:** `acc` for the accumulator and a single letter for the element in trivial folds. ```rust .fold(PathBuf::new(), |acc, x| acc.join(x)) ``` -- **Test fixtures:** `let a`, `let b`, `let c` for interchangeable specimens in equality or comparison tests. +- **Test fixtures:** `let a`, `let b`, `let c` for interchangeable specimens with identical roles in equality or comparison tests (e.g., testing commutativity). Do not use single letters when the variables have distinct roles — use `actual`/`expected` or similar descriptive names instead. ```rust let a = HardlinkList::new().add(1, "/x").add(2, "/y"); @@ -129,8 +127,6 @@ Use **descriptive names** for variables and closure parameters by default. Singl assert_eq!(a, b); ``` -- **Macro-generated variables:** Single-letter names inside macro bodies (e.g., `let a = include_str!($a_path)`) where the name mirrors a macro parameter. - #### When single-letter names are NOT allowed - **Multi-line closures:** If the closure body spans multiple lines or contains logic beyond a single expression, use a descriptive name. From c8d001ab4eff4049869256a533f3a1e8157cd939 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 15 Mar 2026 23:16:59 +0000 Subject: [PATCH 3/8] docs: add conventional single-letter names (n, f) to naming guidelines Document that `n` is allowed for natural numbers/counts/indices and `f` for fmt::Formatter, matching established math and Rust stdlib conventions. https://claude.ai/code/session_01X9XkBJTA4nYi6gVT71iA1g --- .github/copilot-instructions.md | 2 +- AGENTS.md | 2 +- CLAUDE.md | 2 +- CONTRIBUTING.md | 7 +++++++ 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 3712d319..d25c5dff 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -8,7 +8,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c - Version releases are the only exception: just the version number (e.g. `0.21.1`) - Prefer merged imports - Use descriptive generic names (`Size`, `Report`), not single letters -- Use descriptive variable and closure parameter names by default — single letters are only allowed in: comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) +- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for number, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) - Prefer `where` clauses for multiple trait bounds - Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated - Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]` diff --git a/AGENTS.md b/AGENTS.md index 3712d319..d25c5dff 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,7 +8,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c - Version releases are the only exception: just the version number (e.g. `0.21.1`) - Prefer merged imports - Use descriptive generic names (`Size`, `Report`), not single letters -- Use descriptive variable and closure parameter names by default — single letters are only allowed in: comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) +- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for number, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) - Prefer `where` clauses for multiple trait bounds - Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated - Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]` diff --git a/CLAUDE.md b/CLAUDE.md index 3712d319..d25c5dff 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,7 +8,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c - Version releases are the only exception: just the version number (e.g. `0.21.1`) - Prefer merged imports - Use descriptive generic names (`Size`, `Report`), not single letters -- Use descriptive variable and closure parameter names by default — single letters are only allowed in: comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) +- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for number, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) - Prefer `where` clauses for multiple trait bounds - Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated - Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index da90a689..e4a04407 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -107,6 +107,13 @@ Use **descriptive names** for variables and closure parameters by default. Singl sort_reflection_by(&mut tree, |a, b| a.name.cmp(&b.name)); ``` +- **Conventional single-letter names:** `n` for a natural number (unsigned integer / count / index), `f` for a `fmt::Formatter`, and similar well-established conventions from math or the Rust standard library. + + ```rust + fn nth(&mut self, n: usize) -> Option + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + ``` + - **Trivial single-expression closures:** A closure whose body is a single field access, method call, or wrapper may use a single letter when the type and purpose are obvious from context. ```rust From 79b1c8c5489e3720b7d4d8d57bcfb1ad2912cf6a Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 15 Mar 2026 23:19:17 +0000 Subject: [PATCH 4/8] docs: fix test fixture example to use real, compilable code Replace fabricated HardlinkList example (HardlinkList doesn't implement PartialEq, and add() is pub(crate) and not chainable) with a BTreeSet example that actually compiles and demonstrates interchangeable roles. https://claude.ai/code/session_01X9XkBJTA4nYi6gVT71iA1g --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e4a04407..b48f6d39 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -129,8 +129,8 @@ Use **descriptive names** for variables and closure parameters by default. Singl - **Test fixtures:** `let a`, `let b`, `let c` for interchangeable specimens with identical roles in equality or comparison tests (e.g., testing commutativity). Do not use single letters when the variables have distinct roles — use `actual`/`expected` or similar descriptive names instead. ```rust - let a = HardlinkList::new().add(1, "/x").add(2, "/y"); - let b = HardlinkList::new().add(2, "/y").add(1, "/x"); + let a = vec![3, 1, 2].into_iter().collect::>(); + let b = vec![2, 3, 1].into_iter().collect::>(); assert_eq!(a, b); ``` From 191a5a4216feb68bb85f24c99bb9784f398faa20 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 15 Mar 2026 23:26:08 +0000 Subject: [PATCH 5/8] docs: refine naming guidelines per review feedback - Narrow `n` to count only (not indexing); document index naming conventions (`index`, `idx`, `i`, `*_index`) - Broaden multi-line closures rule to multi-statement functions and closures - Fix contradiction: carve out exception for conventional names (`n`, `f`) in function/method parameters rule https://claude.ai/code/session_01X9XkBJTA4nYi6gVT71iA1g --- .github/copilot-instructions.md | 2 +- AGENTS.md | 2 +- CLAUDE.md | 2 +- CONTRIBUTING.md | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index d25c5dff..b6fd3bbf 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -8,7 +8,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c - Version releases are the only exception: just the version number (e.g. `0.21.1`) - Prefer merged imports - Use descriptive generic names (`Size`, `Report`), not single letters -- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for number, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) +- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for count, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) - Prefer `where` clauses for multiple trait bounds - Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated - Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]` diff --git a/AGENTS.md b/AGENTS.md index d25c5dff..b6fd3bbf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,7 +8,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c - Version releases are the only exception: just the version number (e.g. `0.21.1`) - Prefer merged imports - Use descriptive generic names (`Size`, `Report`), not single letters -- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for number, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) +- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for count, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) - Prefer `where` clauses for multiple trait bounds - Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated - Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]` diff --git a/CLAUDE.md b/CLAUDE.md index d25c5dff..b6fd3bbf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,7 +8,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c - Version releases are the only exception: just the version number (e.g. `0.21.1`) - Prefer merged imports - Use descriptive generic names (`Size`, `Report`), not single letters -- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for number, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) +- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for count, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) - Prefer `where` clauses for multiple trait bounds - Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated - Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b48f6d39..a2301122 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -107,7 +107,7 @@ Use **descriptive names** for variables and closure parameters by default. Singl sort_reflection_by(&mut tree, |a, b| a.name.cmp(&b.name)); ``` -- **Conventional single-letter names:** `n` for a natural number (unsigned integer / count / index), `f` for a `fmt::Formatter`, and similar well-established conventions from math or the Rust standard library. +- **Conventional single-letter names:** `n` for a natural number (unsigned integer / count), `f` for a `fmt::Formatter`, and similar well-established conventions from math or the Rust standard library. Note: for indices, use `index`, `idx`, `i`, or `*_index` (e.g., `row_index`) — not `n`. ```rust fn nth(&mut self, n: usize) -> Option @@ -136,7 +136,7 @@ Use **descriptive names** for variables and closure parameters by default. Singl #### When single-letter names are NOT allowed -- **Multi-line closures:** If the closure body spans multiple lines or contains logic beyond a single expression, use a descriptive name. +- **Multi-statement functions and closures:** If the function or closure body contains more than one statement, use a descriptive name. ```rust // Good @@ -161,7 +161,7 @@ Use **descriptive names** for variables and closure parameters by default. Singl let m = entry.metadata()?; ``` -- **Function and method parameters:** Always use descriptive names. +- **Function and method parameters:** Always use descriptive names, except for conventional single-letter names listed above (`n`, `f`, etc.). - **Closures with non-obvious context:** If the type or purpose is not immediately clear from the surrounding method chain, use a descriptive name. From 5abc8b80bfab8b2628c2e959e54eeb22cad68fb0 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 15 Mar 2026 23:35:58 +0000 Subject: [PATCH 6/8] docs: add i/j/k index rules and address review feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add dedicated rule for `i`/`j`/`k`: allowed only in short closures and index-based loops - Wrap fn signature examples in trait/fn bodies for valid syntax - Clarify "multi-statement" → "multi-line" with concrete examples - Fix pseudocode `match { ... }` → `match { _ => todo!() }` - Update summary files (CLAUDE.md, AGENTS.md, copilot-instructions.md) https://claude.ai/code/session_01X9XkBJTA4nYi6gVT71iA1g --- .github/copilot-instructions.md | 2 +- AGENTS.md | 2 +- CLAUDE.md | 2 +- CONTRIBUTING.md | 23 +++++++++++++++++++---- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index b6fd3bbf..78756d14 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -8,7 +8,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c - Version releases are the only exception: just the version number (e.g. `0.21.1`) - Prefer merged imports - Use descriptive generic names (`Size`, `Report`), not single letters -- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for count, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) +- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for count, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, index variables (`i`/`j`/`k` in short closures or index-based loops only), and test fixtures (identical roles only). Never use single letters in multi-line functions or closures - Prefer `where` clauses for multiple trait bounds - Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated - Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]` diff --git a/AGENTS.md b/AGENTS.md index b6fd3bbf..78756d14 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,7 +8,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c - Version releases are the only exception: just the version number (e.g. `0.21.1`) - Prefer merged imports - Use descriptive generic names (`Size`, `Report`), not single letters -- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for count, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) +- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for count, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, index variables (`i`/`j`/`k` in short closures or index-based loops only), and test fixtures (identical roles only). Never use single letters in multi-line functions or closures - Prefer `where` clauses for multiple trait bounds - Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated - Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]` diff --git a/CLAUDE.md b/CLAUDE.md index b6fd3bbf..78756d14 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,7 +8,7 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c - Version releases are the only exception: just the version number (e.g. `0.21.1`) - Prefer merged imports - Use descriptive generic names (`Size`, `Report`), not single letters -- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for count, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, and test fixtures (identical roles only) +- Use descriptive variable and closure parameter names by default — single letters are only allowed in: conventional names (`n` for count, `f` for formatter), comparison closures (`|a, b|`), trivial single-expression closures, fold accumulators, index variables (`i`/`j`/`k` in short closures or index-based loops only), and test fixtures (identical roles only). Never use single letters in multi-line functions or closures - Prefer `where` clauses for multiple trait bounds - Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated - Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a2301122..ec045616 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -110,8 +110,23 @@ Use **descriptive names** for variables and closure parameters by default. Singl - **Conventional single-letter names:** `n` for a natural number (unsigned integer / count), `f` for a `fmt::Formatter`, and similar well-established conventions from math or the Rust standard library. Note: for indices, use `index`, `idx`, `i`, or `*_index` (e.g., `row_index`) — not `n`. ```rust - fn nth(&mut self, n: usize) -> Option - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + trait Iterator { + fn nth(&mut self, n: usize) -> Option; + } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ... } + ``` + +- **Index variables (`i`, `j`, `k`):** These may only be used in two contexts: (1) short closures, and (2) index-based loops/iterations (rare in Rust). In all other cases, use `index`, `idx`, or `*_index`. + + ```rust + // OK — short closure + left_indices.zip(right_indices).map(|(i, j)| matrix[i][j]) + + // OK — index-based loop (rare in Rust) + for i in 0..len { ... } + + // Bad — use a descriptive name instead + let i = items.iter().position(|item| item.is_active()).unwrap(); ``` - **Trivial single-expression closures:** A closure whose body is a single field access, method call, or wrapper may use a single letter when the type and purpose are obvious from context. @@ -136,7 +151,7 @@ Use **descriptive names** for variables and closure parameters by default. Singl #### When single-letter names are NOT allowed -- **Multi-statement functions and closures:** If the function or closure body contains more than one statement, use a descriptive name. +- **Multi-line functions and closures:** If a function or closure body spans multiple lines (e.g., contains a `let` binding followed by another expression, or multiple chained operations), use a descriptive name. ```rust // Good @@ -167,7 +182,7 @@ Use **descriptive names** for variables and closure parameters by default. Singl ```rust // Good — not obvious what the closure receives - .filter_map(|entry| match entry { ... }) + .filter_map(|entry| match entry { _ => todo!() }) .for_each(|child| child.par_sort_by(compare)) // Bad — reader must look up what .filter receives From f7c5603a92c73dac2ed3b78a888ccd2b7a8a0168 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 15 Mar 2026 23:50:13 +0000 Subject: [PATCH 7/8] docs: fix invalid Rust syntax in code examples - Add `type Item;` to trait Iterator example - Replace `{ ... }` with `{ todo!() }` and `{ /* ... */ }` https://claude.ai/code/session_01X9XkBJTA4nYi6gVT71iA1g --- CONTRIBUTING.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ec045616..961bc370 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -111,9 +111,10 @@ Use **descriptive names** for variables and closure parameters by default. Singl ```rust trait Iterator { + type Item; fn nth(&mut self, n: usize) -> Option; } - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ... } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { todo!() } ``` - **Index variables (`i`, `j`, `k`):** These may only be used in two contexts: (1) short closures, and (2) index-based loops/iterations (rare in Rust). In all other cases, use `index`, `idx`, or `*_index`. @@ -123,7 +124,7 @@ Use **descriptive names** for variables and closure parameters by default. Singl left_indices.zip(right_indices).map(|(i, j)| matrix[i][j]) // OK — index-based loop (rare in Rust) - for i in 0..len { ... } + for i in 0..len { /* ... */ } // Bad — use a descriptive name instead let i = items.iter().position(|item| item.is_active()).unwrap(); From b19c0fb49a558c369f3deab6353f96894ac011e7 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 15 Mar 2026 23:57:28 +0000 Subject: [PATCH 8/8] docs: fix n-as-index contradiction and clarify i/j/k cross-reference - Replace `nth(n)` example with `with_capacity(n)` since `n` is for counts, not indices - Remove `i` from the conventional names note and cross-reference the dedicated i/j/k rule instead https://claude.ai/code/session_01X9XkBJTA4nYi6gVT71iA1g --- CONTRIBUTING.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 961bc370..74033a2e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -107,13 +107,10 @@ Use **descriptive names** for variables and closure parameters by default. Singl sort_reflection_by(&mut tree, |a, b| a.name.cmp(&b.name)); ``` -- **Conventional single-letter names:** `n` for a natural number (unsigned integer / count), `f` for a `fmt::Formatter`, and similar well-established conventions from math or the Rust standard library. Note: for indices, use `index`, `idx`, `i`, or `*_index` (e.g., `row_index`) — not `n`. +- **Conventional single-letter names:** `n` for a natural number (unsigned integer / count), `f` for a `fmt::Formatter`, and similar well-established conventions from math or the Rust standard library. Note: for indices, use `index`, `idx`, or `*_index` (e.g., `row_index`) — not `n`. (For `i`/`j`/`k`, see the dedicated rule below.) ```rust - trait Iterator { - type Item; - fn nth(&mut self, n: usize) -> Option; - } + fn with_capacity(n: usize) -> Self { todo!() } fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { todo!() } ```