refactor(ir): converge structural type-shape resolution onto resolveCompound (A2.3b)
Codex corrective step before the A2 merge gate: A2.3 left type_bridge with a parallel structural type-resolution algorithm and an inline tuple-literal-spread shape in lower.zig with a `.void` fallback. Finding 1 — single owner for structural shapes: - TypeResolver.resolveCompound is now the sole structural type-shape constructor. Namespaced on `table` (so the stateless type_bridge can call it) and extended to own function types, plain `Closure(P...) -> R`, and plain positional/named tuples (it already owned *T/[*]T/[]T/?T/[N]T). It returns null only for the pack-shaped forms that need caller state (`Closure(..p)`, spread tuples); OOM yields `.unresolved`. - type_bridge: deleted its 8 independent structural resolvers (resolveArray/Slice/Pointer/ManyPointer/Optional/Function/Closure/TupleType). resolveAstType delegates those node kinds to resolveCompound via a binding-free StatelessInner adapter. The only residual stateless shape code is two tiny fallbacks for the pack-shaped forms resolveCompound defers (resolveClosurePackShape — used by Into(Block) at registration time — and resolveTupleSpreadShape) plus resolveParameterizedType (kept: generic-instantiation convergence is A4.1 per PLAN-ARCH). - lower.zig: stateful resolveTypeWithBindings uses resolveCompound; the `.function_type_expr` switch arm is gone. PackResolver.resolveFunctionTypeWithBindings deleted (subsumed). Plain closures/tuples now resolve via resolveCompound in both paths; only pack closures / spread tuples reach PackResolver. Finding 2 — no `.void` failure fallback in lower.zig pack handling: - the inline tuple_literal-with-spread type assembly moved into PackResolver.resolveTupleLiteralType (returns ?TypeId; OOM `catch return .void` became `catch return .unresolved`). Alias result preserved: TypeTable.aliases stays gone; no table.aliases reads; ProgramIndex.type_alias_map threaded explicitly. type_resolver.test.zig: resolveCompound test rewritten (namespaced + new function/closure/tuple/pack-shape arms, arena-backed). Gate green: zig build, zig build test, run_examples 350/0.
This commit is contained in:
@@ -12799,11 +12799,13 @@ pub const Lowering = struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Structural compound types (`*T`, `[*]T`, `[]T`, `?T`, `[N]T`) are
|
||||
// owned by TypeResolver (A2.1). Element types recurse through the full
|
||||
// stateful resolver (`resolveInner` → here) so generic structs /
|
||||
// bindings in element position keep their resolution.
|
||||
if (self.typeResolver().resolveCompound(node, self)) |t| return t;
|
||||
// Structural type shapes — `*T`, `[*]T`, `[]T`, `?T`, `[N]T`, functions,
|
||||
// PLAIN closures, and PLAIN tuples — are owned by
|
||||
// `TypeResolver.resolveCompound` (A2.3b). Element types recurse through
|
||||
// the full stateful resolver (`resolveInner` → here) so generic structs
|
||||
// / bindings keep their resolution. resolveCompound returns null only
|
||||
// for the pack-shaped forms (`Closure(..p)`, spread tuples) below.
|
||||
if (TypeResolver.resolveCompound(&self.module.types, node, self)) |t| return t;
|
||||
// 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
|
||||
@@ -12817,48 +12819,23 @@ pub const Lowering = struct {
|
||||
if (node.data == .call) {
|
||||
return self.resolveTypeCallWithBindings(&node.data.call);
|
||||
}
|
||||
// Pointers / slices / many-pointers / optionals / arrays are owned by
|
||||
// TypeResolver (handled above). The pack-aware tuple / closure /
|
||||
// function shapes are owned by `PackResolver` (packs.zig, A2.3).
|
||||
// Plain structural shapes were handled by resolveCompound above. What
|
||||
// reaches here is the PACK-shaped subset, owned by `PackResolver`
|
||||
// (packs.zig): pack-shaped `Closure(..p)` and spread tuples. (Functions
|
||||
// are never pack-shaped at the type level — resolveCompound owns them
|
||||
// all, so there is no function arm here.)
|
||||
switch (node.data) {
|
||||
.closure_type_expr => |ct| {
|
||||
return self.packResolver().resolveClosureTypeWithBindings(&ct);
|
||||
},
|
||||
.function_type_expr => |ft| {
|
||||
return self.packResolver().resolveFunctionTypeWithBindings(&ft);
|
||||
},
|
||||
.tuple_type_expr => |tt| {
|
||||
return self.packResolver().resolveTupleTypeWithBindings(&tt);
|
||||
},
|
||||
// `(..$Ts)` in a type position (e.g. a struct field) parses as a
|
||||
// tuple LITERAL whose elements include a pack spread; expand it to
|
||||
// the bound pack's element types, same as `resolveTupleTypeWithBindings`.
|
||||
// tuple LITERAL whose elements include a pack spread; PackResolver
|
||||
// expands it (returns null when no spread, so we fall through).
|
||||
.tuple_literal => |tl| {
|
||||
var any_spread = false;
|
||||
for (tl.elements) |el| {
|
||||
if (el.value.data == .spread_expr) {
|
||||
any_spread = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (any_spread) {
|
||||
var field_ids = std.ArrayList(TypeId).empty;
|
||||
defer field_ids.deinit(self.alloc);
|
||||
for (tl.elements) |el| {
|
||||
if (el.value.data == .spread_expr) {
|
||||
if (self.packResolver().packTypeElems(el.value.data.spread_expr.operand)) |elems| {
|
||||
defer self.alloc.free(elems);
|
||||
for (elems) |e| field_ids.append(self.alloc, e) catch return .void;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
field_ids.append(self.alloc, self.resolveTypeWithBindings(el.value)) catch return .void;
|
||||
}
|
||||
return self.module.types.intern(.{ .tuple = .{
|
||||
.fields = self.alloc.dupe(TypeId, field_ids.items) catch return .void,
|
||||
.names = null,
|
||||
} });
|
||||
}
|
||||
if (self.packResolver().resolveTupleLiteralType(&tl)) |t| return t;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user