iter clippy-sweep: clear all 61 cargo clippy warnings

Hygiene sweep across the workspace under `cargo clippy --workspace
--all-targets`. Before: 61 warnings. After: zero. Tests stay 563
green, `cargo doc` stays at zero warnings, and all three bench
scripts exit 0 against existing baselines.

Twelve lint classes, three fix shapes:

- Documentation hygiene (~32 hits): `doc_lazy_continuation` resolved
  by adding blank lines before continuation paragraphs or rephrasing
  the offending line; plus four `empty_line_after_doc_comments` hits
  in workspace.rs where eight `///` blocks left orphan by form-a.1
  T5 test relocation were converted to plain `//`.
- Idiomatic refactors (~16 hits): `.err().expect()` → `.expect_err()`,
  redundant `.into_iter()` and `.into()` removed, `|f| g(f)` →
  `g`, `.trim().split_whitespace()` → `.split_whitespace()`,
  `push_str("x")` → `push('x')`, two manual `impl Default` flipped
  to `#[derive(Default)]` + `#[default]`, two nested `if let Some(_)
  = …` collapsed.
- Block extraction (1 hit): a 13-line block inside an `else if`
  condition in synth's Var-arm extracted to a new helper
  `is_class_method_dispatch(name, env)` next to
  `qualifier_is_class_shape`.

