commit e3af422003046575754ce886fb0748cf307ff19f (tree)
parent 7af3e9e6b79a95a95c282344be02e540fb571d07
Author: Motiejus <motiejus@jakstys.lt>
Date: Fri, 27 Feb 2026 14:56:34 +0000
sema: fix analyzeNavValC default, add type body fallback
Two changes to improve IP entry matching for declarations whose value
bodies can't be fully evaluated:
1. analyzeNavValC: change default result from IP_INDEX_VOID_VALUE to
IP_INDEX_NONE. Previously, unevaluable declarations (e.g. struct
literals like `const lime1: CpuModel = .{...}`) got resolved_type
set to void, causing spurious *const void entries.
2. analyzeNavValC: when value body evaluation fails, extract and resolve
the TYPE annotation body from ZIR. For `const x: T = <unevaluable>`,
this sets resolved_type to T so resolveNavRef can create a correct
ptr_nav(*const T) instead of no entry at all.
3. getTypeBodyFromZir: new helper to extract the type body from a
ZIR_INST_DECLARATION, complementing getValueBodyFromZir.
IP gap for neghf2 reduced: first mismatch moved from [692] to [699].
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat:
| M | stage0/sema.c | | | 60 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
1 file changed, 58 insertions(+), 2 deletions(-)
diff --git a/stage0/sema.c b/stage0/sema.c
@@ -2772,6 +2772,8 @@ static void resolveRootInStartModule(
// Forward declaration for getValueBodyFromZir (defined later at ~line 7032).
static void getValueBodyFromZir(const Zir* zir, uint32_t decl_inst,
const uint32_t** body_out, uint32_t* body_len_out);
+static void getTypeBodyFromZir(const Zir* zir, uint32_t decl_inst,
+ const uint32_t** body_out, uint32_t* body_len_out);
// --- resolveZirRefValue ---
// Resolve a ZIR ref from an arbitrary module's ZIR to an IP index.
@@ -4844,7 +4846,7 @@ static InternPoolIndex analyzeNavValC(uint32_t nav_idx) {
bool completed
= analyzeBodyInner(&mini_sema, &ct_block, value_body, value_body_len);
- AirInstRef result = AIR_REF_FROM_IP(IP_INDEX_VOID_VALUE);
+ AirInstRef result = AIR_REF_FROM_IP(IP_INDEX_NONE);
if (!completed) {
uint32_t break_inst = mini_sema.comptime_break_inst;
ZirInstData break_data = mini_sema.code.inst_datas[break_inst];
@@ -4857,8 +4859,30 @@ static InternPoolIndex analyzeNavValC(uint32_t nav_idx) {
semaBlockDeinit(&ct_block);
semaDeinit(&mini_sema);
- if (!AIR_REF_IS_IP(result))
+ if (!AIR_REF_IS_IP(result) || AIR_REF_TO_IP(result) == IP_INDEX_NONE) {
+ // Value body evaluation failed. Try to resolve the TYPE annotation
+ // so that resolveNavRef can create a ptr_nav with the correct type.
+ // For `const lime1: CpuModel = .{...}`, the type body resolves to
+ // CpuModel even though the struct literal can't be evaluated.
+ const uint32_t* type_body = NULL;
+ uint32_t type_body_len = 0;
+ getTypeBodyFromZir(zir, nav->zir_index, &type_body, &type_body_len);
+ if (type_body && type_body_len > 0) {
+ uint32_t last_inst = type_body[type_body_len - 1];
+ if (last_inst < zir->inst_len
+ && zir->inst_tags[last_inst] == ZIR_INST_BREAK_INLINE) {
+ ZirInstRef op = zir->inst_datas[last_inst].break_data.operand;
+ InternPoolIndex type_result
+ = resolveZirTypeRef(zir, op, ns_idx, file_idx);
+ if (type_result != IP_INDEX_NONE) {
+ nav = ipGetNav(nav_idx);
+ nav->resolved_type = type_result;
+ return type_result;
+ }
+ }
+ }
return IP_INDEX_NONE;
+ }
InternPoolIndex result_ip = AIR_REF_TO_IP(result);
InternPoolIndex result_type = ipTypeOf(s_module_ip, result_ip);
@@ -10696,6 +10720,38 @@ static void getValueBodyFromZir(const Zir* zir, uint32_t decl_inst,
*body_out = &zir->extra[di];
}
+// getTypeBodyFromZir: extract type body from a ZIR_INST_DECLARATION.
+// Similar to getValueBodyFromZir but returns the type annotation body
+// instead of the value body.
+static void getTypeBodyFromZir(const Zir* zir, uint32_t decl_inst,
+ const uint32_t** body_out, uint32_t* body_len_out) {
+ if (zir->inst_tags[decl_inst] != ZIR_INST_DECLARATION) {
+ *body_out = NULL;
+ *body_len_out = 0;
+ return;
+ }
+ uint32_t payload = zir->inst_datas[decl_inst].declaration.payload_index;
+ uint32_t flags_1 = zir->extra[payload + 5];
+ uint32_t id = (flags_1 >> 27) & 0x1F;
+ uint32_t di = payload + 6;
+ if (declIdHasName(id))
+ di++;
+ if (declIdHasLibName(id))
+ di++;
+ uint32_t type_body_len = 0;
+ if (declIdHasTypeBody(id)) {
+ type_body_len = zir->extra[di];
+ di++;
+ }
+ if (declIdHasSpecialBodies(id))
+ di += 3; // align, linksection, addrspace lengths
+ if (declIdHasValueBody(id))
+ di++; // value_body_len
+ // di now points to start of body data; type body is first
+ *body_len_out = type_body_len;
+ *body_out = (type_body_len > 0) ? &zir->extra[di] : NULL;
+}
+
// evalCrossModuleDeclValue: evaluate a cross-module declaration's value body
// using a temporary mini-sema. Returns the comptime result (e.g. BOOL_TRUE
// or BOOL_FALSE), or VOID if the value cannot be resolved.