commit 7b0bb54b5c8af3bcfca57432e43fd78cae36c703 (tree)
parent 248370697e0778777dcb24c009f1b79e76dde442
Author: Motiejus <motiejus@jakstys.lt>
Date: Sat, 28 Feb 2026 16:41:57 +0000
sema: replace resolveRootInStartModule with start.zig comptime eval
Evaluate start.zig's comptime blocks via analyzeComptimeUnit instead
of calling resolveRootInStartModule. The comptime block `_ = root;`
resolves @import("root") to the root module, creating the ptr_nav
entry as a side effect of DECL_VAL import resolution.
Add @import("root") handling in ZIR_INST_IMPORT and DECL_VAL handlers,
ported from PerThread.zig doImport "root" case. The root module's
file_idx is stored in s_root_file_idx, set during semaAnalyze.
Remove resolveRootInStartModule (now dead code).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
| M | stage0/sema.c | | | 68 | +++++++++++++++++++++++++++++++++++--------------------------------- |
1 file changed, 35 insertions(+), 33 deletions(-)
diff --git a/stage0/sema.c b/stage0/sema.c
@@ -2679,30 +2679,6 @@ static bool resolveImportPath(const char* source_dir, const char* import_path,
// Forward declaration (defined later).
static InternPoolIndex ensureNavValUpToDate(uint32_t nav_idx);
-// --- resolveRootInStartModule ---
-// After loading the root module, create a ptr_nav entry for the "root"
-// Nav in start.zig's namespace. This matches the Zig compiler's
-// evaluation of start.zig's `_ = root;` comptime block.
-static void resolveRootInStartModule(
- uint32_t start_file_idx, uint32_t root_file_idx) {
- if (start_file_idx == UINT32_MAX || root_file_idx == UINT32_MAX)
- return;
-
- uint32_t start_ns_idx = s_file_namespace[start_file_idx];
- uint32_t root_nav = findNavInNamespace(start_ns_idx, "root");
- if (root_nav == UINT32_MAX)
- return;
-
- InternPoolIndex root_struct = s_file_root_type[root_file_idx];
- if (root_struct == 0 && root_file_idx > 0)
- return;
-
- InternPoolIndex ptr_type = internPtrConst(IP_INDEX_TYPE_TYPE);
- Nav* nav = ipGetNav(root_nav);
- nav->resolved_type = root_struct;
- (void)internNavPtr(ptr_type, root_nav);
-}
-
// 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);
@@ -11439,13 +11415,23 @@ static bool analyzeBodyInner(
if (strcmp(import_path, "builtin") == 0
&& s_cg_builtin_ns_idx != UINT32_MAX) {
// @import("builtin") — resolve to the CG
- // builtin module's root struct type, like any
- // other import. Field access will find navs
- // through the struct's namespace, and
- // ensureNavValUpToDate handles CG builtin navs
- // via resolveCgBuiltinField.
+ // builtin module's root struct type.
resolved
= s_namespaces[s_cg_builtin_ns_idx].owner_type;
+ } else if (strcmp(import_path, "root") == 0
+ && s_root_file_idx != UINT32_MAX) {
+ // @import("root") — the user's root module.
+ // Ported from PerThread.zig doImport "root".
+ resolved = s_file_root_type[s_root_file_idx];
+ if (s_in_main_analysis) {
+ uint32_t nav_idx2 = findNavInNamespace(
+ s_file_namespace[sema->file_idx], decl_name);
+ if (nav_idx2 != UINT32_MAX) {
+ InternPoolIndex pt
+ = internPtrConst(IP_INDEX_TYPE_TYPE);
+ (void)internNavPtr(pt, nav_idx2);
+ }
+ }
} else if (sema->source_dir) {
char import_full[1024];
if (resolveImportPath(sema->source_dir, import_path,
@@ -11501,7 +11487,8 @@ static bool analyzeBodyInner(
// Non-comptime: just load import side effects.
const char* import_path
= findDeclImportPath(sema, decl_name_idx);
- if (import_path && strcmp(import_path, "builtin") != 0) {
+ if (import_path && strcmp(import_path, "builtin") != 0
+ && strcmp(import_path, "root") != 0) {
char import_full[1024];
if (resolveImportPath(sema->source_dir, import_path,
import_full, sizeof(import_full))) {
@@ -11528,6 +11515,11 @@ static bool analyzeBodyInner(
if (strcmp(import_path, "builtin") == 0
&& s_cg_builtin_ns_idx != UINT32_MAX) {
result = s_namespaces[s_cg_builtin_ns_idx].owner_type;
+ } else if (strcmp(import_path, "root") == 0
+ && s_root_file_idx != UINT32_MAX) {
+ // @import("root") → the user's root module.
+ // Ported from PerThread.zig doImport "root" case.
+ result = s_file_root_type[s_root_file_idx];
} else if (sema->source_dir) {
char import_full[1024];
if (resolveImportPath(sema->source_dir, import_path,
@@ -12232,9 +12224,19 @@ SemaFuncAirList semaAnalyze(Sema* sema) {
sema->file_idx = root_file_idx;
(void)createFileRootStructC(root_file_idx, &sema->code);
- // Create ptr_nav for "root" in start.zig ($136),
- // matching start.zig's comptime { _ = root; }.
- resolveRootInStartModule(start_file_idx, root_file_idx);
+ // Evaluate start.zig's comptime blocks. The first block
+ // contains `_ = root;` which resolves @import("root") to
+ // the root module, creating ptr_nav ($136).
+ // Ported from upstream: start.zig comptime evaluated after
+ // root module is registered so @import("root") resolves.
+ if (start_file_idx != UINT32_MAX) {
+ uint32_t start_ns = s_file_namespace[start_file_idx];
+ const SemaNamespace* sns = &s_namespaces[start_ns];
+ for (uint32_t ci = 0; ci < sns->comptime_decl_count; ci++) {
+ analyzeComptimeUnit(
+ start_file_idx, sns->comptime_decls[ci]);
+ }
+ }
// Load std/builtin.zig chain ($137+).
resolveBuiltinModuleChain(start_file_idx);