You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Three invariants were each violated on master and found the hard way during the 2026-06 series; all three are statically checkable in toolchain/mfc/lint_source.py (already CI-gated via precheck):
GPU_DECLARE must live in the module that declares its variables. Violations compile fine on NVHPC and fail only on Cray ftn (ftn-1448) — i.e. the feedback loop runs through Frontier CI, weeks after the commit. This bit the executable-dedup work (fixed in Share the global-parameters core across executables; generate MPI broadcasts; build hygiene #1552) and the rule currently exists only as documentation.
No fypp set-literal loops (#:for x in {...}). Python set iteration order is hash-randomized per process, so emitted code differs between builds — harmless for the constant-assignment sites converted in Phase-2 completion: post-process context types, m_riemann_solvers split, cleanup #1556, but it silently defeats build reproducibility and makes emitted-code diffing (a verification technique the series relied on heavily) noisy. The existing sites are fixed; nothing stops new ones.
Three independent rules in lint_source.py, each with the same shape: parse, check, report file:line with a named rule.
Rule 1: for each $:GPU_DECLARE(create='[vars]'), every variable root must have a ::-declaration in the same file (modulo the generated-include case: declares inside generated includes are co-located by construction). The emission-level checker script used during the dedup work is the prototype — porting it to a source-level lint is mostly regex bookkeeping. Known special cases to encode: struct-member declares (bc_x%vb1) check the root.
Rule 2: trivial — flag #:for ... in { outside comments.
Effort: small (an afternoon each). Risk: minimal — lint-only. Impact: four recurring bug classes become unrecurrable at commit time instead of at Frontier-CI time or never.
Motivation
Three invariants were each violated on master and found the hard way during the 2026-06 series; all three are statically checkable in
toolchain/mfc/lint_source.py(already CI-gated via precheck):#:for x in {...}). Python set iteration order is hash-randomized per process, so emitted code differs between builds — harmless for the constant-assignment sites converted in Phase-2 completion: post-process context types, m_riemann_solvers split, cleanup #1556, but it silently defeats build reproducibility and makes emitted-code diffing (a verification technique the series relied on heavily) noisy. The existing sites are fixed; nothing stops new ones.Proposal & execution sketch
Three independent rules in
lint_source.py, each with the same shape: parse, check, report file:line with a named rule.$:GPU_DECLARE(create='[vars]'), every variable root must have a::-declaration in the same file (modulo the generated-include case: declares inside generated includes are co-located by construction). The emission-level checker script used during the dedup work is the prototype — porting it to a source-level lint is mostly regex bookkeeping. Known special cases to encode: struct-member declares (bc_x%vb1) check the root.#:for ... in {outside comments.@:ALLOCATEd array names vs@:DEALLOCATEd ones; report unmatched. Needs an explicit allowlist mechanism (some arrays are legitimately freed elsewhere or conditionally) — start in warn-only mode for one release, then promote to error with the allowlist populated. Fixing Gs_rs and Res_gs are @:ALLOCATE'd but never deallocated in the Riemann finalizer #1568/Single-precision output arrays (q_sf_s family) are never deallocated in post_process #1569 should precede or accompany enabling it.Effort: small (an afternoon each). Risk: minimal — lint-only. Impact: four recurring bug classes become unrecurrable at commit time instead of at Frontier-CI time or never.