From ea599150cd8f9c7f8c737160f0165ce5c8e11134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Thu, 12 Feb 2026 20:35:58 +0000 Subject: [PATCH] astgen: implement error set declarations Port errorSetDecl from upstream AstGen.zig:5905-5955. Replaces the SET_ERROR placeholder at the ERROR_SET_DECL case. Loops tokens between lbrace and rbrace, collecting identifier strings into the ErrorSetDecl payload. Also add error_set_decl to the test comparison functions. Tests added: empty error set, error set with members. Co-Authored-By: Claude Opus 4.6 --- astgen.c | 29 +++++++++++++++++++++++++---- astgen_test.zig | 26 ++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/astgen.c b/astgen.c index d764f577cb..7833a720c9 100644 --- a/astgen.c +++ b/astgen.c @@ -3476,11 +3476,32 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) { return rvalue(gz, rl, addStrTok(gz, ZIR_INST_ERROR_VALUE, str, error_token), node); } - // error_set_decl (AstGen.zig:1131-1140). + // error_set_decl (AstGen.zig:5905-5955). case AST_NODE_ERROR_SET_DECL: { - // TODO: proper error set, for now just emit a placeholder. - SET_ERROR(ag); - return ZIR_REF_VOID_VALUE; + AstData esd = ag->tree->nodes.datas[node]; + uint32_t lbrace = esd.lhs; + uint32_t rbrace = esd.rhs; + // Reserve 1 extra word for ErrorSetDecl.fields_len. + ensureExtraCapacity(ag, 1 + (rbrace - lbrace)); + uint32_t payload_index = ag->extra_len; + ag->extra_len++; // placeholder for fields_len + uint32_t fields_len = 0; + for (uint32_t tok = lbrace + 1; tok < rbrace; tok++) { + TokenizerTag ttag = ag->tree->tokens.tags[tok]; + if (ttag == TOKEN_DOC_COMMENT || ttag == TOKEN_COMMA) + continue; + if (ttag == TOKEN_IDENTIFIER) { + uint32_t str_index = identAsString(ag, tok); + ensureExtraCapacity(ag, 1); + ag->extra[ag->extra_len++] = str_index; + fields_len++; + } + } + ag->extra[payload_index] = fields_len; + return rvalue(gz, rl, + addPlNodePayloadIndex( + gz, ZIR_INST_ERROR_SET_DECL, node, payload_index), + node); } // assign in expr context (AstGen.zig:1011-1014). case AST_NODE_ASSIGN: diff --git a/astgen_test.zig b/astgen_test.zig index d162142233..93213dfb3b 100644 --- a/astgen_test.zig +++ b/astgen_test.zig @@ -472,6 +472,7 @@ fn expectEqualData( .array_cat, .array_init, .array_init_ref, + .error_set_decl, => { const r = ref.pl_node; const g = got.pl_node; @@ -780,6 +781,7 @@ fn dataMatches(tag: Zir.Inst.Tag, ref: Zir.Inst.Data, got: c.ZirInstData) bool { .array_cat, .array_init, .array_init_ref, + .error_set_decl, => { return @intFromEnum(ref.pl_node.src_node) == got.pl_node.src_node and ref.pl_node.payload_index == got.pl_node.payload_index; @@ -908,6 +910,30 @@ test "astgen: struct comptime field" { try expectEqualZir(gpa, ref_zir, c_zir); } +test "astgen: empty error set" { + const gpa = std.testing.allocator; + const source: [:0]const u8 = "const E = error{};"; + var ref_zir = try refZir(gpa, source); + defer ref_zir.deinit(gpa); + var c_ast = c.astParse(source.ptr, @intCast(source.len)); + defer c.astDeinit(&c_ast); + var c_zir = c.astGen(&c_ast); + defer c.zirDeinit(&c_zir); + try expectEqualZir(gpa, ref_zir, c_zir); +} + +test "astgen: error set with members" { + const gpa = std.testing.allocator; + const source: [:0]const u8 = "const E = error{ OutOfMemory, OutOfTime };"; + var ref_zir = try refZir(gpa, source); + defer ref_zir.deinit(gpa); + var c_ast = c.astParse(source.ptr, @intCast(source.len)); + defer c.astDeinit(&c_ast); + var c_zir = c.astGen(&c_ast); + defer c.zirDeinit(&c_zir); + try expectEqualZir(gpa, ref_zir, c_zir); +} + test "astgen: corpus test_all.zig" { const gpa = std.testing.allocator; try corpusCheck(gpa, "test_all.zig", @embedFile("test_all.zig"));