commit c3bef00f7499ea37cf5ae8d6f5e008ddf49ba583 (tree)
parent b4b778a10d8facc2fc1edb0581ba7428e1f1e937
Author: Motiejus Jakštys <motiejus@jakstys.lt>
Date: Sun, 15 Mar 2026 16:08:56 +0000
zig0: fix 6 astgen test failures
1. globalVarDecl: type break_inline used gz->decl_node_index (parent)
instead of type_gz.decl_node_index (=node), producing non-zero
offset where Zig produces 0. Fixes extern var and union-with-var.
2. switchExprNone: used refIsNoReturn(parent_gz, result) to decide
whether to emit break after switch prong body, but fullBodyExpr
returns void_value for unlabeled blocks ending with break/noreturn.
Changed to endsWithNoReturn(&scratch_scope) matching Zig. Also
fixed the same bug in switchExprErrUnionInner inline case handling.
3. switchExprNone/switchExprErrUnionInner: dbg_var_val was emitted
after save_err_ret_index, but Zig emits dbg_var_val first. Swapped
order to match.
4. switchExprErrUnionInner: identAsString for error payload was called
after operand evaluation, but Zig calls it before the first-pass
counting loop. Moved to match string_bytes ordering.
5. switchExprNone/switchExprErrUnionInner: is_simple_noreturn for else
prong didn't detect |e| return e pattern. Added identAsString
comparison matching Zig's logic (AstGen.zig:7775-7780).
All 441 tests now pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
1 file changed, 24 insertions(+), 18 deletions(-)
diff --git a/stage0/astgen.c b/stage0/astgen.c
@@ -6748,8 +6748,7 @@ static void globalVarDecl(AstGen* ag, GenZir* gz, Scope* scope,
.ctx = RI_CTX_NONE };
uint32_t type_inst
= expr(&type_gz, &type_gz.base, coerced_type_rl, vd.type_node);
- genZir_makeBreak(&type_gz, decl_inst, type_inst,
- (int32_t)node - (int32_t)gz->decl_node_index);
+ genZir_makeBreak(&type_gz, decl_inst, type_inst, 0);
}
// Record type_gz boundary for slicing.
@@ -10324,6 +10323,10 @@ static uint32_t switchExprErrUnionInner(GenZir* parent_gz, Scope* scope,
non_err_is_ref = (ri.tag == RL_REF || ri.tag == RL_REF_COERCED_TY);
}
+ // Error capture name (AstGen.zig:7106-7112).
+ // Must be before first pass to match string_bytes ordering.
+ uint32_t err_name = identAsString(ag, error_payload);
+
// First pass: count cases.
uint32_t scalar_cases_len = 0;
uint32_t multi_cases_len = 0;
@@ -10402,9 +10405,6 @@ static uint32_t switchExprErrUnionInner(GenZir* parent_gz, Scope* scope,
payload_capture_inst_is_placeholder = true;
}
- // Error capture name.
- uint32_t err_name = identAsString(ag, error_payload);
-
// Item result info.
ResultInfo item_ri = { .tag = RL_COERCED_TY,
.data = switch_inst + ZIR_REF_START_INDEX,
@@ -10588,7 +10588,7 @@ static uint32_t switchExprErrUnionInner(GenZir* parent_gz, Scope* scope,
scratch_scope.instructions_top = ag->scratch_inst_len;
uint32_t item_result = fullBodyExpr(
&scratch_scope, scope, item_ri, item);
- if (!genZir_refIsNoReturn(parent_gz, item_result))
+ if (!genZir_endsWithNoReturn(&scratch_scope))
genZir_addBreak(&scratch_scope,
ZIR_INST_BREAK_INLINE, switch_inst,
item_result,
@@ -10677,13 +10677,13 @@ static uint32_t switchExprErrUnionInner(GenZir* parent_gz, Scope* scope,
scratch_scope.instructions_top = ag->scratch_inst_len;
- if (do_err_trace && nodeMayAppendToErrorTrace(tree, operand_node))
- genZir_addSaveErrRetIndex(&scratch_scope, ZIR_REF_NONE);
-
if (dbg_var_name != 0)
genZir_addDbgVar(&scratch_scope, ZIR_INST_DBG_VAR_VAL,
dbg_var_name, dbg_var_inst);
+ if (do_err_trace && nodeMayAppendToErrorTrace(tree, operand_node))
+ genZir_addSaveErrRetIndex(&scratch_scope, ZIR_REF_NONE);
+
uint32_t body_node = cd.rhs;
uint32_t result = fullBodyExpr(&scratch_scope, sub_scope,
block_scope.break_result_info, body_node);
@@ -10729,6 +10729,15 @@ static uint32_t switchExprErrUnionInner(GenZir* parent_gz, Scope* scope,
AstData retd = tree->nodes.datas[body_node];
if (retd.lhs == 0)
is_simple_noreturn = true;
+ else if (capture == 1
+ && tree->nodes.tags[retd.lhs] == AST_NODE_IDENTIFIER) {
+ // Check |e| return e pattern (AstGen.zig:7775-7780).
+ uint32_t payload_token = arrow_token + 2;
+ uint32_t ret_ident = tree->nodes.main_tokens[retd.lhs];
+ uint32_t payload_name = identAsString(ag, payload_token);
+ uint32_t retval_name = identAsString(ag, ret_ident);
+ is_simple_noreturn = (payload_name == retval_name);
+ }
}
else_info_val = (body_len & 0x07FFFFFFu) | ((capture & 3u) << 27)
| ((is_inline ? 1u : 0u) << 29)
@@ -11150,7 +11159,7 @@ static uint32_t switchExprNone(
scratch_scope.instructions_top = ag->scratch_inst_len;
uint32_t item_result = fullBodyExpr(
&scratch_scope, scope, item_ri, item);
- if (!genZir_refIsNoReturn(parent_gz, item_result)) {
+ if (!genZir_endsWithNoReturn(&scratch_scope)) {
genZir_addBreak(&scratch_scope,
ZIR_INST_BREAK_INLINE, switch_inst,
item_result,
@@ -11274,7 +11283,7 @@ static uint32_t switchExprNone(
uint32_t body_node = cd.rhs;
uint32_t result = fullBodyExpr(&scratch_scope, sub_scope,
block_scope.break_result_info, body_node);
- if (!genZir_refIsNoReturn(parent_gz, result)) {
+ if (!genZir_endsWithNoReturn(&scratch_scope)) {
genZir_addBreak(&scratch_scope, ZIR_INST_BREAK, switch_inst,
result,
(int32_t)body_node - (int32_t)parent_gz->decl_node_index);
@@ -11305,15 +11314,12 @@ static uint32_t switchExprNone(
is_simple_noreturn = true;
else if (capture == 1
&& tree->nodes.tags[retd.lhs] == AST_NODE_IDENTIFIER) {
- // Check |e| return e pattern.
- // Simplified: just check if token slices match.
+ // Check |e| return e pattern (AstGen.zig:7775-7780).
uint32_t payload_token = arrow_token + 2;
uint32_t ret_ident = tree->nodes.main_tokens[retd.lhs];
- if (tree->tokens.starts[payload_token]
- != tree->tokens.starts[ret_ident]) {
- // Different tokens, check content.
- // (Simplified: compare strings)
- }
+ uint32_t payload_name = identAsString(ag, payload_token);
+ uint32_t retval_name = identAsString(ag, ret_ident);
+ is_simple_noreturn = (payload_name == retval_name);
}
}
else_info_val = (body_len & 0x07FFFFFFu) | ((capture & 3u) << 27)