refactor(ir): move generic-binding + alias-aware name resolution into TypeResolver (A2.2)
Architecture phase A2.2 -- behavior-preserving. TypeResolver gains the generic-binding and bare-name resolution it now owns: - resolveBinding(node, env): $T / bare return-type T lookup via an explicit ResolveEnv (no hidden Lowering state). - resolveNamed(name, table, alias_map): the full bare-name algorithm (primitive -> arbitrary-width int -> string-prefix [*]/*/?/[:0]u8 -> already-registered -> alias(alias_map) -> empty-struct stub), MOVED from type_bridge.resolveTypeName so it is single-sourced. - resolveName(self, name): resolves through the canonical alias source ProgramIndex.type_alias_map -- the compiler path no longer reads the TypeTable.aliases borrow. Lowering.resolveTypeWithBindings: the `if (self.type_bindings)` block (the $T lookup plus parameterized/call/closure/function arms that were redundant with the unconditional handling below) collapses to one resolveBinding delegation via a new resolveEnv() snapshot; the bare-name fallback routes type_expr/identifier to resolveName (index-based alias), other node kinds still to resolveAstType. type_bridge.resolveTypeName becomes a 1-line delegate to resolveNamed, passing its TypeTable.aliases borrow as the alias source. Single algorithm; the alias map stays single-sourced in ProgramIndex. Deferred to A2.3: removing the TypeTable.aliases borrow (its ~30 resolveAstType callers must converge onto TypeResolver first) and type_bridge's stateless compound resolvers. A2.2 #3 (templates/protocols/type-fns via ProgramIndex) was already satisfied by A1.1b. Tests: resolveBinding ($T bound/unbound/no-env), resolveName (alias->primitive, alias->pointer via ProgramIndex), resolveNamed (width-int, string-prefix, unknown->stub). No new fallback path; no duplicate truth. Gate green: zig build, zig build test, bash tests/run_examples.sh (350 passed, 0 failed). lower.zig 19372->19367; type_bridge.zig 647->592; type_resolver.zig 90->159.
This commit is contained in:
@@ -20,6 +20,7 @@ const ProtocolDeclInfo = program_index_mod.ProtocolDeclInfo;
|
||||
const ProtocolMethodInfo = program_index_mod.ProtocolMethodInfo;
|
||||
const ModuleConstInfo = program_index_mod.ModuleConstInfo;
|
||||
const TypeResolver = @import("type_resolver.zig").TypeResolver;
|
||||
const ResolveEnv = @import("type_resolver.zig").ResolveEnv;
|
||||
|
||||
const TypeId = types.TypeId;
|
||||
const StringId = types.StringId;
|
||||
@@ -12742,6 +12743,16 @@ pub const Lowering = struct {
|
||||
};
|
||||
}
|
||||
|
||||
/// Snapshot the active resolution context (Principle 2) for `TypeResolver`.
|
||||
/// A2.2 wires the type bindings + literal target; the pack/comptime fields
|
||||
/// are populated as A2.3 moves the cases that consume them.
|
||||
fn resolveEnv(self: *Lowering) ResolveEnv {
|
||||
return .{
|
||||
.type_bindings = if (self.type_bindings) |*tb| tb else null,
|
||||
.target_type = self.target_type,
|
||||
};
|
||||
}
|
||||
|
||||
/// Inner-type recursion hook for `TypeResolver.resolveCompound`: resolves a
|
||||
/// child type node through the full stateful resolver, so generic structs /
|
||||
/// bindings / aliases in element position keep their resolution.
|
||||
@@ -12798,34 +12809,12 @@ pub const Lowering = struct {
|
||||
// stateful resolver (`resolveInner` → here) so generic structs /
|
||||
// bindings in element position keep their resolution.
|
||||
if (self.typeResolver().resolveCompound(node, self)) |t| return t;
|
||||
if (self.type_bindings) |tb| {
|
||||
switch (node.data) {
|
||||
.type_expr => |te| {
|
||||
// Check bindings for any type_expr name — not just those
|
||||
// marked is_generic. The return type `T` in `-> T` may
|
||||
// not have the `$` prefix, so is_generic is false, but
|
||||
// it still refers to the type param.
|
||||
if (tb.get(te.name)) |ty| return ty;
|
||||
},
|
||||
.identifier => |id| {
|
||||
if (tb.get(id.name)) |ty| return ty;
|
||||
},
|
||||
.parameterized_type_expr => |pt| {
|
||||
return self.resolveParameterizedWithBindings(&pt);
|
||||
},
|
||||
.call => |cl| {
|
||||
// Handle List(T), Vector(N, T) etc. as type constructor calls
|
||||
return self.resolveTypeCallWithBindings(&cl);
|
||||
},
|
||||
.closure_type_expr => |ct| {
|
||||
return self.resolveClosureTypeWithBindings(&ct);
|
||||
},
|
||||
.function_type_expr => |ft| {
|
||||
return self.resolveFunctionTypeWithBindings(&ft);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
// Generic type-param binding (`$T`, or a bare return-type `T` without
|
||||
// the `$` prefix) — owned by TypeResolver via the explicit ResolveEnv.
|
||||
// The parameterized / call / closure / function arms that used to live
|
||||
// here were redundant with the unconditional handling just below (both
|
||||
// read the active bindings through the same resolvers), so they're gone.
|
||||
if (TypeResolver.resolveBinding(node, self.resolveEnv())) |t| return t;
|
||||
// Even without active type_bindings, handle parameterized types with struct templates
|
||||
if (node.data == .parameterized_type_expr) {
|
||||
return self.resolveParameterizedWithBindings(&node.data.parameterized_type_expr);
|
||||
@@ -12885,10 +12874,16 @@ pub const Lowering = struct {
|
||||
if (node.data == .type_expr and node.data.type_expr.is_generic) {
|
||||
return .unresolved;
|
||||
}
|
||||
// Alias resolution (`ShaderHandle :: u32`, `Vec4 ::
|
||||
// Vector(4,f32)`) is now handled inside `resolveTypeName`
|
||||
// via the `TypeTable.aliases` borrow loaned at lowerRoot.
|
||||
return type_bridge.resolveAstType(node, &self.module.types);
|
||||
// Bare type names resolve through TypeResolver, which reads the
|
||||
// canonical alias table directly (`ProgramIndex.type_alias_map`) — this
|
||||
// path no longer depends on the `TypeTable.aliases` borrow. Other node
|
||||
// kinds (inline type decls, error types) still route through type_bridge
|
||||
// (A2.3 converges its remaining `resolveAstType` callers).
|
||||
switch (node.data) {
|
||||
.type_expr => |te| return self.typeResolver().resolveName(te.name),
|
||||
.identifier => |id| return self.typeResolver().resolveName(id.name),
|
||||
else => return type_bridge.resolveAstType(node, &self.module.types),
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve a `Closure(...)` type expression with the active type/pack
|
||||
|
||||
Reference in New Issue
Block a user