295 lines
15 KiB
Markdown
295 lines
15 KiB
Markdown
# 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:
|
|
|
|
```text
|
|
(diagnostic
|
|
(schema slovo.diagnostic)
|
|
(version 1)
|
|
...)
|
|
```
|
|
|
|
The JSON form uses a single JSON object:
|
|
|
|
```json
|
|
{"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:
|
|
|
|
```json
|
|
{"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 `message` or `hint` text 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.
|
|
|
|
## Project And Workspace Codes
|
|
|
|
Project, package, and workspace diagnostics are covered by integration tests
|
|
because they often require multiple files, manifests, or generated temporary
|
|
directories rather than a single `.slo` golden fixture. These codes still use
|
|
the same `slovo.diagnostic` version `1` schema and PascalCase code policy.
|
|
|
|
Current package/workspace loader and graph diagnostics include:
|
|
|
|
- `DependencyNameMismatch`
|
|
- `DependencyPathEscape`
|
|
- `DuplicatePackageDependencyName`
|
|
- `DuplicatePackageName`
|
|
- `DuplicateWorkspaceMember`
|
|
- `InvalidPackageDependencyName`
|
|
- `InvalidPackageName`
|
|
- `InvalidPackageVersion`
|
|
- `MissingPackageDependency`
|
|
- `MissingPackageModule`
|
|
- `PackageDependencyCycle`
|
|
- `PackageImportNotDependency`
|
|
- `PackageManifestInvalid`
|
|
- `PackageSourceReadFailed`
|
|
- `PackageSourceRootEscape`
|
|
- `PackageSourceRootMissing`
|
|
- `ProjectEntryMainInvalidSignature`
|
|
- `ProjectEntryMainMissing`
|
|
- `ProjectManifestInvalid`
|
|
- `ProjectManifestReadFailed`
|
|
- `ProjectSourceReadFailed`
|
|
- `ProjectSourceRootMissing`
|
|
- `UnsupportedDependency`
|
|
- `WorkspaceBuildAmbiguousEntryPackage`
|
|
- `WorkspaceDefaultPackageEntryMissing`
|
|
- `WorkspaceDefaultPackageMissing`
|
|
- `WorkspaceEntryMainInvalidSignature`
|
|
- `WorkspaceEntryMainMissing`
|
|
- `WorkspaceManifestInvalid`
|
|
- `WorkspaceMemberManifestMissing`
|
|
- `WorkspaceMemberPathEscape`
|
|
|
|
## Explicit Deferrals
|
|
|
|
`1.0.0-beta.13` does not define:
|
|
|
|
- a stable `1.0.0` diagnostics 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 `error` and
|
|
source-less `note` uses
|
|
- 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`
|