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:
@@ -457,6 +457,7 @@ pub const ModuleCache = std.StringHashMap(ResolvedModule);
|
||||
pub const RawDeclRef = union(enum) {
|
||||
fn_decl: *const ast.FnDecl,
|
||||
const_decl: *const ast.ConstDecl,
|
||||
var_decl: *const ast.VarDecl,
|
||||
struct_decl: *const ast.StructDecl,
|
||||
enum_decl: *const ast.EnumDecl,
|
||||
union_decl: *const ast.UnionDecl,
|
||||
@@ -499,13 +500,14 @@ pub const NamespaceTarget = struct {
|
||||
pub const NamespaceEdges = std.StringHashMap(std.StringHashMap(NamespaceTarget));
|
||||
|
||||
/// The `RawDeclRef` a top-level node carries, or null when the node is not a
|
||||
/// selectable named declaration (e.g. `impl_block`, `var_decl`, `ufcs_alias`,
|
||||
/// a flat `c_import_decl`). Public so the unified resolver's namespace collector
|
||||
/// selectable named declaration (e.g. `impl_block`, `ufcs_alias`, a flat
|
||||
/// `c_import_decl`). Public so the unified resolver's namespace collector
|
||||
/// can classify a `NamespaceTarget.own_decls` node without re-deriving the map.
|
||||
pub fn rawDeclRefOf(decl: *const Node) ?RawDeclRef {
|
||||
return switch (decl.data) {
|
||||
.fn_decl => |*d| .{ .fn_decl = d },
|
||||
.const_decl => |*d| .{ .const_decl = d },
|
||||
.var_decl => |*d| .{ .var_decl = d },
|
||||
.struct_decl => |*d| .{ .struct_decl = d },
|
||||
.enum_decl => |*d| .{ .enum_decl = d },
|
||||
.union_decl => |*d| .{ .union_decl = d },
|
||||
@@ -584,6 +586,7 @@ pub fn buildImportFacts(
|
||||
pub const DeclKind = enum {
|
||||
function,
|
||||
constant,
|
||||
global,
|
||||
@"struct",
|
||||
@"enum",
|
||||
@"union",
|
||||
@@ -597,6 +600,7 @@ fn declKindOf(ref: RawDeclRef) DeclKind {
|
||||
return switch (ref) {
|
||||
.fn_decl => .function,
|
||||
.const_decl => .constant,
|
||||
.var_decl => .global,
|
||||
.struct_decl => .@"struct",
|
||||
.enum_decl => .@"enum",
|
||||
.union_decl => .@"union",
|
||||
|
||||
Reference in New Issue
Block a user