astgen: add reachableExprComptime and comptime_token handling in varDecl

Port two missing features from upstream AstGen.zig varDecl:

1. Add reachableExprComptime (AstGen.zig:418-438) which wraps init
   expressions in comptimeExpr when force_comptime is set, and checks
   for noreturn results. Replace plain exprRl calls in all three varDecl
   paths (const rvalue, const alloc, var) with reachableExprComptime.

2. Extract comptime_token by scanning backwards from mut_token (matching
   Ast.zig fullVarDeclComponents). For const path, set force_comptime to
   wrap init in comptime block. For var path, use comptime_token to set
   is_comptime which selects alloc_comptime_mut/alloc_inferred_comptime_mut
   tags and sets maybe_comptime on the scope.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 22:42:31 +00:00
parent 52ce6ea81a
commit 91e1d1bd2e

View File

@@ -2314,6 +2314,27 @@ static uint32_t reachableExpr(GenZir* gz, Scope* scope, ResultLoc rl,
return result; return result;
} }
// Forward declaration needed by reachableExprComptime.
static uint32_t comptimeExpr(
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node, uint32_t reason);
// Mirrors reachableExprComptime (AstGen.zig:418-438).
// Like reachableExpr but optionally wraps in comptimeExpr when
// comptime_reason is non-zero (i.e. force_comptime is set).
static uint32_t reachableExprComptime(GenZir* gz, Scope* scope, ResultLoc rl,
uint32_t node, uint32_t reachable_node, uint32_t comptime_reason) {
uint32_t result;
if (comptime_reason != 0)
result = comptimeExpr(gz, scope, rl, node, comptime_reason);
else
result = exprRl(gz, scope, rl, node);
if (refIsNoReturn(gz, result)) {
(void)reachable_node;
SET_ERROR(gz->astgen);
}
return result;
}
static uint32_t tryResolvePrimitiveIdent(GenZir* gz, uint32_t node); static uint32_t tryResolvePrimitiveIdent(GenZir* gz, uint32_t node);
// SimpleComptimeReason (std.zig:727) — values used in block_comptime payload. // SimpleComptimeReason (std.zig:727) — values used in block_comptime payload.
@@ -6586,6 +6607,14 @@ static void varDecl(GenZir* gz, Scope* scope, uint32_t node,
uint32_t ident_name = identAsString(ag, name_token); uint32_t ident_name = identAsString(ag, name_token);
// Extract comptime_token by scanning backwards from mut_token
// (Ast.zig:2012-2023, fullVarDeclComponents).
bool has_comptime_token = false;
if (mut_token > 0
&& tree->tokens.tags[mut_token - 1] == TOKEN_KEYWORD_COMPTIME) {
has_comptime_token = true;
}
// Extract type_node and init_node based on variant. // Extract type_node and init_node based on variant.
uint32_t type_node = 0; uint32_t type_node = 0;
uint32_t init_node = 0; uint32_t init_node = 0;
@@ -6619,6 +6648,12 @@ static void varDecl(GenZir* gz, Scope* scope, uint32_t node,
if (is_const) { if (is_const) {
// --- CONST path (AstGen.zig:3232-3340) --- // --- CONST path (AstGen.zig:3232-3340) ---
// `comptime const` is a non-fatal error; treat it like the init was
// marked `comptime` (AstGen.zig:3234-3239).
uint32_t force_comptime
= has_comptime_token ? COMPTIME_REASON_COMPTIME_KEYWORD : 0;
if (!nodesNeedRlContains(ag, node)) { if (!nodesNeedRlContains(ag, node)) {
// Rvalue path (AstGen.zig:3246-3271). // Rvalue path (AstGen.zig:3246-3271).
// Evaluate type annotation and build result_info // Evaluate type annotation and build result_info
@@ -6638,7 +6673,8 @@ static void varDecl(GenZir* gz, Scope* scope, uint32_t node,
} }
// Evaluate init expression (AstGen.zig:3251-3252). // Evaluate init expression (AstGen.zig:3251-3252).
uint32_t init_ref = exprRl(gz, scope, result_info, init_node); uint32_t init_ref = reachableExprComptime(
gz, scope, result_info, init_node, node, force_comptime);
if (ag->has_compile_errors) if (ag->has_compile_errors)
return; return;
@@ -6699,7 +6735,8 @@ static void varDecl(GenZir* gz, Scope* scope, uint32_t node,
init_rl.src_node = 0; init_rl.src_node = 0;
} }
init_rl.ctx = RI_CTX_CONST_INIT; init_rl.ctx = RI_CTX_CONST_INIT;
uint32_t init_ref = exprRl(gz, scope, init_rl, init_node); uint32_t init_ref = reachableExprComptime(
gz, scope, init_rl, init_node, node, force_comptime);
if (ag->has_compile_errors) if (ag->has_compile_errors)
return; return;
@@ -6733,20 +6770,22 @@ static void varDecl(GenZir* gz, Scope* scope, uint32_t node,
} else { } else {
// --- VAR path (AstGen.zig:3342-3416) --- // --- VAR path (AstGen.zig:3342-3416) ---
// comptime_token handling (AstGen.zig:3343-3345).
bool is_comptime = has_comptime_token || gz->is_comptime;
uint32_t alloc_ref; uint32_t alloc_ref;
bool resolve_inferred = false; bool resolve_inferred = false;
if (type_node != 0) { if (type_node != 0) {
// Typed var: alloc_mut (AstGen.zig:3361-3375). // Typed var: alloc_mut (AstGen.zig:3361-3375).
uint32_t type_ref = typeExpr(gz, scope, type_node); uint32_t type_ref = typeExpr(gz, scope, type_node);
ZirInstTag alloc_tag = gz->is_comptime ZirInstTag alloc_tag = is_comptime ? ZIR_INST_ALLOC_COMPTIME_MUT
? ZIR_INST_ALLOC_COMPTIME_MUT : ZIR_INST_ALLOC_MUT;
: ZIR_INST_ALLOC_MUT;
alloc_ref = addUnNode(gz, alloc_tag, type_ref, node); alloc_ref = addUnNode(gz, alloc_tag, type_ref, node);
} else { } else {
// Inferred type var: alloc_inferred_mut // Inferred type var: alloc_inferred_mut
// (AstGen.zig:3384-3392). // (AstGen.zig:3384-3392).
ZirInstTag alloc_tag = gz->is_comptime ZirInstTag alloc_tag = is_comptime
? ZIR_INST_ALLOC_INFERRED_COMPTIME_MUT ? ZIR_INST_ALLOC_INFERRED_COMPTIME_MUT
: ZIR_INST_ALLOC_INFERRED_MUT; : ZIR_INST_ALLOC_INFERRED_MUT;
ZirInstData adata; ZirInstData adata;
@@ -6768,7 +6807,10 @@ static void varDecl(GenZir* gz, Scope* scope, uint32_t node,
var_init_rl.src_node = 0; var_init_rl.src_node = 0;
} }
var_init_rl.ctx = RI_CTX_NONE; var_init_rl.ctx = RI_CTX_NONE;
uint32_t init_ref = exprRl(gz, scope, var_init_rl, init_node); uint32_t comptime_reason
= has_comptime_token ? COMPTIME_REASON_COMPTIME_KEYWORD : 0;
uint32_t init_ref = reachableExprComptime(
gz, scope, var_init_rl, init_node, node, comptime_reason);
(void)init_ref; (void)init_ref;
if (ag->has_compile_errors) if (ag->has_compile_errors)
@@ -6791,7 +6833,7 @@ static void varDecl(GenZir* gz, Scope* scope, uint32_t node,
ptr_out->ptr = final_ptr; ptr_out->ptr = final_ptr;
ptr_out->token_src = name_token; ptr_out->token_src = name_token;
ptr_out->name = ident_name; ptr_out->name = ident_name;
ptr_out->maybe_comptime = gz->is_comptime; ptr_out->maybe_comptime = is_comptime;
*scope_out = &ptr_out->base; *scope_out = &ptr_out->base;
} }
} }