chore(edition): port to Rust 2024 + declare MSRV 1.85 (#401) - #406
Conversation
A (#402): edition 2021 -> 2024. cargo fix --edition made no auto-edits; the only behavioral-adjacent change is approximate_eq rewritten to the 2024-safe tail-expr drop-order form (bind owned intermediate before the borrowing iterator) -- numerical logic unchanged. B (#403): #[allow] -> #[expect] where the lint still fires under --all-features; #[allow] retained where the lint does not fire (avoids unfulfilled_lint_expectations). C (#404): declare rust-version = "1.85" in Cargo.toml and add an msrv CI job that builds with dtolnay/rust-toolchain@1.85.0 to verify the claim. Added [lints.rust] unexpected_cfgs check-cfg table for cfg(coverage, coverage_nightly) and cfg(tarpaulin). Also: - AGENTS.md: document edition-2024 invariants (no RPIT, explicit dyn Trait + 'a, tail-expr drop-order, lint-suppression policy, unsafe stance) and the 'preserve bespoke numerical-system logic and performance' constraint for non-behavioral refactors. - svm/svc.rs: drop two redundant let-and-return tails surfaced by the 2024 clippy::let_and_return lint. - preprocessing/categorical.rs: keep nested-if (annotated #[allow(clippy::collapsible_if)]) because collapsing to a let-chain needs let-chains, unstable until 1.88 -- incompatible with MSRV 1.85. - cargo fmt normalization across the tree. D (#368, unsafe -> split_at_mut) is deferred to its own PR per the 'preserve numerical logic' constraint. Verified: fmt=0, clippy --all-features -Drust-2018-idioms -Drust-2024-compatibility -Dwarnings=0, test --all-features=0 (474 unit + 68+3 doctests), cargo +1.85.0 build --all-features=0. Bump 0.6.1 -> 0.6.2.
- Install pin: ^0.5.3 -> ^0.6 (current is 0.6.2). - Quick-start example: fix .unwrap -> .unwrap() (was a real typo that would not compile as a doctest). - Roadmap: 'Move to Rust 2021 edition' -> 'Move to Rust 2024 edition (MSRV 1.85)'. - Contributing: note MSRV 1.85 / edition 2024 alongside 'stable Rust'. - Replace stale 'v0.4 API' prose references with version-agnostic 'smartcore API' wording to stop the version label going stale again.
Overall AssessmentPR #406 is a thorough, disciplined Rust 2024 migration. The scope is clearly bounded — A (edition flip), B ( A — Edition flip (
|
| Location | Severity | Note |
|---|---|---|
linalg/basic/arrays.rs::approximate_eq |
🟡 Minor | Simplify to let diff = self.sub(other); diff.iterator(0).all(...) — removes need for #[expect] entirely |
logistic_regression.rs |
🟡 Minor | Second #[allow(clippy::ptr_arg)] on adjacent method lacks an explanation comment; add // lint does not fire here |
.github/workflows/ci.yml |
🟠 Fix | TZ: "/usr/share/zoneinfo/your/location" is an unfilled placeholder — remove it |
.github/workflows/ci.yml |
🟡 Minor | msrv job has no needs: — consider adding to avoid wasted runner time on upstream failures |
numbers/floatnum.rs, numbers/realnum.rs |
🟡 Style | ln_1pe collapsed to one-liner by cargo fmt; consider #[rustfmt::skip] if numeric code readability is preferred |
The TZ placeholder is the only item that should be fixed before merge — it's a broken template artifact. Everything else is polish. PR #406 is ready to merge once the TZ line is removed.
Sources
[1] chore(edition): port to Rust 2024 + declare MSRV 1.85 (#401) by Mec-iS · Pull Request #406 · smartcorelib/smartcore #406
Per PR #406 review feedback: - ci.yml: remove the unfilled TZ template placeholders from all three jobs (broken template artifact; Rust builds don't depend on TZ). - arrays.rs::approximate_eq: drop the redundant let result = ...; result + the #[expect(clippy::let_and_return)] — under edition 2024 the drop order changed so the simpler form compiles cleanly (no E0597, no clippy warning). Numerical logic unchanged.
Summary
Complete fix for #401 — the edition-2024 porting epic. Closes #402 (A), #403 (B), #404 (C). D (#368,
unsafe→split_at_mut) is deliberately deferred to its own PR: the bespoke raw-pointer iteration logic inmatrix.rs::iterator_mutmust be preserved per the "keep numerical-system logic and performance" constraint, and a safe rewrite deserves a dedicated review.Changes
A — Edition flip (#402)
edition = "2021"→"2024"inCargo.toml.cargo fix --editionmade zero auto-edits. The only behavioral-adjacent change:linalg/basic/arrays.rs::approximate_eqrewritten to the 2024-safe tail-expr drop-order form — bind the owned intermediate (self.sub(other)) before the borrowing iterator, instead of chaining(self.sub(other)).iterator(0).all(...)in tail position (2024 reorders temporaries → the borrow would dangle). Numerical logic unchanged, only structural form. Annotated#[expect(clippy::let_and_return)]because this binding is load-bearing, not redundant.AGENTS.mdupdated: edition line + a new "Edition 2024 invariants" section.B —
#[allow]→#[expect](#403)#[allow(...)]→#[expect(...)]at every site where the lint still fires under--all-features(verifies the suppression is honest).#[allow]at ~19 sites where the lint does not fire (e.g.clippy::ptr_arg,upper_case_acronyms, severaldead_code) — converting those to#[expect]would tripunfulfilled_lint_expectations. Choice follows the TDD-skill guidance:#[expect]only where the lint actually fires.lib.rsblock split: 4 lints kept as#![expect], 2 demoted to#![allow].C — MSRV declaration + CI verification (#404)
rust-version = "1.85"inCargo.toml(edition 2024 stabilized in 1.85).msrvjob inci.yml: builds withdtolnay/rust-toolchain@1.85.0(both--all-featuresand no-features) — this actually verifies the MSRV claim, not just declares it.[lints.rust] unexpected_cfgscheck-cfgtable added forcfg(coverage, coverage_nightly)andcfg(tarpaulin)(edition-2024unexpected_cfgslint).cargo +1.85.0 build --all-featuresand the-Drust-2024-compatibilityclippy group.Other
svm/svc.rs: removed two redundantlet svc = ...; svctail expressions surfaced by the 2024clippy::let_and_returnlint.preprocessing/categorical.rs: kept the nested-ifform (annotated#[allow(clippy::collapsible_if)]). Collapsing to alet-chain requires let-chains, which stabilized only in Rust 1.88 — incompatible with the declared MSRV 1.85. This was discovered by runningcargo +1.85.0 build(not by guessing).cargo fmtnormalization across the tree (CI enforces--check).Pre-migration audit (verified, read-only)
-> impl Traitreturns (zero RPIT) → no lifetime over-capture regression.dyn Traitalready carry explicit+ 'alifetimes → no dyn-elision surprise.cfg(coverage)/cfg(tarpaulin)in source →unexpected_cfgsonly needs the Cargo.toml declaration.unsafe {}blocks inmatrix.rs— untouched here (deferred to tech-debt: replace unsafe raw-pointer iterator_mut in DenseMatrix (basic/matrix.rs) with safe split_at_mut approach #368).Verification (run, not guessed)
cargo fmt --all -- --checkcargo clippy --all-features -- -Drust-2018-idioms -Drust-2024-compatibility -Dwarningscargo test --all-featurescargo +1.85.0 build --all-features(MSRV)cargo +1.85.0 build(no features, MSRV)Version bumped
0.6.1→0.6.2; CHANGELOG updated under[0.6.2].Checklist
developmentcargo fmt --all -- --checkcargo clippy --all-features -- -Drust-2018-idioms -Dwarningscargo clippy --all-features -- -Drust-2024-compatibility -Dwarningscargo test --all-featuresCloses #401, #402, #403, #404.