Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -477,3 +477,36 @@ jobs:
1. Review the changelog fragment in this PR
2. Merge this PR to main
3. The automated release workflow will publish to crates.io and create a GitHub release

# === DEPLOY RUST DOCUMENTATION ===
# Deploy generated Rust documentation to GitHub Pages after a successful release
deploy-docs:
name: Deploy Rust Documentation
needs: [auto-release, manual-release]
# Run if either release job succeeded (the other will be skipped)
if: |
always() && !cancelled() && (
needs.auto-release.result == 'success' ||
needs.manual-release.result == 'success'
)
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: main

- name: Setup Rust
uses: dtolnay/rust-toolchain@stable

- name: Build documentation
run: cargo doc --no-deps

- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: rust/target/doc
destination_dir: rust
keep_files: true
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Thank you for your interest in contributing! This document provides guidelines a
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

This project uses a specific nightly toolchain. It will be automatically selected when you run cargo commands due to `rust/rust-toolchain.toml`.
This project uses the stable toolchain. It will be automatically selected when you run cargo commands due to `rust/rust-toolchain.toml`.

3. **Install development tools**

Expand Down
21 changes: 21 additions & 0 deletions changelog.d/20260411_000000_edition_2024_audit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
bump: minor
---

### Changed
- Upgrade Rust edition from 2021 to 2024 (stable since Rust 1.85)
- Bump MSRV from 1.70 to 1.85 (required for edition 2024)
- Move tests from `src/imp.rs` to `tests/traits.rs` as proper integration tests

### Fixed
- Fix CONTRIBUTING.md incorrectly stating "nightly toolchain" (project uses stable)
- Fix README.md showing outdated install version `0.4` instead of `0.5`
- Regenerate Cargo.lock to match current version (0.5.0)

### Added
- Implement `for_each_integer_type!` macro (resolves TODO)
- Document IDE alias design decision for `LinkReference` trait (resolves TODO)
- Add 8 new integration tests (total: 75 integration + 6 doc tests)
- Add crate-level documentation in `lib.rs`
- Add automated rustdoc deployment to GitHub Pages after release
- Add case study documentation for issue #142 audit findings
154 changes: 154 additions & 0 deletions docs/case-studies/issue-142/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Case Study: Issue #142 — Rust Best Practices Audit and Edition 2024 Migration

## Overview