Three `#[allow]`s with inline rationale where clippy's suggestion
would lose meaning: `only_used_in_recursion` on walk_pattern (the
parameter preserves the five-fn walker-framework signature
uniformity), 2× `if_same_then_else` on qualify_local_types shapes
(two branches encode semantically distinct disqualification
reasons), `too_many_arguments` on `Emitter::new` (8 workspace-flat
tables; bundling would just rename boilerplate).
This commit is contained in:
2026-05-14 00:48:17 +02:00
parent 04258c5cc1
commit abcdd05991
19 changed files with 302 additions and 162 deletions
@@ -0,0 +1,134 @@
# iter clippy-sweep — clear all 61 `cargo clippy` warnings
**Date:** 2026-05-14
**Started from:** 04258c5 (post-WhatsNew of rustdoc-sweep + drift-test-narrowing)
**Status:** DONE
## Summary
Hygiene sweep against `cargo clippy --workspace --all-targets`. Before:
61 warnings across all eight crates. After: zero. Tests stay 563 green;
`cargo doc --workspace --no-deps` stays at zero warnings (the
rustdoc-sweep baseline); all three bench scripts (`bench/check.py`,
`bench/compile_check.py`, `bench/cross_lang.py`) all exit 0 against
the existing baselines — a free Stabilitätsbeweis that the sweep
touched no semantics.
Twelve warning classes, fixed with three different shapes:
- **Pure documentation fixes** (~32 warnings). `doc_lazy_continuation`
on multi-line `///` and `//!` comments where clippy parsed the
second line as a list continuation; resolved by either adding a
blank line, escaping the marker, or rephrasing the offending line.
Affected: `lex.rs:235-243` (3-line bullet list), `lib.rs:2360-2368`
in `ailang-check` (3-line bullet list), `lib.rs:3736` in
`ailang-check` (a `> 1` numeric comparison parsed as a quote
marker; rephrased to "any cardinality above one"), `drop.rs:570-585`
(numbered list + paragraph mix), `e2e.rs:915-920` (a `+ three
primitive instances` line where `+` was parsed as bullet marker),
`e2e.rs:1607-1614`, `typeclass_22b3.rs:706-708`, `eq_ord_e2e.rs:13`.
Plus four `empty_line_after_doc_comments` hits in
`workspace.rs:1675-2506` — these were `///` doc-comments left
orphaned by form-a.1 Task 5 test relocation; converted to plain
`//` comments (eight blocks total) since they no longer document
any function.
- **Idiomatic refactors** (8 warnings). `err_expect` (5 hits in
`parse.rs`): `.err().expect("…")``.expect_err("…")`.
`useless_conversion` (3 hits): `.extend(x.into_iter())``.extend(x)`
in `desugar.rs:275` + `lift.rs:201`; `vec!["x".into()]`
`vec!["x"]` in `lib.rs:5522` (where the call-site `fn_def`
parameter is `Vec<&str>` so the conversion was identity).
`redundant_closure` (2 hits): `|f| collect_pattern_binders(f)`
`collect_pattern_binders` in `linearity.rs:717`; same pattern in
`loader.rs:108`. `trim_split_whitespace`: `.trim().split_whitespace()`
`.split_whitespace()` in `prose/src/lib.rs:2103` (since
`split_whitespace` already ignores leading/trailing whitespace).
`single_char_add_str`: `out.push_str("x")``out.push('x')` in
`prose/src/lib.rs:383`. `collapsible_match` (2 hits): nested
`if let Some(_) = …` collapsed to `if let Some(Some(_)) = …` in
`mono.rs:1028` + `drop.rs:535-536`.
- **`derivable_impls`** (2 hits). `impl Default for ParamMode {
fn default() -> Self { ParamMode::Implicit } }` in `ast.rs:731`
→ `#[derive(Default)]` + `#[default] Implicit`. Same shape for
`AllocStrategy` in `codegen/src/lib.rs:164`. The derive form is
strictly more explicit (the `#[default]` attribute marks which
variant in-source rather than the impl body referencing it by
name) so the change is also a small clarity gain.
- **`blocks_in_conditions`** (1 hit). The synth `Term::Var` arm in
`check/src/lib.rs` had a 13-line block inside an `else if`
condition (the mq.2 dispatch entry: `else if { let (m, q) =
parse_method_qualifier(name); qualifier_is_class_shape(&q) &&
env.method_to_candidate_classes.contains_key(m) }`). Extracted
to a new helper `fn is_class_method_dispatch(name, env) -> bool`
next to `qualifier_is_class_shape`. The helper inherits the
block's full doc-comment so the why-each-branch reasoning is
preserved at the call site.
- **`only_used_in_recursion`** (1 hit). `walk_pattern(p, f)` in
`workspace.rs:1399` carries an `f: &mut F` parameter that
Pattern walking never invokes (ct.1 left this seam unused: no
Pattern variant carries a cross-module reference). Rather than
delete `f` (which would break the symmetry with the five other
`walk_*` framework functions in this file that all share the
same `<F>(_, f: &mut F) -> Result<…>` signature), added
`#[allow(clippy::only_used_in_recursion)]` with an inline
comment naming the framework-uniformity rationale.
- **`if_same_then_else`** (2 hits). Both in `qualify_local_types`
shapes (`check/src/lib.rs:3457` + `codegen/src/subst.rs:165`):
the if-chain has two branches returning `name.clone()` for
semantically distinct reasons (`name.contains('.')` = already
qualified; `is_primitive_name(name)` = primitive needs no
qualification). Combining the branches with `||` would obscure
the reasoning. Added `#[allow(clippy::if_same_then_else)]` with
an inline comment naming why each branch disqualifies the name.
- **`too_many_arguments`** (1 hit). `Emitter::new` takes 8 of the
workspace-flat tables the emitter needs at construction time.
Bundling them into a context struct would just rename the
boilerplate without reducing it. Added
`#[allow(clippy::too_many_arguments)]` with the rationale
inline.
## Files touched
- `crates/ailang-core/src/ast.rs` (1 derive flip)
- `crates/ailang-core/src/desugar.rs` (1 .extend)
- `crates/ailang-core/src/workspace.rs` (1 walk_pattern allow + 8 `///`→`//` blocks)
- `crates/ailang-surface/src/lex.rs` (1 doc-list blank line)
- `crates/ailang-surface/src/parse.rs` (5 `.expect_err`)
- `crates/ailang-surface/tests/loader.rs` (1 redundant closure)
- `crates/ailang-prose/src/lib.rs` (push_str + trim removal)
- `crates/ailang-check/src/lib.rs` (helper extraction + 1 allow + 1 doc rephrase + 1 doc-list blank line + 1 vec literal)
- `crates/ailang-check/src/lift.rs` (1 .extend)
- `crates/ailang-check/src/linearity.rs` (1 redundant closure)
- `crates/ailang-codegen/src/lib.rs` (1 derive flip + 1 too_many_args allow)
- `crates/ailang-codegen/src/subst.rs` (1 if_same_then_else allow)
- `crates/ailang-codegen/src/drop.rs` (1 doc-list blank line + 1 collapsible_match)
- `crates/ailang-check/src/mono.rs` (1 collapsible_match)
- `crates/ail/tests/e2e.rs` (2 doc rephrasings)
- `crates/ail/tests/typeclass_22b3.rs` (1 doc rephrasing)
- `crates/ail/tests/eq_ord_e2e.rs` (1 doc rephrasing)
## Verification
- `cargo clippy --workspace --all-targets 2>&1 | grep -c '^warning:'`
→ `0` (was 61).
- `cargo test --workspace` → 563 passed + 3 ignored, 0 failed
(baseline holds).
- `cargo doc --workspace --no-deps 2>&1 | grep -c '^warning:'` →
`0` (rustdoc-sweep baseline holds — no regression).
- `bench/check.py` → exit 0.
- `bench/compile_check.py` → exit 0.
- `bench/cross_lang.py` → exit 0.
## Concerns
- (none)
## Known debt
- (none)
+1
View File
@@ -60,3 +60,4 @@
- 2026-05-13 — iter str-concat: `str_concat : (borrow Str, borrow Str) -> Str` heap-Str concatenation primitive shipped in four-site lockstep, closing fieldtest-form-a friction finding #4. T1 RED-pin `crates/ail/tests/str_concat_e2e.rs` + new corpus fixture `examples/show_user_adt_with_label.ail` (Show user-ADT body using `(app str_concat "Item " (app int_to_str n))` through prelude `print`; ok 23/2). T2 `runtime/str.c` C helper `ailang_str_concat(a, b)` appended after `ailang_str_clone`: reads `len` headers from both source payloads, `str_alloc(la+lb)`, memcpys both bytes, NUL-terminates. T3 `crates/ailang-check/src/builtins.rs` install entry (Type::Fn arity-2 Borrow-Borrow params, Own return, effects empty) + list() row + `install_str_concat_signature` unit test reaching into `env.globals` directly (deeper than synth_in_builtins_env-based siblings because first builtin with arity-2 Borrow params). T4 `crates/ailang-codegen/src/lib.rs` four-site lockstep: extern `declare ptr @ailang_str_concat(ptr, ptr)` after str_clone declare + lower_app arm after str_clone arm (arity-2 check + two `lower_term` + `fresh_ssa` + body push) + `is_builtin_callable` match-list extended with `"str_concat"` + IR-pin unit test `str_concat_emits_call_to_ailang_str_concat` asserting both extern declaration AND call instruction in emitted IR. Five IR snapshots regenerated (`hello.ll`, `list.ll`, `max3.ll`, `sum.ll`, `ws_main.ll`) to absorb the new unconditional declare line in IR header — same upkeep pattern as hs.4 (sole diff verified at IR line 17 across all snapshots). T5 lockstep-collision repair: `examples/bug_unbound_in_instance_method.ail` had used `str_concat` as the literal UNBOUND name (because that was the fieldtester's LLM-natural repro); renamed to `format_label` (LLM-author-realistic helper name that will never become a builtin) and updated `crates/ail/tests/unbound_in_instance_method_pin.rs` (`replace_all` on `str_concat``format_label`, including one test name flipped to `check_fires_unbound_var_for_format_label_in_instance_method_body`), preserving the regression guard's intent (instance-method-body walked through unbound-var check) while substituting a name with stable unbound semantics. T6 `docs/DESIGN.md` new §"Heap-Str primitives" subsection (line 1994) between the milestone-24 Show-backer enumeration and the existing `Primitive output goes through ...` paragraph, cataloguing all five heap-Str primitives (`int_to_str`, `bool_to_str`, `float_to_str`, `str_clone`, `str_concat`) with type signatures, iter origins, and the user-visible-vs-prelude-internal distinction; Show-backer block unchanged. T7 `docs/roadmap.md` struck `[x] [feature] str_concat` line at end of P2 cluster. Two minor plan-vs-actual discrepancies recorded in journal Concerns: (a) T3 Step 5 test-count prediction `passed: 560 failed: 1` was actual `passed: 558 failed: 3` because the unbound_in_instance_method_pin tests turn RED at checker registration not at codegen (assertion is on the `[unbound-var]` diagnostic which depends only on the checker registry) — implementation correct, T5 fully repairs; (b) IR snapshot regen for T4 was not explicitly scripted in the plan but follows hs.4 precedent. Final iter state: 562/562 green (559 baseline + 3 new pins), zero re-loops across all 7 tasks. Bench impact none (no new code paths touched by bench corpus; bench fixtures use `int_to_str` / `bool_to_str` only). Closes fieldtest-form-a queue: bug (closed bugfix-instance-body-unbound-var), spec_gaps 2+3 (closed form-a.tidy), friction (closed here). Remaining open: spec_gap 1 dropped per recon (audit-form-a "plan two sites" claim did not match HEAD) → 2026-05-13-iter-str-concat.md
- 2026-05-13 — iter rustdoc-sweep: cleared all 23 `cargo doc --workspace --no-deps` warnings (17 in `ailang-check` + 4 in `ailang-core` + 2 in `ailang-surface`). Two warning classes: (a) `pub` doc-comments that linked-via-brackets to `pub(crate)`/private items (15 hits) — replaced ``[`fn`]`` with plain backtick-code-span ``` `fn` ``` so the identifier stays readable but rustdoc no longer tries to resolve the link; (b) unresolved/ambiguous links (8 hits) — `mono.rs` `[`Registry`]`/`[`Registry::entries`]` ×3 fully-qualified to `[`ailang_core::workspace::Registry…`]`; `loader.rs` `[`crate::parse`]` ×2 (ambiguous between fn + mod) disambiguated to `[`crate::parse()`]`; `lib.rs` `metas[i]` (parsed as a link) escaped to `metas\[i\]`. Tests 562 → 562, no behaviour change → 2026-05-13-iter-rustdoc-sweep.md
- 2026-05-13 — iter drift-test-narrowing: `crates/ailang-core/tests/design_schema_drift.rs` now scans §"Data model" only, not the whole DESIGN.md. New helper `data_model_section()` slices `DESIGN_MD` from `## Data model` to the next top-level `## ` header; all 7 anchor-presence tests switched from `DESIGN_MD.contains(anchor)` to `data_model_section().contains(anchor)`. Closes the audit-form-a-precursor `[high]` "anchors-elsewhere-pass-silently" failure mode (an anchor present only in §"Decision 11" or another discussion section was previously treated as documented). All 38 anchors verified pre-edit to live in §"Data model" so the tightening doesn't regress to red. New pin `data_model_section_is_bounded` (starts-with `## Data model`, no bleed past `\n## Pipeline`, > 1 KB) guards the extractor itself against silent regression to whole-document scanning. Tests 562 → 563 (+1) → 2026-05-13-iter-drift-test-narrowing.md
- 2026-05-14 — iter clippy-sweep: cleared all 61 `cargo clippy --workspace --all-targets` warnings across 12 lint classes. Bulk: 32× `doc_lazy_continuation` + 4× `empty_line_after_doc_comments` (8 orphan `///` blocks in `workspace.rs` left by form-a.1 T5 relocation converted to plain `//`) — pure documentation hygiene. Idiomatic refactors: 5× `err_expect` (`.err().expect()``.expect_err()`), 3× `useless_conversion`, 2× `redundant_closure`, 2× `collapsible_match`, 1× `single_char_add_str`, 1× `trim_split_whitespace`. Two `derivable_impls` (manual `Default` for `ParamMode` + `AllocStrategy` flipped to `#[derive(Default)]` + `#[default]`). One `blocks_in_conditions` extracted to a new helper `is_class_method_dispatch(name, env)` next to `qualifier_is_class_shape` in `check/src/lib.rs`. Three `#[allow]`s with inline rationale: `only_used_in_recursion` on `walk_pattern` (preserves the 5-fn walker-framework signature uniformity), 2× `if_same_then_else` on `qualify_local_types` shapes (`check/src/lib.rs:3457` + `codegen/src/subst.rs:165` — the two `name.clone()` branches encode semantically distinct disqualification reasons), `too_many_arguments` on `Emitter::new` (8 workspace-flat tables; bundling would just rename boilerplate). Tests 563 → 563 (no behavior change); `cargo doc` stays at 0 warnings (rustdoc-sweep baseline holds); all 3 bench scripts exit 0 against existing baselines (free stability check that the sweep touched no semantics) → 2026-05-14-iter-clippy-sweep.md