Every diagnostic the compiler can emit has a stable code. Codes are never
reused or renumbered. The machine-readable registry lives in
crates/rynix-diag/src/code.rs; a test asserts that every registered code is
documented in this file.
Numbering plan:
RYX0xxx— lexical (Phase 1)RYX1xxx— syntactic (Phase 2)RYX2xxx— names and types (Phase 4)RYX3xxx— escape/region analysis (Phase 6)RYX4xxx— code generation and linking (Phase 7)RYX5xxx— runtime-facing checks (Phase 8)
Fix policy: fixes carry a confidence in [0.0, 1.0]. Anything at or above
0.9 is safe for an AI agent to apply without confirmation; below that, the
fix is a suggestion. Fixes are edit lists (span + replacement) and must be
mechanically applicable.
A byte that cannot start any token (e.g. $, @, ;, `, a lone !,
&, |, or a stray control character). The character is consumed as an
Unknown token and lexing continues.
Targeted fixes:
;→ remove it (newlines terminate statements), confidence 0.90!→ replace withnot, confidence 0.85&/&&→ replace withand, confidence 0.85 (0.60 for a single&)|/||→ replace withor, confidence 0.85 (0.60 for a single|)'→ replace with"(strings use double quotes), confidence 0.70
A raw line terminator was found inside a string. The token ends before the
newline. Fix: insert " at the end of the string content, confidence 0.90.
Non-ASCII text outside strings and comments. Identifiers are ASCII-only in
v0.1 (ADR-0002). The whole run is consumed (as Ident when it extends an
ASCII identifier, otherwise as Unknown) and lexing continues.
Covers: uppercase base prefix (0X1 — fix: lowercase, confidence 0.95),
missing digits after a base prefix (0x), invalid digit for the base
(0b12, 0o9), misplaced underscore (1__0, 1_, 0x_1), missing
exponent digits (1e, 1e+), uppercase exponent (1E5 — fix: lowercase
e, confidence 0.90), and numeric suffixes (123abc, suffixes do not exist
in v0.1). The sub-span points at the offending bytes.
Unknown escape character, malformed \x (needs exactly two hex digits), or
malformed \u{...} (needs 1–6 hex digits, a closing }, and a valid Unicode
scalar value). Fix for unknown escapes: remove the backslash, confidence 0.70.
The file ended before the closing ". Fix: append ", confidence 0.80.
A token appeared where no production expected it. The parser inserts an
Error node spanning the token and resumes at the next synchronisation
point (Newline, end, def, struct, enum, type, import).
A specific token was required (e.g. ), :, in, end) and something
else was found. When the expected token is a single character of
punctuation, a high-confidence fix inserts it at the current position.
A (, [, or { was never closed before a statement boundary or EOF.
The opening span is labelled; recovery pretends the closer was present.
A keyword-delimited block (def/struct/enum/if/loop/for) ran
into EOF or a sibling item without seeing end. Fix: insert end at the
recovery point, confidence 0.85.
One of agent, signal, tensor was used as an identifier or item name.
These remain reserved; the node is still built so later phases can attach
more precise guidance. (match is a live keyword and is not reserved.)
The file ended while a construct was still open (parameter list, type,
expression). Distinct from RYX1004 which is specifically about end.
Comparisons are non-associative (canonical syntax). a < b < c is an
error; write a < b and b < c. Fix: rewrite as a conjunction, confidence
0.80.
A path segment could not be found in the current scope (value or type position).
Two items or locals in the same scope share a name. The secondary label points at the earlier definition.
An expression's type is incompatible with the type required by its context (assignment, argument, return, condition, etc.).
A value was used where a type was required (e.g. in a parameter annotation).
x = ... or x += ... where x was not declared mut.
Field access on a struct type that has no such field.
A call site supplies a different number of arguments than the callee's signature.
break / continue appeared outside any loop or for.
A call was attempted on a non-function value.
A binding of a linear type (Vec, Map, struct, enum, slice, or
opaque ptr) was used after ownership transferred via let, assignment, or
a call argument. Reinitialize the binding before using it again. Integer,
float, bool, and str values are copy and do not move.
A function marked #^ effect: pure (or #^ effects: pure) transitively
performs io and/or network (soft builtins such as print, http_*,
tcp_*, kv_*, or a call to another impure function). Remove the pure
marker or isolate the side effect.
tensor, signal, and agent are reserved keywords / names. They are not
product soft builtins and have no runtime. Calls are rejected until a future
ADR ships a real implementation.
Free-function calls named system, exec / exec*, popen, or dlopen
(and close aliases) are rejected as process/dynamic-load escapes. See
ADR-0023. RIR CallExt with the same names is also
rejected by sanitize before emit.
Assignment to an index place (a[i] = …) is rejected. Field stores
(p.x = …) are supported for mut bindings with i64 struct fields
(Phase 12 Wave 3). Assign only to bare bindings or struct fields.