- **Issue:** [#142](https://github.com/linksplatform/Numbers/issues/142)
- **PR:** [#143](https://github.com/linksplatform/Numbers/pull/143)
- **Date:** 2026-04-11
- **Status:** Audited and fixed.

---

## Issue Requirements

The issue requested a comprehensive audit of the Rust codebase:

1. **Verify no non-stable Rust features are used** — ensure the crate compiles on stable Rust without any `#![feature(...)]` flags.
2. **Use latest versions of dependencies** — check all dependencies are at their latest stable versions.
3. **Use latest stable version of Rust** — update the edition and MSRV to the latest stable.
4. **Ensure highest possible code quality** — apply latest Rust best practices.
5. **Sync documentation with code** — verify docs fully describe all features.
6. **Compile case study data** — document findings in `docs/case-studies/issue-142/`.

---

## Audit Findings

### 1. Non-Stable Features

**Finding:** The crate uses **no non-stable features**. No `#![feature(...)]` attributes are present anywhere in the source code. The `rust-toolchain.toml` correctly specifies `channel = "stable"`.

**Verdict:** ✅ Compliant — no action needed.

### 2. Dependencies

**Finding:** The only dependency is `num-traits`, which was already at the latest version (`0.2.19`). The `num-traits` crate is the de facto standard for generic numeric programming in Rust, maintained by the `rust-num` project. No alternative crate offers equivalent functionality with better maintenance or API design.

**Verdict:** ✅ Already up-to-date — no action needed.

### 3. Rust Edition and MSRV

**Finding:** The crate used `edition = "2021"` and `rust-version = "1.70"`.

- **Rust Edition 2024** was stabilized on 2025-02-20 with Rust 1.85.0 ([announcement](https://blog.rust-lang.org/2025/02/20/Rust-1.85.0/)).
- Edition 2024 is now widely adopted and brings improvements to lifetime capture rules, match ergonomics, and macro fragment specifiers.
- The crate migrated cleanly to Edition 2024 with zero code changes required.

**Action taken:** Updated `edition` to `"2024"` and `rust-version` to `"1.85"`.

### 4. Code Quality

**Finding:** The code quality was already high:

- **Clippy:** Zero warnings with all targets and features enabled.
- **Formatting:** Fully compliant with `rustfmt`.
- **Tests:** 75 integration tests + 6 doc tests, all passing.
- **Architecture:** Clean trait design with blanket implementations and zero-cost abstractions.

**Improvements made:**

- **Implemented `for_each_integer_type!` macro:** The original TODO comment `// TODO: Create macro foreach` requested a macro to DRY up repetitive per-type macro invocations. Implemented the `for_each_integer_type!` helper macro that invokes a given macro for all 12 primitive integer types.
- **Documented IDE alias design decision:** The original TODO comment `// TODO: Not use alias - IDEs does not support it` was about the `LinkReference` trait listing supertraits explicitly. Added a `# Design note` in the doc comment explaining why aliases are not used (IDE compatibility).
- **Moved tests to `tests/` directory:** All unit tests were in `src/imp.rs`. Moved them to `rust/tests/traits.rs` as proper integration tests, following Rust best practices for separation of tests from source code.
- **Added new tests:** Added 8 additional integration tests covering `ToPrimitive`, `PrimInt` operations, `FromPrimitive`, `Send + Sync`, `Display`, `Hash`, and overflow scenarios. Total: 75 integration tests + 6 doc tests = 81 tests.
- **Cargo.lock version mismatch:** Lock file showed version `0.4.0` while `Cargo.toml` was at `0.5.0`. Regenerated.

### 5. Documentation Sync

**Findings and fixes:**

| Document | Issue | Fix |
|----------|-------|-----|
| `rust/README.md` | Installation example showed `platform-num = "0.4"` | Updated to `"0.5"` |
| `CONTRIBUTING.md` | Stated project uses "a specific nightly toolchain" | Corrected to "the stable toolchain" |
| `rust/src/lib.rs` | No crate-level documentation | Added comprehensive module-level docs with trait summary table and example |
| `rust/src/imp.rs` | All five traits have `///` docs with examples | Already in sync — enhanced `LinkReference` with design note |

### 6. Automated Documentation Generation

**Finding:** The C# part of the project already has automated docs via `docfx`, deployed to GitHub Pages at `csharp/` subdirectory on the `gh-pages` branch.

**Action taken:** Added a `deploy-docs` job to the main `.github/workflows/rust.yml` workflow that:
- Runs only after a successful release (auto-release or manual-release)
- Checks out the `main` branch to get the released code
- Runs `cargo doc --no-deps` to generate HTML documentation
- Deploys to `rust/` subdirectory on the `gh-pages` branch
- Uses `peaceiris/actions-gh-pages@v4` (same approach as the C# docs)

This ensures Rust documentation is regenerated and published only when a new version is released, matching the project's release-driven documentation strategy.

---

## Solution Plan

### Approach: Targeted Improvements

1. **Edition upgrade (2021 → 2024):** Adopts the latest stable edition, bringing the crate in line with modern Rust ecosystem standards. Zero code changes required.

2. **MSRV bump (1.70 → 1.85):** Required by Edition 2024. The MSRV-aware resolver (stabilized in Rust 1.84) ensures downstream users on older toolchains automatically get compatible older versions.

3. **Documentation improvements:** Fixed factual inaccuracies, added crate-level docs, enhanced trait documentation with design notes.

4. **TODO resolution:** Instead of removing TODOs, implemented the requested `for_each_integer_type!` macro and documented the IDE alias design decision.

5. **Test restructuring:** Moved tests from `src/` to `tests/` directory and added new test coverage.

6. **Automated docs deployment:** Integrated Rust documentation generation and GitHub Pages deployment into the main CI/CD workflow, triggered after successful releases.

---

## Research: Related Tools and Libraries

### Alternatives to `num-traits`

| Crate | Description | Assessment |
|-------|-------------|------------|
| [`num-traits`](https://crates.io/crates/num-traits) (current) | Standard numeric traits for Rust | Best choice — 667M+ downloads, stable API, active maintenance |
| [`num`](https://crates.io/crates/num) | Full numeric library (includes num-traits) | Heavier — unnecessary for trait-only usage |
| [`num-integer`](https://crates.io/crates/num-integer) | Integer-specific traits | Too narrow — doesn't provide PrimInt, Signed, etc. |

**Conclusion:** `num-traits` remains the optimal dependency for this crate's use case.

### Rust Edition 2024 Key Changes

The following Edition 2024 changes were evaluated for impact on this crate:

| Change | Impact on `platform-num` |
|--------|--------------------------|
| RPIT lifetime capture | None — crate doesn't use `impl Trait` in return position |
| `if let` temporary scope | None — no `if let` in trait definitions |
| Match ergonomics refinements | None — no pattern matching in trait code |
| `expr` macro fragment changes | None — macros use `$T:ty`, not `$e:expr` |
| Prelude additions (Future, IntoFuture) | None — crate is synchronous |

**Result:** Clean migration with zero code changes.

### Rust Documentation Generation

For Rust projects, `cargo doc` is the standard documentation generator (equivalent to C#'s `docfx`). It:
- Parses `///` and `//!` doc comments using Markdown
- Generates cross-linked HTML with search
- Supports code examples that are compiled and tested (`cargo test --doc`)
- Is built into the Rust toolchain — no additional dependencies needed

---

## Verification

All quality checks pass after changes:

- `cargo fmt --check` — ✅ clean
- `cargo clippy --all-targets --all-features` — ✅ zero warnings
- `cargo test --all-features` — ✅ 75 integration tests + 6 doc tests pass
- `cargo doc --no-deps` — ✅ documentation generates successfully
- Edition 2024 compilation — ✅ no migration issues
2 changes: 1 addition & 1 deletion rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "platform-num"
version = "0.5.0"
edition = "2021"
rust-version = "1.70"
edition = "2024"
rust-version = "1.85"
authors = ["uselesssgoddess", "Linksplatform Team <linksplatformtechnologies@gmail.com>"]
license = "Unlicense"
repository = "https://github.com/linksplatform/Numbers"
Expand Down
2 changes: 1 addition & 1 deletion rust/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Add to your `Cargo.toml`:

```toml
[dependencies]
platform-num = "0.4"
platform-num = "0.5"
```

## Usage
Expand Down
Loading
Loading