pub enum QalaError {
Show 26 variants
UnterminatedString {
span: Span,
},
UnterminatedInterpolation {
span: Span,
},
InvalidEscape {
span: Span,
message: String,
},
UnexpectedChar {
span: Span,
ch: char,
},
IntOverflow {
span: Span,
},
MalformedNumber {
span: Span,
message: String,
},
BadByteLiteral {
span: Span,
message: String,
},
UnexpectedToken {
span: Span,
expected: Vec<TokenKind>,
found: TokenKind,
},
UnclosedDelimiter {
span: Span,
opener: TokenKind,
found: TokenKind,
},
UnexpectedEof {
span: Span,
expected: Vec<TokenKind>,
},
Parse {
span: Span,
message: String,
},
TypeMismatch {
span: Span,
expected: String,
found: String,
},
MissingReturn {
span: Span,
fn_name: String,
expected: String,
},
UndefinedName {
span: Span,
name: String,
},
UnknownType {
span: Span,
name: String,
},
RecursiveStructByValue {
span: Span,
path: Vec<String>,
},
NonExhaustiveMatch {
span: Span,
enum_name: String,
missing: Vec<String>,
},
InterfaceNotSatisfied {
span: Span,
ty: String,
interface: String,
missing: Vec<String>,
mismatched: Vec<(String, String, String)>,
},
EffectViolation {
span: Span,
caller: String,
caller_effect: String,
callee: String,
callee_effect: String,
},
RedundantQuestionOperator {
span: Span,
message: String,
},
Type {
span: Span,
message: String,
},
IntegerOverflow {
span: Span,
op: BinOp,
lhs: i64,
rhs: i64,
},
ComptimeBudgetExceeded {
span: Span,
},
ComptimeEffectViolation {
span: Span,
fn_name: String,
effect: String,
},
ComptimeResultNotConstable {
span: Span,
type_name: String,
},
Runtime {
span: Span,
message: String,
},
}Expand description
every way the compiler can reject a program, with the source span of the
fault. PartialEq so tests can compare errors directly; no Eq and no
serde derives, because the parse variants carry TokenKind, which holds
an f64 and is therefore neither Eq nor (currently) serde-derivable.
the diagnostics layer (Phase 3) builds its own structured editor form from
span() and message() rather than serializing this enum directly.
Variants§
UnterminatedString
a string literal reached a raw newline or end of file before its closing
". span = the opening quote, since that is where the reader’s attention
belongs, not the place the scanner ran out of input.
UnterminatedInterpolation
an interpolation { inside a string was never closed by a } before the
string ended or the file ended. span = the unmatched {.
InvalidEscape
a backslash escape sequence that the language does not define (anything
other than \n \t \r \0 \\ \" \{ \} or a well-formed \u{...}). span =
the backslash, not the character after it.
UnexpectedChar
a byte that cannot begin any token here: a non-ASCII byte outside a
string or comment, or a lone & / |. span = the offending byte (the
whole UTF-8 sequence for a non-ASCII character). ch is the decoded
character, for the message.
IntOverflow
an integer literal whose magnitude does not fit in i64. span = the
digits.
MalformedNumber
a numeric literal with a malformed shape: a misplaced digit separator
(1_, 1__0, 1_.0), an empty or invalid radix body (0x, 0xG,
0b2), an exponent with no digits (1e). span = the literal.
BadByteLiteral
a byte literal that is not exactly one ASCII character or one one-byte
escape between b' and ' (b'', b'ab', b'\x', a non-ASCII byte
inside). span = the literal.
UnexpectedToken
the parser found a token that is not legal at this position. span = the
offending token, or, when found is TokenKind::Eof, a zero-width
point just after the last real token. expected is the set of token
kinds the parser could have accepted here.
UnclosedDelimiter
an opening delimiter (( / [ / {) was closed by the wrong delimiter
or never closed at all. span = the opening delimiter, not the surprising
closer, because the opener is where the reader needs to look. found is
the wrong closer, or TokenKind::Eof if the input ran out first.
UnexpectedEof
the input ended while the parser was still expecting more. span = a
zero-width point immediately after the last valid token (offset = end of
that token, length 0), not src.len() unless that is where the last
token ends. expected is what would have been legal next.
Parse
a parse failure that does not fit the structured variants above: the
recursion-depth limit (“expression nests too deeply”), a malformed
pipeline right-hand side, and similar. span = wherever the failure was
detected; message is the human description.
TypeMismatch
an expression’s actual type does not match the type required by its
context (an argument vs a parameter, an initializer vs an annotation, an
arm body vs the first arm’s type, …). span = the offending
sub-expression. expected and found are rendered via
QalaType::display() so the wording is always the canonical form (i64,
Result<i64, str>, ? for the poison type, and so on).
MissingReturn
a function declared to return a non-void type fell off the end of its
body without producing a value. span = the last expression in the body,
or the closing brace of an empty body, because that is where the missing
value should appear. expected is the canonical form of the declared
return type.
UndefinedName
a name is used that the type checker cannot resolve to a local, a parameter, a top-level function, or a stdlib entry. span = the identifier. one variant covers free identifiers and unknown function calls together; the message is the same either way.
UnknownType
a type name is used (in a parameter annotation, a struct field, an enum
variant data position, a let annotation, a generic argument) that no
struct / enum / interface declaration nor any built-in primitive
matches. span = the type expression’s source position.
RecursiveStructByValue
a struct contains itself by value, directly or transitively through
other by-value compounds. span = the declaration site of the
lexicographically smallest struct in the cycle (the “head” – chosen so
the message is deterministic). path lists the cycle’s struct names
starting and ending with the head, so the cycle reads as a closed loop
when joined with arrows.
NonExhaustiveMatch
a match does not cover every variant of its scrutinee’s enum and has
no _ wildcard. span = the match keyword (where the reader’s
attention belongs). missing is alphabetically sorted by the type
checker before this variant is constructed; the message stores the
already-sorted list verbatim so the output is deterministic.
InterfaceNotSatisfied
a named type used in an interface position does not satisfy the
interface: one or more required methods are missing, and one or more
methods that do exist have the wrong signature. span = the use site (the
place where the type was demanded to satisfy the interface). missing
and mismatched are sorted by the type checker; the diagnostics layer
turns them into per-method note: lines. each mismatched tuple is
(method_name, expected_signature, found_signature).
Fields
EffectViolation
a function with one effect set is calling a function with effects it has
not declared. span = the call site. caller_effect / callee_effect
are the lowercase effect words (pure, io, alloc, panic, or a
comma-joined combo like io, alloc) produced by
EffectSet::display(). the message reads “{caller_effect} function
{caller} calls {callee_effect} function {callee}”.
RedundantQuestionOperator
the ? operator was used somewhere it cannot be: outside a
Result/Option-returning function, or on a value whose type is not
Result<_, _> / Option<_>, or where the operand’s error type does
not match the enclosing function’s error type. span = the ? token.
the type checker constructs the specific human wording so this variant
stores the message structurally, mirroring the existing Parse
fallback.
Type
a type-level fault that does not fit any structured variant above: a
literal pattern matched against an enum value, a variant name that is
not a member of the enum, a ? operand whose type is not Result /
Option, and so on. span = wherever the fault was detected;
message is the human description. mirrors the existing Parse
fallback so later passes can extend the type-error vocabulary without
reshaping the enum.
IntegerOverflow
an arithmetic operation that would overflow i64 if computed at
compile time. emitted by codegen’s inline constant folder before the
operation is materialised in bytecode. span = the outer binary
operator’s full span (the Binary { span, .. } node, not the
operator-token span). op is the offending operator; lhs and rhs
are the literal operands at fold time, used to render a precise
message like integer overflow: 9223372036854775807 * 2 does not fit in i64. comparison and logical BinOp variants (Eq, Lt, &&,
and the rest) never reach this variant – those folds cannot overflow.
ComptimeBudgetExceeded
the comptime interpreter exhausted its 100000-instruction budget.
emitted at the originating comptime { ... } block, not at the
runaway instruction inside it – the reader’s attention belongs at
the block declaration so they can shrink the work. the budget is a
hard limit; raising it is a v2 concern.
ComptimeEffectViolation
defense-in-depth: the comptime interpreter dispatched a CALL whose
callee is not pure. phase 3’s effect checker should have caught this;
emitting at codegen prevents the comptime interpreter from running
an IO/alloc/panic body if the typechecker missed something. span =
the comptime block’s span (NOT the call site, since by codegen time
the call is buried inside the throwaway chunk); fn_name is the
callee name; effect is EffectSet::display() of the callee’s
effect (one of pure, io, alloc, panic, or a comma-joined
combo like io, alloc).
ComptimeResultNotConstable
the comptime block evaluated successfully but its result is not
representable in the constant pool: an array, a struct, an
enum-variant payload, or any heap-allocated compound. span = the
comptime block; type_name is QalaType::display() of the result’s
type. v1 keeps the constant pool primitives-and-strings-only;
relaxing this is a future enhancement.
Runtime
a fault the bytecode VM hit while executing a program: division or
modulo by zero, an array index out of bounds, a call-frame stack
overflow from deep recursion, a value-stack overflow, or a malformed
bytecode stream (an undecodable opcode byte, a truncated operand, a
jump offset out of range). the VM never panics on any of these – it
constructs this variant and unwinds. span covers the offending
source line: the VM derives it from chunk.source_lines[ip] via
crate::span::LineIndex and stores a span covering that line, so the
diagnostics renderer formats a runtime fault exactly like a type error.
message is the human description. mirrors the Type and Parse
fallback variants – one structured { span, message } shape.
Implementations§
Source§impl QalaError
impl QalaError
Trait Implementations§
Source§impl From<QalaError> for Diagnostic
impl From<QalaError> for Diagnostic
Source§fn from(err: QalaError) -> Self
fn from(err: QalaError) -> Self
build a Diagnostic from a QalaError. severity is always
Error; category is always None (errors have no category –
only warnings do). the message comes from err.message() and the
span from err.span(). five variants carry structured extra
data which becomes per-method note: lines or a single hint:
line; the rest leave notes and hints empty.