13 KiB
Slovo Diagnostics
This document defines the 1.0.0-beta.13 beta policy for Slovo machine
diagnostics. It documents the existing slovo.diagnostic version 1 schema,
the relationship between the S-expression and JSON encodings, the current
golden diagnostic code catalog, and the migration rules for changing machine
diagnostic fields or codes.
This is a diagnostics policy and catalog slice only. It does not add source
language syntax, runtime behavior, stdlib APIs, ABI/layout guarantees, LSP,
watch mode, SARIF, daemon protocols, stable Markdown output, or a stable
1.0.0 diagnostics freeze.
Schema Identity
The machine diagnostic schema name is slovo.diagnostic.
The current schema version is 1.
The S-expression form uses a root (diagnostic ...) object:
(diagnostic
(schema slovo.diagnostic)
(version 1)
...)
The JSON form uses a single JSON object:
{"schema":"slovo.diagnostic","version":1}
The schema name and version belong to the machine contract. Changing either one requires an explicit migration note, release-note entry, and matching Glagol snapshot or JSON fixture updates.
Encodings
S-expression diagnostics and JSON diagnostics are two encodings of the same diagnostic data model. They must not diverge semantically.
The default human diagnostics path may print human-readable prose and then the S-expression machine form for source diagnostics. Human prose, spacing, excerpts, hints, and surrounding text remain beta-flexible unless a later release freezes them explicitly. Tools should consume the machine form, not the human rendering.
--json-diagnostics emits JSON diagnostics on stderr. Each diagnostic is one
complete JSON object on one line. There is no JSON array wrapper, no pretty
printing, and no required trailing summary object for source failures. Consumers
should parse stderr as newline-delimited JSON objects and should treat each
line as an independent diagnostic record.
JSON and S-expression escaping must preserve the same string values. JSON uses
standard JSON string escaping. S-expression strings use the Glagol diagnostic
string escaping convention already used in golden .diag fixtures.
Fields
Every source-attached compiler diagnostic must include these machine fields:
| Field | S-expression | JSON | Meaning |
|---|---|---|---|
| Schema | (schema slovo.diagnostic) |
"schema":"slovo.diagnostic" |
Diagnostic schema name. |
| Version | (version 1) |
"version":1 |
Diagnostic schema version. |
| Severity | (severity error) |
"severity":"error" |
Diagnostic severity. |
| Code | (code TypeMismatch) |
"code":"TypeMismatch" |
Stable PascalCase diagnostic code for the condition. |
| Message | (message "...") |
"message":"..." |
Concise beta-flexible human message for the machine record. |
| Source file | (file "...") |
"file":"..." |
Source identity used by the invocation or project loader. |
| Span | (span ...) |
"span":{...} |
Primary source span and line/column range. |
Optional fields may appear when the compiler has precise data:
| Field | S-expression | JSON | Meaning |
|---|---|---|---|
| Expected | (expected "...") |
"expected":"..." |
Expected type, arity, value, or form. |
| Found | (found "...") |
"found":"..." |
Found type, arity, value, or form. |
| Hint | (hint "...") |
"hint":"..." |
Safe repair or orientation hint. |
| Related spans | repeated (related ...) |
"related":[...] |
Secondary source locations tied to the primary diagnostic. |
Optional fields are additive when they do not replace an existing machine field or change an existing diagnostic code. Removing an optional field from an existing golden fixture is a migration-level change unless the release note states that the previous field was incorrect.
Severity
Current source diagnostics use severity error.
JSON source-less or invocation-level messages may use error for failures and
note for informational tool output such as a machine-readable test-run
summary. A note is not by itself a source failure; consumers should still use
the process exit code and artifact manifest success field to determine command
success.
Adding a new severity value is an additive schema change only when old
consumers can safely ignore or display it. Reclassifying an existing failing
diagnostic from error to another severity is migration-level.
Source And Range Semantics
file is the source identity reported by the compiler path, project loader, or
workspace loader. It is not a promise of absolute path normalization, URI
formatting, registry identity, or editor document identity.
Primary and related byte spans are zero-based and half-open: start is the
first byte included, and end is the first byte after the highlighted source.
Line and column ranges are one-based and derived from the original source text. Columns are byte columns within the original UTF-8 source line; a tab counts as one input byte. The end column is the first byte column after the highlighted range on the end line.
Diagnostic locations are derived from source input, not formatter output, lowered IR, generated C, LLVM IR, native object code, or runtime stack traces.
Related Spans
Related spans identify secondary source locations such as an original declaration, previous duplicate, or conflicting arm. A related span never replaces the primary span.
In S-expression diagnostics, each related location is a repeated
(related (span ...)) form. In JSON diagnostics, related locations are objects
inside the related array. Each related object has its own file and span;
it may also carry a message string.
Related messages are beta-flexible prose. The existence of a related span for a current golden fixture is part of the machine shape for that fixture and should change only intentionally.
Source-Less Diagnostics
Some diagnostics describe tool invocation or usage failures rather than a source range. Examples include invalid CLI arguments, missing inputs, and source-loading failures before a source span is available.
JSON source-less diagnostics use:
{"file":null,"span":null}
Source-less diagnostics must not invent dummy paths, byte offsets, or
line/column ranges. Text-mode source-less diagnostics may remain human-only in
current Glagol output; consumers that need machine-readable source-less
diagnostics should request --json-diagnostics.
If a future release adds S-expression source-less diagnostics, absence of a
source must be explicit and documented under slovo.diagnostic version 1 or
a later migrated version. It must not be encoded as fake source coordinates.
Artifact Manifest Metadata
slovo.artifact-manifest records the diagnostic metadata for a tool
invocation. The relevant fields are:
(diagnostics-schema-version 1): the diagnostic schema version used by the invocation.(diagnostics-encoding sexpr)or(diagnostics-encoding json): the encoding selected for diagnostics.(primary-output (kind diagnostics) ...): the primary output kind when the command failed by emitting diagnostics.(diagnostic_artifacts ...): the diagnostic stream artifact metadata for project/package/workspace modes.(diagnostics_count N): the project-level count when available.
The manifest points to or records diagnostic streams. It does not define a separate diagnostic schema, embed a parsed diagnostic catalog, freeze Markdown documentation structure, or replace the newline discipline of JSON diagnostic stderr.
Compatibility And Migration
Diagnostic changes are classified as follows.
Clarifying changes:
- Rewording human-readable stderr prose.
- Rewording
messageorhinttext without changing the diagnostic code, source span, field set, severity, or expected/found semantics. - Improving documentation around an existing code or fixture.
Additive changes:
- Adding a new diagnostic code for a newly covered boundary.
- Adding a new golden fixture for a newly rejected form.
- Adding an optional field when the old fields, code, severity, source span, and JSON-line discipline remain valid.
- Adding related spans for a new fixture.
Migration changes:
- Renaming, removing, splitting, or merging an existing diagnostic code covered by golden fixtures.
- Changing required field names, schema name, schema version, span shape, range indexing, JSON null policy, or JSON-line discipline.
- Removing an existing optional field or related span from a golden fixture without documenting the correction.
- Changing a source-attached diagnostic into a source-less diagnostic, or the reverse, for an existing golden fixture.
- Reclassifying an existing failing diagnostic away from severity
error. - Changing artifact manifest diagnostic metadata fields or their meaning.
Every migration-level diagnostic change must update this document or the next
release policy, docs/language/MIGRATION_POLICY.md if needed,
docs/language/RELEASE_NOTES.md, and the matching Glagol golden snapshots or
tests.
Current Golden Catalog
The current golden diagnostics contract is the snapshot inventory in
compiler/tests/diagnostics_contract.rs. As of 1.0.0-beta.13, that contract
references 358 .diag snapshots under tests/, and those snapshots contain
114 unique diagnostic codes.
This catalog inventories those codes. It is policy-focused: messages and fixture-specific prose remain in the snapshots.
| Area | Current codes |
|---|---|
| General calls, typing, signatures, and source shape | ArityMismatch, ReturnTypeMismatch, SingleFileMainSignature, TypeMismatch, UnclosedList, UnknownFunction, UnknownTopLevelForm, UnsupportedBackendFeature, UnsupportedUnitSignatureType |
| Control flow and tests | EmptyWhileBody, IfBranchTypeMismatch, IfConditionNotBool, MalformedIfForm, MalformedTestForm, MalformedWhileForm, NestedWhileUnsupported, TestExpressionNotBool, WhileBodyFormNotUnit, WhileConditionNotBool |
| Literals and strings | I64LiteralOutOfRange, IntegerOutOfRange, InvalidI64Literal, UnsupportedFloatLiteral, UnsupportedStringConcatenation, UnsupportedStringEscape, UnsupportedStringLiteral |
| Locals, assignment, and name conflicts | CannotAssignImmutableLocal, CannotAssignParameter, DuplicateFunction, DuplicateLocal, DuplicateTestName, InvalidSetTarget, InvalidTestName, LocalDeclarationInWhileBodyUnsupported, LocalDeclarationNotAllowed, LocalRedeclaresParameter, LocalShadowsCallable, ParameterShadowsCallable, UnknownVariable, UnsupportedLocalType |
| Type aliases, generics, maps, and sets | DuplicateTypeAlias, MalformedTypeAlias, SelfTypeAlias, TypeAliasCycle, TypeAliasNameConflict, UnknownTypeAliasTarget, UnsupportedGenericFunction, UnsupportedGenericStandardLibraryCall, UnsupportedGenericTypeAlias, UnsupportedGenericTypeParameter, UnsupportedMapType, UnsupportedSetType, UnsupportedTypeAliasTarget |
| Structs and fields | DuplicateStruct, DuplicateStructConstructorField, DuplicateStructField, EmptyStructUnsupported, FieldAccessOnNonStruct, MissingStructField, RecursiveStructFieldUnsupported, StructConstructorFieldOrderMismatch, UnknownStructField, UnknownStructType, UnsupportedStructFieldType |
| Arrays and vectors | ArrayIndexNotI32, ArrayIndexOutOfBounds, EmptyArrayUnsupported, IndexOnNonArray, MutableArrayLocalUnsupported, UnsupportedArrayElementType, UnsupportedArrayEquality, UnsupportedArrayPrint, UnsupportedVectorElementType, UnsupportedVectorEquality, ZeroLengthArrayUnsupported |
| Options, results, and match | DuplicateMatchArm, MalformedMatchPattern, MalformedOptionConstructor, MalformedResultConstructor, MalformedUnwrapForm, MatchArmTypeMismatch, MatchBindingCollision, MatchSubjectTypeMismatch, NonExhaustiveMatch, OptionObservationTypeMismatch, OptionUnwrapTypeMismatch, ResultObservationTypeMismatch, ResultUnwrapTypeMismatch, UnsupportedMatchContainer, UnsupportedMatchMutation, UnsupportedMatchPayloadType, UnsupportedOptionPayloadType, UnsupportedOptionResultEquality, UnsupportedOptionResultPrint, UnsupportedResultPayloadType |
| Enums | DuplicateEnum, DuplicateEnumVariant, EmptyEnumUnsupported, EnumSubjectMismatch, InvalidEnumMatchArm, MixedEnumPayloadTypesUnsupported, RecursiveEnumPayloadStructUnsupported, UnknownEnumConstructor, UnknownVariantConstructor, UnsupportedEnumContainer, UnsupportedEnumEquality, UnsupportedEnumOrdering, UnsupportedEnumPayloadType, UnsupportedEnumPrint, VariantConstructorArity |
| Unsafe operations | MalformedUnsafeForm, UnsafeRequired, UnsupportedUnsafeOperation |
| Standard-library reservation boundaries | UnsupportedStandardLibraryCall |
Future releases may add codes or split broad codes when the release scope requires more precise tooling behavior. Such changes must be documented using the compatibility classes above.
Explicit Deferrals
1.0.0-beta.13 does not define:
- a stable
1.0.0diagnostics freeze - LSP diagnostics, watch mode, SARIF, daemon protocols, or debug adapters
- a stable Markdown documentation schema
- stable source-map, DWARF, LLVM debug metadata, or runtime stack trace schema
- warning, lint, or suggestion taxonomies beyond the current
errorand source-lessnoteuses - localized diagnostic text
- machine-readable remediation edits
- a separate diagnostic catalog artifact emitted by the compiler
- stable package registry, URI, or workspace identity semantics for
file