docs: add libVCT public specification set (000-015)
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
# 011 — Diagnostics
|
||||
|
||||
- **Status:** Draft
|
||||
- **Normative language:** `MUST`, `MUST NOT`, `SHOULD`, `SHOULD NOT`, and `MAY` are to
|
||||
be interpreted as described in RFC 2119.
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
libVCT has a single central diagnostics service (`vct.diag`). Every module emits
|
||||
diagnostics through it; no module prints directly to a stream. This gives embedders one
|
||||
uniform surface for errors, warnings, notes, optimizer remarks, and internal compiler
|
||||
errors, and it lets the CLI present them in several formats without every module knowing
|
||||
which format is active.
|
||||
|
||||
## 2. Scope
|
||||
|
||||
This file specifies the diagnostics service, the `Diagnostic` structure and its
|
||||
severity and code vocabulary, source maps, output channels, optimizer remarks, the
|
||||
internal-compiler-error policy, and process exit codes. The pipeline that produces these
|
||||
diagnostics is specified in [010 — Driver & CLI](010-driver-cli.md); the backends that
|
||||
consume source maps are specified in [008 — C Backend](008-c-backend.md) and
|
||||
[009 — LLVM Backend](009-llvm-backend.md).
|
||||
|
||||
## 3. Definitions
|
||||
|
||||
| Term | Meaning |
|
||||
|---|---|
|
||||
| Diagnostic | One emitted message with severity, code, span, and optional notes and suggestions. |
|
||||
| Severity | Error, Warning, Note, Remark, or Ice. |
|
||||
| `DiagCode` | A stable, namespaced identifier such as `VCT1002`. |
|
||||
| Span | A source range: file, line, column, and length. |
|
||||
| Source map | The association of HIR nodes with frontend source locations, resolved for VIR through the lowering map. |
|
||||
| Consumer | A `DiagnosticConsumer` callback that receives emitted diagnostics. |
|
||||
| ICE | Internal compiler error. |
|
||||
|
||||
## 4. Model
|
||||
|
||||
The service is **emit-only** from the perspective of compilation modules. A module
|
||||
builds a `Diagnostic` and hands it to the service. The service forwards it to the
|
||||
configured consumer. Fatal conditions (an error diagnostic, or an ICE) stop the
|
||||
pipeline at the next safe boundary; they never let compilation continue on invalid
|
||||
state.
|
||||
|
||||
The service is GC-allocated, consistent with the cold path rule in
|
||||
[001 — Architecture](001-architecture.md).
|
||||
|
||||
```d
|
||||
struct Diagnostic {
|
||||
Severity severity; // Error | Warning | Note | Remark | Ice
|
||||
DiagCode code; // stable namespaced, e.g. VCT1002
|
||||
string message;
|
||||
Span primary;
|
||||
Span[] notes;
|
||||
Suggestion[] suggestions;
|
||||
}
|
||||
```
|
||||
|
||||
## 5. Normative requirements
|
||||
|
||||
### 5.1 Central service
|
||||
|
||||
**R1.** Every module MUST emit diagnostics through the central service. No module MUST
|
||||
print to standard output or standard error directly.
|
||||
|
||||
**R2.** The service MUST be GC-allocated.
|
||||
|
||||
**R3.** The service MUST forward each emitted diagnostic to the configured consumer in
|
||||
emission order.
|
||||
|
||||
**R4.** An `Error` or `Ice` diagnostic MUST prevent further compilation on the invalid
|
||||
path. The pipeline MUST stop at the next safe boundary after such a diagnostic.
|
||||
|
||||
### 5.2 Diagnostic structure
|
||||
|
||||
**R5.** Every diagnostic MUST carry a `Severity` and a `DiagCode`. A diagnostic with no
|
||||
code MUST NOT be emitted.
|
||||
|
||||
**R6.** `Severity` MUST be one of the values in Table 1.
|
||||
|
||||
**Table 1. Severity levels**
|
||||
|
||||
| Severity | Meaning |
|
||||
|---|---|
|
||||
| Error | Compilation cannot proceed correctly. |
|
||||
| Warning | Suspicious but continuable. |
|
||||
| Note | Supporting context attached to another diagnostic. |
|
||||
| Remark | An optimizer decision record. |
|
||||
| Ice | Internal compiler error. |
|
||||
|
||||
**R7.** A `DiagCode` MUST be a stable, namespaced identifier in the form `VCT` followed
|
||||
by digits. Once published, a code's meaning MUST NOT change and the code MUST NOT be
|
||||
renumbered.
|
||||
|
||||
**R8.** A diagnostic MUST carry a primary `Span` whenever a source location is known, and it MAY
|
||||
carry additional note spans and suggestions. When no location can be resolved, the diagnostic MUST
|
||||
carry no location instead (see R12).
|
||||
|
||||
**R9.** A `Note` diagnostic MUST be attached to a parent diagnostic rather than emitted
|
||||
as a standalone top-level message.
|
||||
|
||||
### 5.3 Source maps
|
||||
|
||||
**R10.** The frontend MUST be able to register a `SourceLocation` (file, line, column,
|
||||
length) against any HIR node.
|
||||
|
||||
**R11.** For VIR entities, the service MUST resolve source locations through the
|
||||
lowering map that associates HIR nodes with the VIR entities they became (see
|
||||
[005 — Lowering](005-lowering.md)).
|
||||
|
||||
**R12.** When a location cannot be resolved, the service MUST degrade gracefully to a
|
||||
diagnostic with no location. It MUST NOT fabricate a location.
|
||||
|
||||
**R13.** The C backend MUST emit `#line` directives from the registered source map (see
|
||||
[008 — C Backend](008-c-backend.md)), and the driver MUST re-map compiler errors through
|
||||
it (see [010 — Driver & CLI](010-driver-cli.md)).
|
||||
|
||||
### 5.4 Channels
|
||||
|
||||
**R14.** The service MUST expose a single canonical `DiagnosticConsumer` callback for
|
||||
embedders.
|
||||
|
||||
**R15.** The CLI MUST provide a human-readable channel that enables color when standard
|
||||
error is a terminal.
|
||||
|
||||
**R16.** The CLI MUST provide a JSON channel selected by `--diagnostics=json`.
|
||||
|
||||
**R17.** The JSON channel MUST use a versioned schema. The schema version MUST appear in
|
||||
the output, and the schema MUST be stable within a major version.
|
||||
|
||||
**R18.** A single diagnostic MUST render equivalently in content across all channels; the
|
||||
channels differ only in presentation.
|
||||
|
||||
Example JSON shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"diagnostics": [
|
||||
{
|
||||
"severity": "error",
|
||||
"code": "VCT1002",
|
||||
"message": "missing trait at lowering",
|
||||
"file": "input.vox",
|
||||
"line": 12,
|
||||
"column": 5,
|
||||
"length": 3,
|
||||
"notes": []
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 5.5 Optimizer remarks
|
||||
|
||||
**R19.** Optimizer remarks MUST be off by default and MUST be enabled by `--remarks`.
|
||||
|
||||
**R20.** Optimizer remarks MUST be enabled automatically at `-O3`.
|
||||
|
||||
**R21.** Every remark MUST be tied to a specific trait-pipeline decision, naming the
|
||||
request or attribute that drove it.
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
HIR: replaced 3 uses of node#412 (comptime 64)
|
||||
VIR: denied Inline on @foo - CostModel (callee 2.4x size budget)
|
||||
```
|
||||
|
||||
### 5.6 Internal compiler error policy
|
||||
|
||||
**R22.** The following conditions MUST be treated as internal compiler errors:
|
||||
|
||||
- a missing or contradictory trait encountered at lowering (see
|
||||
[005 — Lowering](005-lowering.md));
|
||||
- a VIR invariant violation detected in a debug build (see [006 — VIR](006-vir.md));
|
||||
- a `Strong` request denied for reason `Illegality` or `ContradictsTrait` (see
|
||||
[007 — VIR Optimizer](007-vir-optimizer.md)).
|
||||
|
||||
**R23.** In release builds, an internal compiler error MUST return a failure result and
|
||||
emit an `Ice` diagnostic that requests a module dump.
|
||||
|
||||
**R24.** In debug builds, an internal compiler error MUST assert.
|
||||
|
||||
**R25.** An internal compiler error MUST NEVER be silently continued past.
|
||||
|
||||
### 5.7 Warning policy
|
||||
|
||||
**R26.** The trait-mismatch warning raised when a suggested trait conflicts with the
|
||||
derived value MUST be promoted to an error under `-Werror`.
|
||||
|
||||
**R27.** A frontend MUST be able to opt out of warning promotions: `-Wno-error=<category>` MUST
|
||||
disable the promotion of that category, and a bare `-Wno-error` MUST disable every promotion.
|
||||
|
||||
### 5.8 Exit codes
|
||||
|
||||
**R28.** The CLI MUST exit with the codes in Table 2.
|
||||
|
||||
**Table 2. Exit codes**
|
||||
|
||||
| Code | Meaning |
|
||||
|---|---|
|
||||
| 0 | Success. |
|
||||
| 1 | Diagnostics present. |
|
||||
| 2 | Usage or configuration error. |
|
||||
| 3 | Internal compiler error. |
|
||||
|
||||
**R29.** Exit code 3 MUST take precedence over exit code 1 when an ICE has been emitted.
|
||||
|
||||
## 6. Invariants
|
||||
|
||||
- **I1.** Every emitted diagnostic has a severity and a `DiagCode`.
|
||||
- **I2.** No compilation module writes directly to a stream.
|
||||
- **I3.** Diagnostics are emitted and rendered in a deterministic order for a fixed
|
||||
input and `Config`.
|
||||
- **I4.** An ICE never resolves to a success exit code.
|
||||
- **I5.** A location is either resolved or omitted; it is never invented.
|
||||
- **I6.** The JSON channel's schema version is always present.
|
||||
|
||||
## 7. Examples
|
||||
|
||||
A frontend registers a location and a later lowering failure reports it:
|
||||
|
||||
```d
|
||||
diag.registerLocation(node, SourceLocation("input.vox", 12, 5, 3));
|
||||
// later, during lowering:
|
||||
emit(Diagnostic(Severity.Error, DiagCode(1002),
|
||||
"missing trait at lowering", span));
|
||||
```
|
||||
|
||||
A `MustTail` request on GCC becomes a hard error rather than a silent fallback:
|
||||
|
||||
```
|
||||
error[VCT1044]: MustTail requires [[clang::musttail]]; current compiler is GCC
|
||||
--> input.vox:7:5
|
||||
```
|
||||
|
||||
## 8. Cross-references
|
||||
|
||||
- [000 — Overview](000-overview.md) for conformance and determinism.
|
||||
- [001 — Architecture](001-architecture.md) for the cold-path GC rule.
|
||||
- [002 — Traits](002-traits.md) for the trait vocabulary and mismatch handling.
|
||||
- [005 — Lowering](005-lowering.md) for the lowering map and ICE conditions.
|
||||
- [006 — VIR](006-vir.md) for the invariants checked in debug.
|
||||
- [007 — VIR Optimizer](007-vir-optimizer.md) for request denials and `DenyReason`.
|
||||
- [008 — C Backend](008-c-backend.md) for `#line` emission.
|
||||
- [010 — Driver & CLI](010-driver-cli.md) for `--remarks`, `--diagnostics`, and exit codes.
|
||||
Reference in New Issue
Block a user