Skip to content

engine: Arrayed/ApplyToAll equation on a variable with no declared dimensions is silently collapsed to scalar instead of rejected #697

@bpowers

Description

@bpowers

Problem

A datamodel::Variable (Flow, and presumably Aux/Stock as well) declared with no dimensions but given an Equation::Arrayed(dims, per_element_equations, ...) (or Equation::ApplyToAll) body is silently accepted by the engine and collapsed to a scalar node. No compile error or diagnostic is produced.

This is structurally inconsistent: the variable carries per-element equations over dimensions it does not declare, yet the engine treats it as a plain scalar.

Concrete example

A datamodel::Variable::Flow with no declared dimensions whose equation is:

Equation::Arrayed(
    dims,                    // non-empty
    per_element_equations,   // one entry per element
    default,
    has_except_default,
)

The engine compiles this without error, emitting a scalar (slot-0) node rather than rejecting the malformed variable.

Why it matters

The mismatch silently degrades downstream analyses. It was discovered during LTM (Loops That Matter) review: a hand-constructed fixture with this shape produced all-zero link scores with no diagnostic, which made it look like LTM itself was broken when in fact the model was malformed. A modeler (or a buggy importer) hitting this gets plausible-looking but wrong results with no signal that anything is off.

This is an engine validation gap, not LTM-specific -- the same silent collapse would mis-feed any analysis that depends on a variable's declared dimensionality matching its equation shape.

Expected behavior

datamodel validation (or model lowering) should reject an Arrayed/ApplyToAll equation on a variable that declares no dimensions, with a clear error that names the offending variable. The arrayed equation's dimension list and the variable's declared dimensions should be required to agree.

Component(s) affected

  • src/simlin-engine -- datamodel validation / model lowering. Equation is defined in src/simlin-engine/src/datamodel.rs (the Arrayed / ApplyToAll variants). The collapse-to-scalar happens during the lowering/compilation pipeline.

Possible approaches

  1. Add a validation check (datamodel-level or in the salsa parse/lower path, e.g. parse_source_variable / lower_var_fragment) that emits an Error-severity Diagnostic when a variable with an empty declared-dimension set carries an Arrayed or ApplyToAll equation.
  2. Conversely, require the Arrayed/ApplyToAll dimension list to be consistent with the variable's declared dimensions, naming the variable in the error.

Severity

Low -- only hand-constructed models or a buggy importer would produce this shape; well-formed XMILE/MDL imports declare dimensions alongside arrayed equations. But because it fails silently and corrupts downstream analysis results, it is worth a guard.

Discovery context

Identified during a deep LTM review while constructing test fixtures: an arrayed-equation Flow with dimensions: [] compiled cleanly and yielded all-zero LTM link scores with no diagnostic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    engineIssues with the rust-based simulation engine

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions