cli+syntax: name the right file + line in multi-file diagnostics#76
Merged
Conversation
A `hale build <dir>` (or file-with-imports) merges every file's items
into one program, but each file's spans are byte offsets into its OWN
source. Diagnostics were rendered against an arbitrary `sources.values()
.next()` source, so an error in an imported file printed a bogus line
with no filename (fathom saw `317:1` for an error that was really in a
different file — hours lost localizing it by diffing gateways).
Fix: parse each file at a distinct virtual `base` offset so merged spans
are globally unique, then demultiplex a diagnostic's span back to its
file at render time.
- hale-syntax: `parse_source_at(source, base)` lexes, shifts every
token (and diagnostic) span by `base`, then parses — so the AST
spans land in a process-wide coordinate space. `Pos/Span/Diag::
shifted` + `Diag::render_located(path, source, base)` (un-shifts and
prefixes the path). No combined source string; `base` is virtual.
- hale-cli: `parse_files` / `parse_with_imports` assign each file a
base (running total) and return a `(base, path, len)` table; both
build paths thread it. `render_located(diag, file_bases, sources)`
finds the file whose range contains the span and renders
`path:line:col: kind: message`. Single-file builds are unchanged
(base 0 = no shift) but now also show the filename.
Now an imported-file error reads e.g. `lib/foo.hl:7:9: type error: ...`.
Regression test in crates/hale-syntax/tests/parse_source_at.rs (shift +
un-shift round-trip).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
The bug (reported by the fathom session)
A
hale build <dir>(or file-with-imports) merges every file's items into one program, but each file's spans are byte offsets into its own source. Diagnostics were rendered against an arbitrarysources.values().next()source, so an error in an imported file printed a bogus line with no filename — fathom saw317:1for an error that was really atapps/mdgw/bybit/main.hl:322, and lost hours localizing it by diffing gateways and grepping shared imports by line count.The fix
Parse each file at a distinct virtual
baseoffset so merged spans are globally unique, then demultiplex a diagnostic's span back to its file at render time. No combined source string is built —baseis virtual.parse_source_at(source, base)lexes, shifts every token (and diagnostic) span bybase, then parses, so AST spans land in a process-wide coordinate space. AddsPos/Span/Diag::shifted+Diag::render_located(path, source, base)(un-shifts + prefixes the path).parse_files/parse_with_importsassign each file a base (running total) and return a(base, path, len)table; both build paths thread it.render_located(diag, file_bases, sources)finds the file whose range contains the span and printspath:line:col: kind: message.Result
Before:
317:1: type error: error not addressed: …(wrong line, no file).After:
apps/mdgw/bybit/main.hl:322:17: type error: error not addressed: …— and/tmp/bug2test/lib.hl:7:9for an error in an imported file (verified). Single-file builds are unchanged (base 0 = no shift) but now also show the filename.Tests
crates/hale-syntax/tests/parse_source_at.rs— shift + un-shift round-trip. Full hale-syntax suite (82 span-sensitive tests) + hale-types/codegen suites stay green.Context
This is bug #2 of a fathom gateway report. Bug #1 ("error not addressed" on the gateways) was not a compiler regression — the gateways called
() fallible(WsError)WS methods without anordisposition (alpaca, same lib, built fine because it addressed them); the fathom session has since cleaned up their code withor discard. This PR only fixes the diagnostic-quality bug that made it hard to find.🤖 Generated with Claude Code