astgen: implement anonymous struct init with result type
Handle anonymous struct init (.{.a = b}) when the result location has
a type (RL_TY/RL_COERCED_TY). Emit validate_struct_init_result_ty and
struct_init_field_type instructions, matching upstream AstGen.zig:
1706-1731 and structInitExprTyped.
Also add validate_struct_init_result_ty to test comparison functions
and fix char literal escape sequences.
build.zig corpus: improved from 25 to 3 inst diff (remaining:
as_node coercion in rvalue).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
38
astgen.c
38
astgen.c
@@ -3047,7 +3047,43 @@ static uint32_t structInitExpr(
|
||||
}
|
||||
|
||||
if (type_expr_node == 0 && fields_len > 0) {
|
||||
// Anonymous struct init (AstGen.zig:1864).
|
||||
// Anonymous struct init with RL type (AstGen.zig:1706-1731).
|
||||
if (rl.tag == RL_TY || rl.tag == RL_COERCED_TY) {
|
||||
uint32_t ty_inst = rl.data;
|
||||
// validate_struct_init_result_ty (AstGen.zig:1710-1713).
|
||||
ensureExtraCapacity(ag, 2);
|
||||
uint32_t val_payload = ag->extra_len;
|
||||
ag->extra[ag->extra_len++] = ty_inst;
|
||||
ag->extra[ag->extra_len++] = fields_len;
|
||||
addPlNodePayloadIndex(gz,
|
||||
ZIR_INST_VALIDATE_STRUCT_INIT_RESULT_TY, node, val_payload);
|
||||
// structInitExprTyped (AstGen.zig:1896-1931).
|
||||
ensureExtraCapacity(ag, 3 + fields_len * 2);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
ag->extra[ag->extra_len++] = node;
|
||||
ag->extra[ag->extra_len++] = ag->source_line;
|
||||
ag->extra[ag->extra_len++] = fields_len;
|
||||
uint32_t items_start = ag->extra_len;
|
||||
ag->extra_len += fields_len * 2;
|
||||
for (uint32_t i = 0; i < fields_len; i++) {
|
||||
uint32_t field_init = fields[i];
|
||||
uint32_t name_token = firstToken(tree, field_init) - 2;
|
||||
uint32_t str_index = identAsString(ag, name_token);
|
||||
uint32_t field_ty_inst = addPlNodeBin(gz,
|
||||
ZIR_INST_STRUCT_INIT_FIELD_TYPE, field_init, ty_inst,
|
||||
str_index);
|
||||
ResultLoc elem_rl = { .tag = RL_COERCED_TY,
|
||||
.data = field_ty_inst, .src_node = 0 };
|
||||
uint32_t init_ref
|
||||
= exprRl(gz, scope, elem_rl, field_init);
|
||||
ag->extra[items_start + i * 2]
|
||||
= field_ty_inst - ZIR_REF_START_INDEX;
|
||||
ag->extra[items_start + i * 2 + 1] = init_ref;
|
||||
}
|
||||
return addPlNodePayloadIndex(
|
||||
gz, ZIR_INST_STRUCT_INIT, node, payload_index);
|
||||
}
|
||||
// Anonymous struct init without RL type (AstGen.zig:1864).
|
||||
// StructInitAnon payload: abs_node, abs_line, fields_len.
|
||||
ensureExtraCapacity(ag, 3 + fields_len * 2);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
|
||||
@@ -500,6 +500,7 @@ fn expectEqualData(
|
||||
.struct_init_ref,
|
||||
.validate_array_init_ref_ty,
|
||||
.validate_array_init_ty,
|
||||
.validate_struct_init_result_ty,
|
||||
=> {
|
||||
const r = ref.pl_node;
|
||||
const g = got.pl_node;
|
||||
@@ -818,6 +819,7 @@ fn dataMatches(tag: Zir.Inst.Tag, ref: Zir.Inst.Data, got: c.ZirInstData) bool {
|
||||
.struct_init_ref,
|
||||
.validate_array_init_ref_ty,
|
||||
.validate_array_init_ty,
|
||||
.validate_struct_init_result_ty,
|
||||
=> {
|
||||
return @intFromEnum(ref.pl_node.src_node) == got.pl_node.src_node and
|
||||
ref.pl_node.payload_index == got.pl_node.payload_index;
|
||||
@@ -988,7 +990,7 @@ test "astgen: corpus test_all.zig" {
|
||||
}
|
||||
|
||||
test "astgen: corpus build.zig" {
|
||||
if (true) return error.SkipZigTest; // TODO: 25 inst diff, struct init result_ty
|
||||
if (true) return error.SkipZigTest; // TODO: 3 inst diff (as_node coercion)
|
||||
const gpa = std.testing.allocator;
|
||||
try corpusCheck(gpa, "build.zig", @embedFile("build.zig"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user