Rust edition 2024: the whole tree, with the env-mutation class made visible (WP20) #177

Merged
enricobuehler merged 2 commits from worktree-edition-2024 into main 2026-08-12 15:38:25 +00:00
Owner

The rust-safety programme's §8.4 (WP20), worked from design/rust-safety-edition-2024-handoff.md. std::env::set_var/remove_var are unsafe fn in edition 2024 — the structural fix for the blind spot the programme found the hard way: the 972af299 environ data race lived in a file containing zero occurrences of the word unsafe, invisible to the census.

What this does

  • Manifests: [workspace.package] edition 2021→2024, rust-version 1.82→1.85 (pinned toolchain is 1.96.0 — no toolchain bump, only the declared floor rises). The 13 crates pinning edition = "2021" literally now inherit it (the root bump alone reaches only edition.workspace = true crates). pf-vkhdr-layer (separate workspace) bumped too; the four vendored crates (fec-rs, cros-codecs, usbip-sim, patched ndk) stay on 2021 deliberately.
  • Mechanical, done textually across all cfg branches so no platform's half is left behind: 150 #[unsafe(no_mangle)] (incl. the two entry points #173–#176 added on main), 12 unsafe extern blocks, gengeneration renames (pf-vdisplay generation stamps, WinUI animation counters — identifiers only, no serde surface), two match-ergonomics reference patterns.
  • Every env-mutation site (20 files) now carries an unsafe block with a real SAFETY proof citing the actual serialization argument (ENV_LOCK, CONFIG_DIR_TEST_LOCK, ART_ROOTS_LOCK, vkdecode's gpu_lock, the --test-threads=1 hardware-spike contracts, or single-threaded startup). identity/mgmt take native's existing #[cfg_attr(not(test), forbid(unsafe_code))] carve-out — shipped code keeps the forbid.
  • Two genuine env races found and fixed en route (exactly the class this migration exists to surface): the Windows service spawned the network-profile warner thread before load_host_env()'s set_var loop, and pf-console-ui's fake_home() re-set HOME outside its OnceLock on every call, so parallel tests raced the write.
  • cbindgen: 0.29.4 parses the new syntax; header regenerates byte-identical. The ci.yml drift check could never catch "failed to regenerate" (build.rs demotes cbindgen failure to a warning, leaving the header untouched and the diff clean) — the step now asserts the punktfunk-core: wrote line and the absence of cbindgen failed first.
  • rustfmt: new root rustfmt.toml pins style_edition = "2021" — the edition bump would otherwise flip the style edition and reformat ~370 untouched files inside this PR. The drivers workspace pins its already-current 2024. Adopting 2024 style tree-wide is its own future one-line-plus-reformat commit.
  • Census: moves UP by design — 2435 → 2453 operations, unsafe blocks 1534 → 1577, env_set_var now a counted category (45). The newly counted sites are a truer number, not a regression. Hygiene gate C's header and shrunk baselines updated in the same commit.
  • Newly-unlocked lints fixed: 10 collapsible_if let-chain collapses; the two let_and_return bindings that existed only because of the 2021 tail-expression temporary rule (their comments said so) are inlined; the tray's MAKEINTRESOURCE(1) cast now spells ptr::without_provenance(1) — clippy's suggested ptr::dangling() would be address 2, silently the wrong resource ordinal.

Verification

  • macOS: workspace check, fmt parity, cbindgen header byte-identical.
  • .25 (Linux): fmt, workspace clippy -D warnings, feature (nvenc,vulkan-encode,pyrowave) + native-only clippy legs, 1171 workspace tests.
  • .133 (Windows): all windows-host.yml clippy invocations --release -D warnings, pf-capture + pf-vdisplay test suites, the drivers-workspace clippy line, and a client leg (pf-client-core + punktfunk-client-windows — no host leg compiles those).
  • Drop order (the semantic change most likely to bite): -W tail-expr-drop-order reports zero findings on all three platforms' halves of pf-encode/pf-zerocopy/pf-capture/pf-frame/pf-vdisplay. One flake surfaced and was exonerated by A/B: pf-zerocopy's recv_keeps_the_first_fd_and_closes_the_rest fails ~1/20 parallel runs on both editions — a pre-existing fd race, not a drop-order regression.

Still owed after merge: the four #[ignore]d alloc/drop-cycle hardware runs, and the aarch64 clippy leg (this PR's CI run is its first look at the migrated tree).

The rust-safety programme's §8.4 (WP20), worked from `design/rust-safety-edition-2024-handoff.md`. `std::env::set_var`/`remove_var` are `unsafe fn` in edition 2024 — the structural fix for the blind spot the programme found the hard way: the `972af299` environ data race lived in a file containing zero occurrences of the word `unsafe`, invisible to the census. ## What this does - **Manifests**: `[workspace.package]` edition 2021→2024, `rust-version` 1.82→1.85 (pinned toolchain is 1.96.0 — no toolchain bump, only the declared floor rises). The 13 crates pinning `edition = "2021"` literally now inherit it (the root bump alone reaches only `edition.workspace = true` crates). pf-vkhdr-layer (separate workspace) bumped too; the four vendored crates (fec-rs, cros-codecs, usbip-sim, patched ndk) stay on 2021 deliberately. - **Mechanical, done textually across all cfg branches** so no platform's half is left behind: 150 `#[unsafe(no_mangle)]` (incl. the two entry points #173–#176 added on main), 12 `unsafe extern` blocks, `gen` → `generation` renames (pf-vdisplay generation stamps, WinUI animation counters — identifiers only, no serde surface), two match-ergonomics reference patterns. - **Every env-mutation site (20 files) now carries an `unsafe` block with a real SAFETY proof** citing the actual serialization argument (`ENV_LOCK`, `CONFIG_DIR_TEST_LOCK`, `ART_ROOTS_LOCK`, vkdecode's `gpu_lock`, the `--test-threads=1` hardware-spike contracts, or single-threaded startup). `identity`/`mgmt` take `native`'s existing `#[cfg_attr(not(test), forbid(unsafe_code))]` carve-out — shipped code keeps the forbid. - **Two genuine env races found and fixed en route** (exactly the class this migration exists to surface): the Windows service spawned the network-profile warner thread *before* `load_host_env()`'s `set_var` loop, and pf-console-ui's `fake_home()` re-set `HOME` outside its `OnceLock` on every call, so parallel tests raced the write. - **cbindgen**: 0.29.4 parses the new syntax; header regenerates byte-identical. The ci.yml drift check could never catch "failed to regenerate" (build.rs demotes cbindgen failure to a warning, leaving the header untouched and the diff clean) — the step now asserts the `punktfunk-core: wrote` line and the absence of `cbindgen failed` first. - **rustfmt**: new root `rustfmt.toml` pins `style_edition = "2021"` — the edition bump would otherwise flip the style edition and reformat ~370 untouched files inside this PR. The drivers workspace pins its already-current 2024. Adopting 2024 style tree-wide is its own future one-line-plus-reformat commit. - **Census**: moves UP by design — 2435 → 2453 operations, unsafe blocks 1534 → 1577, `env_set_var` now a counted category (45). The newly counted sites are a truer number, not a regression. Hygiene gate C's header and shrunk baselines updated in the same commit. - **Newly-unlocked lints fixed**: 10 `collapsible_if` let-chain collapses; the two `let_and_return` bindings that existed only because of the 2021 tail-expression temporary rule (their comments said so) are inlined; the tray's `MAKEINTRESOURCE(1)` cast now spells `ptr::without_provenance(1)` — clippy's suggested `ptr::dangling()` would be address 2, silently the wrong resource ordinal. ## Verification - **macOS**: workspace check, fmt parity, cbindgen header byte-identical. - **.25 (Linux)**: fmt, workspace clippy `-D warnings`, feature (`nvenc,vulkan-encode,pyrowave`) + native-only clippy legs, 1171 workspace tests. - **.133 (Windows)**: all windows-host.yml clippy invocations `--release -D warnings`, pf-capture + pf-vdisplay test suites, the drivers-workspace clippy line, and a client leg (pf-client-core + punktfunk-client-windows — no host leg compiles those). - **Drop order** (the semantic change most likely to bite): `-W tail-expr-drop-order` reports **zero findings on all three platforms' halves** of pf-encode/pf-zerocopy/pf-capture/pf-frame/pf-vdisplay. One flake surfaced and was exonerated by A/B: pf-zerocopy's `recv_keeps_the_first_fd_and_closes_the_rest` fails ~1/20 parallel runs on **both** editions — a pre-existing fd race, not a drop-order regression. Still owed after merge: the four `#[ignore]`d alloc/drop-cycle hardware runs, and the aarch64 clippy leg (this PR's CI run is its first look at the migrated tree).
enricobuehler added 2 commits 2026-08-12 15:29:15 +00:00
The safety half of the rust-safety programme's §8.4: `std::env::set_var`/`remove_var` are
`unsafe fn` in edition 2024, converting the class of bug the programme found the hard way
(the 972af299 environ data race lived in a file with ZERO occurrences of the word
`unsafe`) from invisible to counted and compiler-enforced.

Manifests: [workspace.package] edition 2021→2024, rust-version 1.82→1.85 (the pinned
toolchain is 1.96.0, so no toolchain bump — only the declared floor rises); the 13 crates
pinning `edition = "2021"` literally now inherit it (Trap 1: the root bump alone reaches
only `edition.workspace = true` crates and would have left pf-encode/pf-capture/pf-inject
et al. on 2021 while reading as complete); pf-driver-proto's stale rust-version 1.82 pin
now inherits; pf-vkhdr-layer (a separate workspace, inherits nothing) bumped to 2024. The
four vendored crates (fec-rs, cros-codecs, usbip-sim, the patched ndk) stay on 2021
deliberately — upstream code stays pristine. The excluded usbip-poc standalone PoC is
untouched.

Mechanical, done textually across ALL cfg branches so no platform's half is left behind
(Trap 3 — 44% of the host's unsafe is Windows-only and a one-platform `cargo fix` misses
it): 148 `#[no_mangle]` → `#[unsafe(no_mangle)]` (83 in abi.rs); 12 bare extern blocks →
`unsafe extern`; `gen` is a reserved keyword, so pf-vdisplay's generation stamps
(registry.rs, windows/manager.rs) and the WinUI shell's animation counters rename
gen → generation (internal identifiers only, no serde/wire surface); two
match-ergonomics patterns take the compiler's suggested reference form.

env mutation: every `set_var`/`remove_var` site (20 files) now sits in an `unsafe` block
whose SAFETY comment states the real serialization argument (pf-vdisplay's ENV_LOCK,
CONFIG_DIR_TEST_LOCK, ART_ROOTS_LOCK, vkdecode's gpu_lock, the `--test-threads=1`
contracts of the hardware spikes, or single-threaded startup). Two genuine hazards
surfaced en route — exactly the WP3b-class finds this migration exists to make visible —
and are fixed here:
- windows/service.rs spawned the network-profile warner thread BEFORE `load_host_env()`,
  so a child-spawning thread (child spawn snapshots the env block) was live while
  `set_var` ran in a loop; the load now precedes the spawn.
- pf-console-ui's `fake_home()` re-set HOME outside its OnceLock on EVERY call, so two
  parallel tests could race the write; the set now happens exactly once inside
  `get_or_init`.

cbindgen (Trap 2): 0.29.4 parses `#[unsafe(no_mangle)]` — verified empirically; the
header regenerates byte-identical. The ci.yml drift check could never catch "failed to
regenerate" (build.rs demotes a cbindgen failure to a warning and writes nothing, leaving
the checked-in header untouched and the diff clean), so the step now first asserts the
"punktfunk-core: wrote" line and the absence of "cbindgen failed" (sh -e safe: no `!`
pipeline, no tee-masked exit).

rustfmt: style_edition pinned to 2021 at the root — edition 2024 would otherwise flip the
style edition and reformat ~370 untouched files inside this same commit, burying the
migration diff. The drivers workspace pins its already-current 2024 style. Adopting the
2024 style tree-wide is its own future one-line-plus-reformat commit.

Census: the primary metric moves UP BY DESIGN — 2435 → 2453 operations, unsafe blocks
1534 → 1577, and env_set_var is now a counted category (45 ops). The newly counted env
sites are a truer number, not a regression; baseline snapshot saved as punktfunk-planning
design/rust-safety-census-baseline-2026-08-12-edition-2024.txt. Gate C's env ratchet is
now compiler-enforced (the hygiene-script header says so); the two shrunk file counts
(nvenc_cuda 49→2 via the test helpers, shell/tests 2→1) are lowered in the same commit
per the gate's own rule.

Drop order (the semantic change most likely to bite this codebase): the migration lint
`-W tail-expr-drop-order` reports zero findings on the macOS-visible halves of
pf-encode / pf-zerocopy / pf-capture / pf-frame; the Linux and Windows halves run the
same lint on the gate boxes. The four #[ignore]d alloc/drop-cycle tests on the hardware
boxes remain owed, as before this change.
Merge remote-tracking branch 'origin/main' into worktree-edition-2024
ci / bun-nix (pull_request) Successful in 24s
windows-drivers / probe-and-proto (pull_request) Successful in 34s
ci / docs-site (pull_request) Successful in 1m23s
apple / swift (pull_request) Successful in 1m45s
apple / screenshots (pull_request) Skipped
ci / web (pull_request) Successful in 3m4s
windows-drivers / driver-build (pull_request) Successful in 2m23s
ci / rust (pull_request) Failing after 4m6s
ci / rust-arm64 (pull_request) Failing after 5m5s
windows / build (x86_64-pc-windows-msvc) (pull_request) Failing after 1m54s
nix / flake (pull_request) Successful in 13m36s
windows / build (aarch64-pc-windows-msvc) (pull_request) Failing after 54s
android / android (pull_request) Successful in 15m6s
c68e0be688
enricobuehler merged commit b385f0a031 into main 2026-08-12 15:38:25 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: unom/punktfunk#177