sema: skip lazy const declarations in zirStructDecl
The upstream Zig sema is lazy — it only evaluates const declarations when first accessed. The C sema was eagerly evaluating ALL non-function declarations, including ones never accessed during analysis (e.g. `pub const panic = common.panic` in neghf2.zig). Only evaluate comptime declarations (id == 3) and function declarations (detected by ZIR_INST_FUNC / FUNC_FANCY). Skip all other const/var declarations, matching upstream behavior. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5608,23 +5608,13 @@ static void zirStructDecl(Sema* sema, SemaBlock* block, uint32_t inst) {
|
||||
}
|
||||
|
||||
// Analyze value body if present.
|
||||
// The upstream Zig sema is lazy: it only evaluates const
|
||||
// declarations when first accessed. We must only eagerly
|
||||
// evaluate comptime declarations (id == 3) and function
|
||||
// declarations (detected by ZIR_INST_FUNC / FUNC_FANCY).
|
||||
// All other const/var declarations are skipped here.
|
||||
bool is_comptime_decl = (id == 3);
|
||||
if (value_body_len > 0) {
|
||||
// Set declaration context so zirFunc can read name/linkage.
|
||||
uint32_t old_decl_name = sema->cur_decl_name;
|
||||
bool old_decl_is_export = sema->cur_decl_is_export;
|
||||
sema->cur_decl_name = decl_name;
|
||||
sema->cur_decl_is_export = declIdIsExport(id);
|
||||
|
||||
// Reset compile errors before each declaration so a
|
||||
// failure in one comptime decl doesn't cascade.
|
||||
sema->has_compile_errors = false;
|
||||
|
||||
// Evaluate non-function declarations in a comptime block.
|
||||
// In upstream, struct declarations are lazily evaluated at
|
||||
// comptime. Using a comptime block here prevents runtime
|
||||
// inline expansions (which would produce extra
|
||||
// DBG_INLINE_BLOCKs). Function declarations (func/
|
||||
// func_fancy) still use the parent block.
|
||||
const uint32_t* value_body = &sema->code.extra[di];
|
||||
bool is_func = false;
|
||||
for (uint32_t vi = 0; vi < value_body_len; vi++) {
|
||||
@@ -5634,20 +5624,34 @@ static void zirStructDecl(Sema* sema, SemaBlock* block, uint32_t inst) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_func) {
|
||||
(void)analyzeBodyInner(
|
||||
sema, block, value_body, value_body_len);
|
||||
} else {
|
||||
SemaBlock decl_block;
|
||||
semaBlockInit(&decl_block, sema, block);
|
||||
decl_block.is_comptime = true;
|
||||
(void)analyzeBodyInner(
|
||||
sema, &decl_block, value_body, value_body_len);
|
||||
semaBlockDeinit(&decl_block);
|
||||
}
|
||||
|
||||
sema->cur_decl_name = old_decl_name;
|
||||
sema->cur_decl_is_export = old_decl_is_export;
|
||||
if (is_func || is_comptime_decl) {
|
||||
// Set declaration context so zirFunc can read
|
||||
// name/linkage.
|
||||
uint32_t old_decl_name = sema->cur_decl_name;
|
||||
bool old_decl_is_export = sema->cur_decl_is_export;
|
||||
sema->cur_decl_name = decl_name;
|
||||
sema->cur_decl_is_export = declIdIsExport(id);
|
||||
|
||||
// Reset compile errors before each declaration so a
|
||||
// failure in one comptime decl doesn't cascade.
|
||||
sema->has_compile_errors = false;
|
||||
|
||||
if (is_func) {
|
||||
(void)analyzeBodyInner(
|
||||
sema, block, value_body, value_body_len);
|
||||
} else {
|
||||
SemaBlock decl_block;
|
||||
semaBlockInit(&decl_block, sema, block);
|
||||
decl_block.is_comptime = true;
|
||||
(void)analyzeBodyInner(
|
||||
sema, &decl_block, value_body, value_body_len);
|
||||
semaBlockDeinit(&decl_block);
|
||||
}
|
||||
|
||||
sema->cur_decl_name = old_decl_name;
|
||||
sema->cur_decl_is_export = old_decl_is_export;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user