ADR-012: Skip Semantic Validation on Unresolved References
Context
Langium’s parser uses error recovery and runs validators even on partial ASTs where cross-references have not resolved. When a decider references a command that does not exist, Langium’s linker already emits “Could not resolve reference to ‘X’.” The question is whether semantic validators — exhaustiveness, totality, guard consistency — should also report errors against these incomplete ASTs.
Two options:
- Run semantic validators regardless; emit duplicate errors when references are missing.
- Guard every semantic validator against unresolved references; skip affected entries silently.
Decision
Semantic validation checks skip AST nodes with unresolved cross-references. Each validation function null-guards reference access (ref?.name) and skips entries where ref is undefined.
Rationale derives from the F-algebra model (ADR-005): an unresolved reference is an undefined morphism. The algebra cannot be checked for totality or exhaustiveness when the carrier set is incomplete. The correct response is to report carrier incompleteness (the linking error) and defer structural checks until all morphisms resolve. Emitting a second diagnostic from a semantic validator would be noise, not signal.
Rule VR-1 (UnresolvedReferenceSkip) in packages/language/specs/validation-reference.allium encodes this policy.
Consequences
Positive
- No duplicate error messages; each problem is reported once from the appropriate phase.
- Validators do not crash or produce misleading output on partial ASTs.
- Remaining resolved references within the same decider are still checked normally.
Negative
- Some semantic errors are masked when references are broken; the user must fix linking errors first before semantic errors surface.
- Every validator must apply the null-guard pattern, adding defensive code throughout the validation layer.