fix(imports): diagnose namespace-alias dup + propagate buildImportFacts errors [stdlib A attempt-2]

Two defects from the Phase A attempt-1 review.

F1 — duplicate-name diagnostic missed NAMESPACE ALIASES (silent first-win).
`addNamespace` unconditionally put the alias into scope/own_decls, so a
same-module collision between an authored decl and a `dup :: #import "…"`
alias compiled clean in the fn-then-alias order (the scalar
ModuleRawDeclIndex silently first-won). Now `addNamespace` returns a bool
and refuses a same-module duplicate (mirroring addOwnDecl); the call site
surfaces it via the new `reportDuplicateName` (the import_decl node has no
declName, so the alias name is passed explicitly). The C-import namespace
site gets the same guard. Both orders now emit "duplicate top-level
declaration 'X'" and exit nonzero (alias-then-fn was already caught by
addOwnDecl seeing the alias in scope).

F2 — buildImportFacts errors were swallowed by `else |_| {}` in core.zig
(REJECTED-PATTERN catch-all leaving the borrowed store silently empty).
`resolveImports` returns !void, so the call is now a plain `try` and a
build failure propagates instead of producing a stale/empty store.

Tests: extend the dup-name regression with fn-vs-namespace-alias
collisions in both orders. No resolution behavior change (no lower.zig
edits; run_examples 471 byte-identical); m3te ios-sim builds via the
worktree binary.
This commit is contained in:
agra
2026-06-06 23:54:51 +03:00
parent b5ec121645
commit 5f06b6504f
3 changed files with 95 additions and 17 deletions

View File

@@ -136,11 +136,12 @@ pub const Compilation = struct {
// Raw import facts (the unified-resolver store): scalar per-module
// raw-decl index + namespace edges, built from the SAME modules. Nothing
// consumes these yet — they are borrowed by `ProgramIndex` for later
// phases (and the LSP). Built without IR lowering.
if (imports.buildImportFacts(self.allocator, self.file_path, mod, &cache)) |facts| {
self.module_decls = facts.decls;
self.namespace_edges = facts.ns_edges;
} else |_| {}
// phases (and the LSP). Built without IR lowering. A build failure here
// (allocation) is the Phase A deliverable failing — propagate it rather
// than leaving the borrowed views silently empty/stale.
const facts = try imports.buildImportFacts(self.allocator, self.file_path, mod, &cache);
self.module_decls = facts.decls;
self.namespace_edges = facts.ns_edges;
// Store main file source in import_sources so error reporting can find it
self.import_sources.put(self.file_path, self.source) catch {};