lang: inline for element form over packs — multi-iterable parity

This commit is contained in:
agra
2026-06-11 14:42:59 +03:00
parent 03dc10bba3
commit 40805e08ec
15 changed files with 277 additions and 40 deletions

View File

@@ -407,6 +407,22 @@ pub fn resolveFieldType(self: *Lowering, ty: TypeId, field: []const u8) TypeId {
}
pub fn lowerFieldAccess(self: *Lowering, fa: *const ast.FieldAccess, span: ast.Span) Ref {
// `inline for xs (x)` element capture as the receiver: re-enter with the
// synthesized `xs[<i>]` as the object, so every pack-element rule below
// (interface-only constraint check, projection, substitution) sees the
// canonical `xs[i].<field>` shape.
if (fa.object.data == .identifier) {
if (self.scope) |scope| {
if (scope.lookup(fa.object.data.identifier.name)) |binding| {
if (binding.pack_elem) |elem| {
var patched = fa.*;
patched.object = elem;
return self.lowerFieldAccess(&patched, span);
}
}
}
}
// `error.X` — an error-tag literal. The `error` keyword in expression
// position parses as identifier "error" (E0.2), so `error.X` is a
// field access we intercept here. `error` is reserved, so this is
@@ -1602,6 +1618,9 @@ pub fn lowerExpr(self: *Lowering, node: *const Node) Ref {
}
if (self.scope) |scope| {
if (scope.lookup(id.name)) |binding| {
// `inline for xs (x)` element capture — lower the
// synthesized `xs[<i>]` it aliases.
if (binding.pack_elem) |elem| break :blk self.lowerExpr(elem);
if (binding.is_alloca) {
break :blk self.builder.load(binding.ref, binding.ty);
}