Skip to content

engine: stdlib module output units not propagated to consumers #457

@bpowers

Description

@bpowers

Description

When a stdlib module (smth1/smth3/delay1/delay3) is instantiated, the synthesized module-output variable (e.g. \$⁚persistent_pollution_appearance_rate⁚0⁚delay3·output) does not carry its inferred output units back out to the call site. Consumers of the module output then fail unit checking with does_not_exist on the synthesized name.

Representative CLI output:

units error in model 'main' variable 'persistent_pollution_appearance_rate': does_not_exist -- can't find or no units for dependency '\$⁚persistent_pollution_appearance_rate⁚0⁚delay3·output'
units error in model 'main' variable 'fertility_control_facilities_per_capita': does_not_exist -- can't find or no units for dependency '\$⁚fertility_control_facilities_per_capita⁚0⁚smth3·output'
units error in model 'main' variable 'average_industrial_output_per_capita': does_not_exist -- can't find or no units for dependency '\$⁚average_industrial_output_per_capita⁚0⁚smth1·output'
units error in model 'main' variable 'delayed_industrial_output_per_capita': does_not_exist -- can't find or no units for dependency '\$⁚delayed_industrial_output_per_capita⁚0⁚smth3·output'

Every stdlib-module use site in World3 triggers this. Because the consumer can't resolve the unit of the module output, downstream inference fails and cascades into many of the other unit_mismatch diagnostics in the file.

Why it matters

  • Stdlib smooth and delay modules are the workhorses of system dynamics modeling. Losing their output units breaks unit checking for essentially any non-trivial SD model.
  • Cascading failure: many of the other unit errors in WRLD3 output are downstream consequences of these four representative failures. Fixing this one should dissolve a large block of noise.
  • The module's output unit is well-defined -- for SMTH/DELAY modules it equals the input argument's unit. The failure here is not "unable to infer" but "inferred unit not plumbed to the right place".

Components affected

  • src/simlin-engine/src/units_check.rs -- dependency lookup for module-output synthesized names
  • src/simlin-engine/src/units_infer.rs -- unit inference for module outputs
  • src/simlin-engine/src/db.rs -- salsa tracked function boundaries around stdlib module expansion and unit checking
  • src/simlin-engine/src/builtins_visitor.rs -- where stdlib module instances are synthesized

Possible approaches

  1. During stdlib module expansion, emit a SourceVariable for the synthesized output variable carrying the inferred unit (derived from the input argument's unit). The existing unit inference and lookup machinery then handles the rest unmodified.
  2. Teach the dependency lookup in units_check to recognize the \$⁚...⁚N⁚<mod>·output naming convention and resolve it by walking into the stdlib model instance to read the output variable's unit there.
  3. Expose the module-output unit via a side table keyed by the synthesized name.

Option 1 aligns with how the rest of the compiler already handles variables and avoids naming-convention coupling between the unit checker and the module expansion code.

Context

Discovered while fixing the delay3 conflation bug in commit 6d48816. Distinct from #421 (closed): that issue covered unit constraint propagation through module arguments (inputs); this one is about the module outputs not being visible to downstream consumers.

Related: #35 (general unit checking tracker), #421 (closed, for input-side propagation).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions