Skip to content

Build-time consistency audit: parameter registry vs Fortran derived types #1573

@sbryngelson

Description

@sbryngelson

Motivation

The single largest bug class found during the 2026-06 refactoring series (#1550-#1572) was mirror drift: a parameter or type member added or removed on one side of a manual mirror without its counterpart. The starkest instance was #1562 — fourteen parameters registered in the toolchain whose Fortran type members had been removed a year earlier; setting any of them in a case file passed validation and then crashed the namelist read with a misleading datatype error.

The registry (toolchain/mfc/params/definitions.py) and the derived types (src/common/m_derived_types.fpp) are maintained by hand on both sides, with nothing checking they agree. #1553 fixed the current instances; nothing prevents recurrence.

Proposal

A build-time audit, run by the same ninja-tracked custom command that already generates the parameter includes (so it costs nothing extra to wire), that:

  1. Parses the struct-member declarations from m_derived_types.fpp for every type backing an indexed parameter family (fluid_pp, patch_icpp, bub_pp, lag_params, chem_params, ...).
  2. Asserts every registered member name + Fortran type class (REAL/INT/LOG/STR) exists in the corresponding derived type, and that every namelist-bound member of those types is registered.
  3. Fails the build with a named, two-sided diff on any mismatch ("registered but not in type: ...", "namelist-bound member not registered: ...").

Execution sketch

  • A new toolchain/mfc/params/generators/type_audit.py (~150 lines): a line-level Fortran declaration parser scoped to the known type blocks (the codebase's declaration style is uniform enough; the broadcast generator already does similar member-walking).
  • Wire into cmake_gen.py after generation; unit tests in params_tests/ with deliberately broken fixtures (member removed, member added, kind mismatch).
  • Validation: mutate one member locally and confirm the build fails with the named diff; then run the audit against current master to confirm it passes clean (it should, post-Fix three pre-existing multi-rank broadcast defects; deregister dead parameters #1553).
  • Effort: small (one toolchain file + tests). Risk: low — it only ever fails builds that would mis-run anyway.

Part of the structural theme proven by the series: make invariants structural, not disciplinary. Companion proposals: the registry-driven defaults and the validator/checker unification.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions