diff --git a/stage0/sema.c b/stage0/sema.c index 861a8c8e7b..d678fd39a5 100644 --- a/stage0/sema.c +++ b/stage0/sema.c @@ -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; + } } } }