From 9501793de59f5c8debae64450e9da94fdc47bb15 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 13 May 2026 16:59:17 +0000 Subject: [PATCH 1/2] chore(toolchain): bump ndarray to Rust 1.95.0 + manual_checked_ops fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aligns ndarray MSRV with the rest of the AdaWorldAPI stack (bevy already on 1.95 for edition 2024, lance-graph bumped in a parallel PR). Single rustc version across {ndarray, bevy, lance-graph, MedCare-rs} — removes the `rustup run 1.95.0 …` vs default-toolchain confusion in local dev and the bevy smoke-test CI. Changes: - `rust-toolchain.toml`: channel 1.94.1 → 1.95.0 - `Cargo.toml`: rust-version "1.94" → "1.95" - `.github/workflows/ci.yaml`: MSRV / BLAS_MSRV env 1.94.0 → 1.95.0; clippy matrix + dtolnay/rust-toolchain pin 1.94.1 → 1.95.0; updated three explanatory comments that referenced the old pin. - `src/impl_owned_array.rs::into_scalar`: fix the ONE 1.95 clippy lint that fires on this codebase — `clippy::manual_checked_ops` wants `checked_div` instead of the manual `if size == 0` + division. The fix is `(first - base).checked_div(size).unwrap_or(0)`; the existing `size == 0` guard above already handles the divisor-is-zero case, so the unwrap is unreachable in practice. Comment explains why. Test surface (post-bump, 1.95.0): cargo test --features rayon --lib: 1788 passed, 36 ignored, 0 failed cargo clippy --features rayon --lib -- -D warnings: clean Signal mining: - New file `.claude/board/UNUSED_INVENTORY_1.95.md` catalogues 36 `#[allow(dead_code|unused)]` suppression sites in the lib. Split into 9 "likely actionable" (A1-A9: stale Rust 1.64 imports, phantom SimdTier variants already flagged by round-1 audit, dead clam code) + 27 "documented scaffolding" (B1-B10: cfg-conditional imports, rayon gates, no_std polyfill helpers, doc-link helpers). Provides a ready-made follow-up backlog without bundling the cleanup into this bump PR. Companion: lance-graph parallel PR bumps to 1.95 the same way. --- .claude/board/UNUSED_INVENTORY_1.95.md | 60 ++++++++++++++++++++++++++ .github/workflows/ci.yaml | 21 +++++---- Cargo.toml | 2 +- rust-toolchain.toml | 14 +++--- src/impl_owned_array.rs | 7 ++- 5 files changed, 87 insertions(+), 17 deletions(-) create mode 100644 .claude/board/UNUSED_INVENTORY_1.95.md diff --git a/.claude/board/UNUSED_INVENTORY_1.95.md b/.claude/board/UNUSED_INVENTORY_1.95.md new file mode 100644 index 00000000..6ad7412b --- /dev/null +++ b/.claude/board/UNUSED_INVENTORY_1.95.md @@ -0,0 +1,60 @@ +# Unused / Allow-suppressed Inventory — 1.95 sweep + +> **Captured:** 2026-05-13 while bumping ndarray master to Rust 1.95.0. +> **Source:** `grep -rn "#\[allow(dead_code\|#\[allow(unused" src/` (lib only). +> **Purpose:** signal mining — each entry below is a piece of code that +> compiles but is allowed to be unused. Some are legitimate scaffolding +> (rayon-gated, no_std polyfill, hot-swap reserves), some are actionable +> (Rust-1.64 compatibility imports that 1.95 likely doesn't need, phantom +> tier variants flagged by the round-1 audit fleet). + +## Categorization + +### A — Likely actionable (real "API drift" candidates) + +| # | Site | Suppression | Why interesting | +|---|---|---|---| +| A1 | `src/impl_owned_array.rs:7` | `unused_imports // Needed for Rust 1.64` | We just bumped to 1.95. The 1.64-era workaround is almost certainly stale. **Action:** remove the suppression, see if the import is still needed; if not, drop it. | +| A2 | `src/iterators/mod.rs:24` | `unused_imports // Needed for Rust 1.64` | Same as A1. | +| A3 | `src/hpc/simd_dispatch.rs:47` | `dead_code` on `SimdTier::WasmSimd128` (and likely `Sse2`) | **Flagged by round-1 audit agent #6**: `SimdTier::Sse2` is never selected in `detect()`; no SSE2 wrapper functions exist. Phantom variants. **Action:** delete or wire. | +| A4 | `src/hpc/clam.rs:928` | `dead_code` | CLAM cluster code. **Action:** verify if the suppressed fn is reachable through any public CLAM call path; if not, delete. | +| A5 | `src/hpc/clam_compress.rs:141` | `dead_code` | Same family as A4. | +| A6 | `src/hpc/jitson/scan_config.rs:144` | `dead_code` | jitson scan-config. Probably scaffolding for an unfinished feature; needs PR-author review. | +| A7 | `src/impl_ref_types.rs:364` | `dead_code` | ndarray ref type helper. | +| A8 | `src/backend/native.rs:376`, `:423` | `dead_code` (×2) | Backend kernel helpers possibly only used by feature-gated paths. | +| A9 | `src/hpc/packed.rs:29`, `:42` | `unused_variables` (×2) | Variables defined but unused. Either rename to `_x` for explicit "ignored", or wire them in. | + +### B — Documented scaffolding (intentional, leave) + +| # | Site | Suppression | Justification | +|---|---|---|---| +| B1 | `src/simd.rs:15,31,48,96,110,126,1612,1658,1672` (×9) | `dead_code` | Tier enum variants for cross-arch builds (only some platforms use all variants) + no_std `LazyLock` polyfill helpers. | +| B2 | `src/split_at.rs:11` | `dead_code // used only when Rayon support is enabled` | Self-documented. | +| B3 | `src/hpc/jitson_cranelift/engine.rs:130` | `dead_code // retained for future hot-swap / eviction by FuncId` | Self-documented. | +| B4 | `src/data_repr.rs:11`, `src/data_traits.rs:11`, `src/impl_constructors.rs:37`, `src/impl_methods.rs:13`, `src/free_functions.rs:13`, `src/impl_views/conversions.rs:10` | `unused_imports` | Conditional-cfg imports needed under some feature combinations. | +| B5 | `src/parallel/mod.rs:120,122` | `unused_imports // used by rustdoc links` | Self-documented. | +| B6 | `src/simd_neon.rs:1721` | `unused_macros` | NEON macros only used on aarch64. | +| B7 | `src/zip/mod.rs:424,715` | `dead_code` / `unused` | Zip iterator scaffolding. | +| B8 | `src/backend/native.rs:20` | `dead_code` | Backend kernel scaffold. | +| B9 | `src/doc/ndarray_for_numpy_users/mod.rs:750` | `unused_imports` | Doc example. | +| B10 | `src/itertools.rs:90` | (inside a doc-comment example) | Not real code. | + +## Suggested follow-ups (post-1.95 bump) + +- **A1, A2 (Rust 1.64 compat sweep):** remove the suppression, attempt build, drop the import if no longer needed. Likely a 2-line change × 2 files. +- **A3 (phantom SimdTier variants):** the round-1 audit fleet already flagged this. Pair with the round-3 cosmetic-SIMD consumer fleet — they'll touch `simd_dispatch.rs` anyway. +- **A4, A5 (clam dead_code):** needs domain owner review. Worth flagging in a CLAM-related PR; not urgent. +- **A6 (jitson scan_config):** check INTEGRATION_PLANS — if jitson is still active, wire; if archived, delete. +- **A7, A8, A9:** small-scope per-site review; aggregate into a "dead-code cleanup" PR. + +## What this PR (1.95 bump) does NOT touch + +This file is **signal mining only**. The 1.95 bump PR itself: +- Bumps `rust-toolchain.toml` → 1.95.0 +- Bumps `Cargo.toml` `rust-version` → "1.95" +- Bumps `MSRV` / `BLAS_MSRV` env in ci.yaml → 1.95.0 +- Fixes the ONE 1.95 clippy lint that fires (`clippy::manual_checked_ops` + in `impl_owned_array.rs::into_scalar`) + +The 36 suppression sites are pre-existing and persist after the bump. +Cleaning them up is the follow-up work surfaced by this inventory. diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ccac38f0..7cfecde9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,8 +21,8 @@ env: # `LazyLock` detection means one binary, all ISAs. Jobs that # specifically need a higher target-cpu can opt in via per-job env. RUSTFLAGS: "-D warnings" - MSRV: 1.94.0 - BLAS_MSRV: 1.94.0 + MSRV: 1.95.0 + BLAS_MSRV: 1.95.0 jobs: pass-msrv: @@ -41,15 +41,18 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - # Pinned to 1.94.1 to match `rust-toolchain.toml`. Auto-tracking - # `stable` would silently bump to 1.95 and start rejecting code - # on lints like `clippy::unnecessary_sort_by` that 1.94 accepted. + # Pinned to 1.95.0 to match `rust-toolchain.toml`. The workspace + # bumped from 1.94.1 → 1.95.0 in commit + # https://github.com/AdaWorldAPI/ndarray (this PR) to align with + # bevy (edition 2024 → 1.95 MSRV) and lance-graph. 1.95 added the + # `clippy::manual_checked_ops` lint which fires on + # `impl_owned_array.rs::into_scalar` — fixed in this same PR. rust: - - "1.94.1" + - "1.95.0" name: clippy/${{ matrix.rust }} steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@1.94.1 + - uses: dtolnay/rust-toolchain@1.95.0 with: components: clippy - uses: Swatinem/rust-cache@v2 @@ -77,7 +80,7 @@ jobs: # The format job MUST use nightly rustfmt for the project's chosen # style to be enforceable. # - # The compile + clippy jobs stay on 1.94.1 (pinned in + # The compile + clippy jobs stay on 1.95.0 (pinned in # `rust-toolchain.toml`) — only this fmt job needs nightly. - uses: dtolnay/rust-toolchain@nightly with: @@ -101,7 +104,7 @@ jobs: with: toolchain: ${{ matrix.rust }} targets: ${{ matrix.target }} - # rust-toolchain.toml pins 1.94.1 — install the cross-compile target + # rust-toolchain.toml pins 1.95.0 — install the cross-compile target # for that toolchain too, since dtolnay/rust-toolchain only installs # for the matrix value which may differ from the pinned version. - run: rustup target add ${{ matrix.target }} diff --git a/Cargo.toml b/Cargo.toml index 29811f17..b1e30f85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "ndarray" version = "0.17.2" edition = "2021" -rust-version = "1.94" +rust-version = "1.95" authors = [ "Ulrik Sverdrup \"bluss\"", "Jim Turner" diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 3ca251ea..e7ebd394 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,8 +1,10 @@ [toolchain] -channel = "1.94.1" -# Pinned to 1.94.1 (latest 1.94 patch, 2026-03-25). 1.95 turned several -# previously-safe patterns into denied lints (e.g. unnecessary_sort_by) -# without sufficient value to justify the churn — bump explicitly when -# a future version is reviewed, never auto-track stable. Mirrors the -# pin in lance-graph, smb-office-rs, and MedCare-rs. +channel = "1.95.0" +# Pinned to 1.95.0 (2026-04-14). Aligns ndarray with the rest of the +# AdaWorldAPI stack: bevy (already on 1.95 for edition 2024) and +# lance-graph (bumped in parallel). 1.95 introduced one new clippy lint +# that fires on this codebase (`clippy::manual_checked_ops` on +# `impl_owned_array.rs::into_scalar`); that's fixed in this same commit. +# Never auto-track `stable` — bump explicitly when a future version is +# reviewed and the workspace clippy passes clean. components = ["clippy", "rustfmt"] diff --git a/src/impl_owned_array.rs b/src/impl_owned_array.rs index 73165500..5cc49cf2 100644 --- a/src/impl_owned_array.rs +++ b/src/impl_owned_array.rs @@ -45,7 +45,12 @@ impl Array { // by `array![1, 2, 3, 4].slice_move(s![2])`.) let first = self.parts.ptr.as_ptr() as usize; let base = self.data.as_ptr() as usize; - let index = (first - base) / size; + // Use `checked_div` to satisfy `clippy::manual_checked_ops` + // (new lint in Rust 1.95). The `size == 0` branch above already + // covers the divisor-is-zero case, so the `unwrap_or` is + // unreachable in practice — `0` is the safest fallback if some + // future refactor lets a `size == 0` ZST sneak past the guard. + let index = (first - base).checked_div(size).unwrap_or(0); debug_assert_eq!((first - base) % size, 0); // Remove the element at the index and return it. self.data.into_vec().remove(index) From b30c5b69675bbf9654407af3773bb4f7ee7ca7ed Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 13 May 2026 17:22:22 +0000 Subject: [PATCH 2/2] ci(format): enforce stable rustfmt + drop continue-on-error band-aid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #133 (commits 7ca1cf3d + ed59b3b1) stripped all 13 nightly-only directives from `rustfmt.toml` and normalized the codebase to stable rustfmt 1.94.1. The CI fmt job, however, was never updated to leverage this — it still used: uses: dtolnay/rust-toolchain@nightly continue-on-error: true …which left fmt failures showing as "passing" on PR checks (an atom-bomb red flag for code-style invariants). The original `continue-on-error: true` rationale ("5,679 drift sites with nightly rustfmt") was dependent on the nightly-only directives that PR #133 already removed. The band-aid was stale. This commit completes what PR #133 implied: - Switch fmt job from `dtolnay/rust-toolchain@nightly` to `dtolnay/rust-toolchain@1.95.0` (the rust-toolchain.toml pin). - Remove `continue-on-error: true` — fmt failures now block merge, as they should. - Rename the job from `format/nightly` → `format/stable` to reflect the actual toolchain. - Replace the stale 24-line comment block with a 12-line explanation citing PR #133 as the source of stable-clean state. Plus the 3 drift sites between stable 1.94.1 and stable 1.95.0 (import ordering changes in `src/hpc/clam.rs`, `src/hpc/mod.rs`, `src/hpc/udf_kernels.rs`) — `cargo fmt --all` on 1.95.0 normalizes them. Bundled with the 1.95 bump since this PR is the trigger. Verified: `cargo fmt --all --check` clean on 1.95.0 post-commit. Companion to PR #133 / "where did that PR go" — completes the missed step. --- .github/workflows/ci.yaml | 35 +++++++++++++++-------------------- src/hpc/clam.rs | 2 +- src/hpc/mod.rs | 2 +- src/hpc/udf_kernels.rs | 2 +- 4 files changed, 18 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7cfecde9..a5af93f7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -61,28 +61,23 @@ jobs: format: runs-on: ubuntu-latest - name: format/nightly - # Marked non-blocking until a separate fmt-sweep PR aligns the - # codebase with `rustfmt.toml`. Local audit (2026-04-30) under - # `cargo +nightly fmt --all -- --check` reports 5,679 drift sites — - # too large to bundle into a CI-fix PR. The format job remains in - # the pipeline as a continuous signal so the sweep author can verify - # zero drift after running `cargo +nightly fmt --all`, but it does - # not gate merge until that sweep lands. - continue-on-error: true + name: format/stable + # Blocking — no continue-on-error. `rustfmt.toml` was stripped of all + # nightly-only directives in PR #133 (`7ca1cf3d chore(fmt): strip + # unstable rustfmt options, keep stable-only config` + `ed59b3b1 + # style: normalize codebase to stable rustfmt 1.94.1`) and the + # codebase normalized — so stable rustfmt enforces the project's + # style losslessly. The previous `continue-on-error: true` + + # `dtolnay/rust-toolchain@nightly` setup was a stale band-aid from + # when `brace_style = AlwaysNextLine`, `imports_granularity = + # Preserve`, `unstable_features = true` still lived in rustfmt.toml. + # That state no longer exists; the band-aid is removed in this PR. steps: - uses: actions/checkout@v4 - # `rustfmt.toml` declares 13 nightly-only options - # (`brace_style = AlwaysNextLine`, `imports_granularity = Preserve`, - # `unstable_features = true`, etc.). Stable rustfmt warns and - # ignores them, then produces drift on every nightly-formatted - # file because its defaults differ from the unstable settings. - # The format job MUST use nightly rustfmt for the project's chosen - # style to be enforceable. - # - # The compile + clippy jobs stay on 1.95.0 (pinned in - # `rust-toolchain.toml`) — only this fmt job needs nightly. - - uses: dtolnay/rust-toolchain@nightly + # Stable rustfmt 1.95.0 — pinned in `rust-toolchain.toml`. No + # nightly dependency since rustfmt.toml is stable-clean post-PR + # #133. + - uses: dtolnay/rust-toolchain@1.95.0 with: components: rustfmt - run: cargo fmt --all --check diff --git a/src/hpc/clam.rs b/src/hpc/clam.rs index 4b66f4d5..904cedb1 100644 --- a/src/hpc/clam.rs +++ b/src/hpc/clam.rs @@ -1281,7 +1281,7 @@ impl ClamTree { use super::bf16_truth::{AwarenessState, PackedQualia}; use super::causality::{causality_decompose, CausalityDecomposition, NarsTruthValue}; -use super::node::{Node, SPO, S__, _P_, __O}; +use super::node::{Node, _P_, __O, SPO, S__}; use super::plane::Distance as PlaneDistance; /// A verified hit enriched with causal metadata from SPO decomposition. diff --git a/src/hpc/mod.rs b/src/hpc/mod.rs index a862ab2e..cec5b4d4 100644 --- a/src/hpc/mod.rs +++ b/src/hpc/mod.rs @@ -247,7 +247,7 @@ mod e2e_tests { use super::causality::{causality_decompose, CausalityDirection}; use super::clam::{knn_brute, ClamTree}; use super::fingerprint::Fingerprint; - use super::node::{Node, SPO, S__, _P_, __O}; + use super::node::{Node, _P_, __O, SPO, S__}; use super::seal::Seal; #[test] diff --git a/src/hpc/udf_kernels.rs b/src/hpc/udf_kernels.rs index b4b19293..1ff3ff50 100644 --- a/src/hpc/udf_kernels.rs +++ b/src/hpc/udf_kernels.rs @@ -22,7 +22,7 @@ use super::bf16_truth::{bf16_hamming_scalar, BF16Weights}; use super::bitwise::hamming_distance_raw; use super::cascade::Cascade; use super::causality::{causality_decompose, CausalityDirection}; -use super::node::{Node, SPO, S__, _P_, __O}; +use super::node::{Node, _P_, __O, SPO, S__}; use super::plane::Truth; // ============================================================================