fix(0115): source-aware global selection — own-wins for module globals
The globals registry (global_names) was last-wins across modules with no per-importer gate: any module's bare K could read/write/type against an unrelated module's same-named global (hash.sx's K table hijacked every user K once std's namespace tail pulled hash into the program), and an own const of an unsupported shape borrowed another module's const and panicked at the unresolved-type tripwire. - var_decl joins RawDeclRef: module globals are selectable raw authors. - selectGlobalAuthor (the globals analogue of F2's selectModuleConst): own author wins, one flat-visible author resolves, >=2 distinct flat authors diagnose loudly, authored-but-not-visible diagnoses, and a compiler-synthesized global (no raw author) emits untracked. A var_decl author whose per-source registration was deduped at flat-merge (two modules declaring the same extern symbol) serves the symbol's registration. - All bare-identifier global sites route through it: value read, addr-of, assignment (store + compound), lvalue address, fn-ptr call, call param typing, and expression type inference. - selectModuleConst gains .own_opaque: an own const author with no materialized per-source value (e.g. an array '::' const) blocks borrowing another module's same-named const — the read diagnoses cleanly instead of panicking. - The fn-as-VALUE arm admits raw-facts-only authors: an own fn whose name a flat-merge collision dropped from the global decl list (first-wins) now resolves via author selection for func_ref/closure/Any shapes too. Regressions: examples 0835 (own const vs flat array global), 0836 (main const vs namespaced array global, incl. inference), 0837 (own array const never borrows cross-module — clean unresolved).
This commit is contained in:
@@ -1024,6 +1024,11 @@ pub fn globalInitValue(self: *Lowering, vd: *const ast.VarDecl, var_ty: TypeId)
|
||||
const sel: SelectedConst = switch (self.selectModuleConst(id.name)) {
|
||||
.resolved => |s| s,
|
||||
.none => .{ .info = ci_global, .source = null },
|
||||
.own_opaque => {
|
||||
if (self.diagnostics) |d|
|
||||
d.addFmt(.err, v.span, "global '{s}' must be initialized by a compile-time constant; '{s}' is not a usable constant here", .{ vd.name, id.name });
|
||||
break :blk null;
|
||||
},
|
||||
.ambiguous => {
|
||||
if (self.diagnostics) |d|
|
||||
d.addFmt(.err, v.span, "'{s}' is ambiguous: it is declared in multiple flat-imported modules; qualify the reference or remove the duplicate import", .{id.name});
|
||||
@@ -1570,7 +1575,7 @@ pub fn selectNominalLeaf(self: *Lowering, name: []const u8, from: []const u8, ra
|
||||
pub fn isNamedTypeKind(raw: resolver_mod.RawDeclRef) bool {
|
||||
return switch (raw) {
|
||||
.struct_decl, .enum_decl, .union_decl, .error_set_decl, .protocol_decl, .foreign_class_decl => true,
|
||||
.fn_decl, .const_decl, .namespace_decl => false,
|
||||
.fn_decl, .const_decl, .var_decl, .namespace_decl => false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1598,7 +1603,7 @@ pub fn namedRefTid(self: *Lowering, ref: resolver_mod.RawDeclRef, name: []const
|
||||
.enum_decl => |d| (table.type_decl_tids.get(@ptrCast(d)) orelse table.findByName(table.internString(name))),
|
||||
.union_decl => |d| (table.type_decl_tids.get(@ptrCast(d)) orelse table.findByName(table.internString(name))),
|
||||
.error_set_decl, .protocol_decl, .foreign_class_decl => table.findByName(table.internString(name)),
|
||||
.fn_decl, .const_decl, .namespace_decl => null,
|
||||
.fn_decl, .const_decl, .var_decl, .namespace_decl => null,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user