Skip to content

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

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.

Activity

  1. added
    engineIssues with the rust-based simulation engine
    on Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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