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:
58
astgen.c
58
astgen.c
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user