ir: whole-program passes pin the source context per decl (fix 0122)

convergeClosureShapeSets, checkErrorFlow, and the unknown-type loop ran
under whatever current_source_file the previous phase left behind —
closure-literal annotations resolved (and reject/unknown-type
diagnostics rendered) against an arbitrary module. Latent while std.sx
was a single file (the ambient happened to be the main file); the
re-export facade restructure exposed it. Each walk now pins
setCurrentSourceFile per decl / per fn (body.source_file is already
stamped by resolveImports). Coverage: examples 0129/1047/1049/1052/
1053/1056 against the facade std.sx. Gates: zbt 426/426, suite 588/588.
This commit is contained in:
agra
2026-06-11 19:24:46 +03:00
parent 721369a711
commit 340be402a5
4 changed files with 84 additions and 0 deletions

View File

@@ -191,8 +191,16 @@ pub const ErrorAnalysis = struct {
/// by all occurrences of its value-signature shape. A `try slot(x)` against
/// any matching-shape slot then widens against this union.
pub fn convergeClosureShapeSets(self: ErrorAnalysis) void {
// Pin the visibility context to each fn's DEFINING module
// (body.source_file, stamped by resolveImports) — a closure literal's
// param/return annotations must resolve where the fn is written, not
// against whatever module the previous pipeline phase happened to
// leave as the ambient context (issue 0122).
const saved = self.l.current_source_file;
defer self.l.setCurrentSourceFile(saved);
var it = self.l.program_index.fn_ast_map.iterator();
while (it.next()) |e| {
self.l.setCurrentSourceFile(e.value_ptr.*.body.source_file orelse saved);
self.collectClosureShapes(e.value_ptr.*.body);
}
}