lang: qualified namespace members in value position + alias carry

Two coupled capabilities on the road to the std restructure
(current/PLAN-STDLIB.md, issue 0114):

1. alias.Type.method() / alias.Type as a call head, alias.CONST, and
   alias.Enum.variant now resolve — previously only alias.fn() and
   type-position alias.Type worked. objectIsValue treats an
   alias-rooted field_access as a type head; the call path strips the
   alias to the existing Type.method machinery; lowerFieldAccess
   resolves alias.CONST pinned to the target module and alias.Enum.x
   as a typed enum literal; resolveTypeWithBindings resolves qualified
   type_exprs pinned to the target.

2. The carry rule: namespaceAliasTarget resolves an alias from the
   file's own edges first, then from DIRECT flat imports (one level),
   diagnosing two distinct carried targets as ambiguous. All qualified
   shapes work through a carried alias — the std.sx namespace tail
   (mem.GPA.init() etc.) is now expressible.

Regression: examples/0831-modules-namespace-alias-carry.sx (direct +
carried, all seven shapes).
This commit is contained in:
agra
2026-06-11 05:52:10 +03:00
parent 2025bb361b
commit ee00db849c
11 changed files with 163 additions and 9 deletions

View File

@@ -360,10 +360,7 @@ pub fn buildGenericStructTemplate(self: *Lowering, sd: *const ast.StructDecl, so
/// module authors no such generic struct — the caller then falls back to the
/// legacy bare lookup.
pub fn qualifiedStructTemplate(self: *Lowering, alias: []const u8, member: []const u8) ?StructTemplate {
const edges = self.program_index.namespace_edges orelse return null;
const from = self.current_source_file orelse return null;
const alias_map = edges.getPtr(from) orelse return null;
const target = alias_map.get(alias) orelse return null;
const target = self.namespaceAliasTarget(alias, null) orelse return null;
for (target.own_decls) |decl| {
// A top-level struct is authored either as a bare `struct_decl` node
// or a `const_decl` whose value is one (`Box :: struct($T){...}`).
@@ -389,10 +386,7 @@ pub fn qualifiedStructTemplate(self: *Lowering, alias: []const u8, member: []con
/// generic struct → `qualifiedStructTemplate` already selected it; any other
/// kind → the type-fn / named-type arms handle it).
pub fn qualifiedMemberMissing(self: *Lowering, alias: []const u8, member: []const u8) bool {
const edges = self.program_index.namespace_edges orelse return false;
const from = self.current_source_file orelse return false;
const alias_map = edges.getPtr(from) orelse return false;
const target = alias_map.get(alias) orelse return false;
const target = self.namespaceAliasTarget(alias, null) orelse return false;
for (target.own_decls) |decl| {
const dn = decl.data.declName() orelse continue;
if (std.mem.eql(u8, dn, member)) return false;