Repository navigation
Conversation
added 8 commits
August 5, 2026 10:40
Loc() = default leaves �egin/end with indeterminate values, and start_decl is only assigned when name binding resolves the path, so both are read uninitialized on any path where an earlier stage bailed out.
log::error() formats the message into err but ends the line on out, so on master every error leaves stderr unterminated and unflushed and prints a stray newline to stdout. It only looks right when both streams are the same console.
An error token is indistinguishable from end-of-file to the parser, so one stray character truncated the token stream and every declaration after it was silently lost. The error is already reported; carry on with the next character instead.
Three problems compounded each other. expect() consumed the offending token even on a mismatch, so the token that would have resynchronised the parse -- usually the n opening the next declaration -- was eaten. parse_error_decl() skipped exactly one token, so the top-level loop re-entered it on the next one. And every attempt reported again. Together, one bad declaration cost an error per token to the end of the file and every declaration after it was lost. expect() now leaves a mismatched token in place, parse_error_decl() consumes at least one token and then skips to the next token that can begin a declaration (counting braces so a nested declaration does not end the skip early), and reported_at() suppresses a second message about a token already complained about. parse_fn_decl() builds an error pattern for a missing parameter list instead of leaving param null.
The four error nodes had no inference rule, so they fell through to Node::infer and produced 'cannot infer type for expression' on top of the parse error that had already been reported. Giving them the error type instead lets should_report_error() silence everything downstream that touches them. CallExpr::is_jumping() asserted on a null type, which a call reaches whenever an earlier stage bailed out (e.g. let a = return(;). The printer dereferenced FnExpr::body and FnDecl's parameter pattern unconditionally, so --print-ast crashed on any file with a function the parser could not finish.
…serting These are all reachable from ordinary source, so in a release build they were silent undefined behaviour and in a debug build they aborted the compiler. Using anything other than an immutable initialized static as an array size, and a break or continue whose enclosing loop is neither a while nor a for, now produce a diagnostic and the error type. The three array-size paths repeated the same checks, so the message lives in the new TypeChecker::invalid_array_size.
A parse error can produce a named declaration whose identifier is empty, so the assert aborted a debug build on invalid input; in a release build name[0] then read past the end of an empty string.
A prototype binds its parameters and has no body to use them in, so every declaration like n f(x: i32) -> i32; warned about x, and the only way to silence it was to rename the parameter to _x in an interface that documents its argument names.
TimGrun
marked this pull request as ready for review
August 5, 2026 10:30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Produce errors instead of crashing when processing invalid code. Also motivated by the requirement of the language server to run further compilation stages after parsing has failed.
Should not change behaviour on valid input.
Error handling improvements:
expect()consumed the token it had just rejected, usually thefnthe parser needed to resynchronise on, andparse_error_decl()skipped a single token, so the top-level loop walked straight back into the same error.expect()now leaves the token in place, andskip_to_decl()runs on to the next declaration boundary, counting braces as it goes.Other improvment:
Note: