| ... | @@ -3229,39 +3229,42 @@ fn processExportsInner( | ... | @@ -3229,39 +3229,42 @@ fn processExportsInner( |
| 3229 | } | 3229 | } |
| 3230 | } | 3230 | } |
| 3231 | | 3231 | |
| 3232 | pub fn populateTestFunctions( | 3232 | pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void { |
| 3233 | pt: Zcu.PerThread, | | |
| 3234 | main_progress_node: std.Progress.Node, | | |
| 3235 | ) Allocator.Error!void { | | |
| 3236 | const zcu = pt.zcu; | 3233 | const zcu = pt.zcu; |
| 3237 | const gpa = zcu.gpa; | 3234 | const gpa = zcu.gpa; |
| 3238 | const ip = &zcu.intern_pool; | 3235 | const ip = &zcu.intern_pool; |
| | 3236 | |
| | 3237 | // Our job is to correctly set the value of the `test_functions` declaration if it has been |
| | 3238 | // analyzed and sent to codegen, It usually will have been, because the test runner will |
| | 3239 | // reference it, and `std.builtin` shouldn't have type errors. However, if it hasn't been |
| | 3240 | // analyzed, we will just terminate early, since clearly the test runner hasn't referenced |
| | 3241 | // `test_functions` so there's no point populating it. More to the the point, we potentially |
| | 3242 | // *can't* populate it without doing some type resolution, and... let's try to leave Sema in |
| | 3243 | // the past here. |
| | 3244 | |
| 3239 | const builtin_mod = zcu.builtin_modules.get(zcu.root_mod.getBuiltinOptions(zcu.comp.config).hash()).?; | 3245 | const builtin_mod = zcu.builtin_modules.get(zcu.root_mod.getBuiltinOptions(zcu.comp.config).hash()).?; |
| 3240 | const builtin_file_index = zcu.module_roots.get(builtin_mod).?.unwrap().?; | 3246 | const builtin_file_index = zcu.module_roots.get(builtin_mod).?.unwrap().?; |
| 3241 | pt.ensureFileAnalyzed(builtin_file_index) catch |err| switch (err) { | 3247 | const builtin_root_type = zcu.fileRootType(builtin_file_index); |
| 3242 | error.AnalysisFail => unreachable, // builtin module is generated so cannot be corrupt | 3248 | if (builtin_root_type == .none) return; // `@import("builtin")` never analyzed |
| 3243 | error.OutOfMemory => |e| return e, | 3249 | const builtin_namespace = Type.fromInterned(builtin_root_type).getNamespace(zcu).unwrap().?; |
| 3244 | }; | 3250 | // We know that the namespace has a `test_functions`... |
| 3245 | const builtin_root_type = Type.fromInterned(zcu.fileRootType(builtin_file_index)); | | |
| 3246 | const builtin_namespace = builtin_root_type.getNamespace(zcu).unwrap().?; | | |
| 3247 | const nav_index = zcu.namespacePtr(builtin_namespace).pub_decls.getKeyAdapted( | 3251 | const nav_index = zcu.namespacePtr(builtin_namespace).pub_decls.getKeyAdapted( |
| 3248 | try ip.getOrPutString(gpa, pt.tid, "test_functions", .no_embedded_nulls), | 3252 | try ip.getOrPutString(gpa, pt.tid, "test_functions", .no_embedded_nulls), |
| 3249 | Zcu.Namespace.NameAdapter{ .zcu = zcu }, | 3253 | Zcu.Namespace.NameAdapter{ .zcu = zcu }, |
| 3250 | ).?; | 3254 | ).?; |
| | 3255 | // ...but it might not be populated, so let's check that! |
| | 3256 | if (zcu.failed_analysis.contains(.wrap(.{ .nav_val = nav_index })) or |
| | 3257 | zcu.transitive_failed_analysis.contains(.wrap(.{ .nav_val = nav_index })) or |
| | 3258 | ip.getNav(nav_index).status != .fully_resolved) |
| 3251 | { | 3259 | { |
| 3252 | // We have to call `ensureNavValUpToDate` here in case `builtin.test_functions` | 3260 | // The value of `builtin.test_functions` was either never referenced, or failed analysis. |
| 3253 | // was not referenced by start code. | 3261 | // Either way, we don't need to do anything. |
| 3254 | zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); | 3262 | return; |
| 3255 | defer { | | |
| 3256 | zcu.sema_prog_node.end(); | | |
| 3257 | zcu.sema_prog_node = std.Progress.Node.none; | | |
| 3258 | } | | |
| 3259 | pt.ensureNavValUpToDate(nav_index) catch |err| switch (err) { | | |
| 3260 | error.AnalysisFail => return, | | |
| 3261 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3262 | }; | | |
| 3263 | } | 3263 | } |
| 3264 | | 3264 | |
| | 3265 | // Okay, `builtin.test_functions` is (potentially) referenced and valid. Our job now is to swap |
| | 3266 | // its placeholder `&.{}` value for the actual list of all test functions. |
| | 3267 | |
| 3265 | const test_fns_val = zcu.navValue(nav_index); | 3268 | const test_fns_val = zcu.navValue(nav_index); |
| 3266 | const test_fn_ty = test_fns_val.typeOf(zcu).slicePtrFieldType(zcu).childType(zcu); | 3269 | const test_fn_ty = test_fns_val.typeOf(zcu).slicePtrFieldType(zcu).childType(zcu); |
| 3267 | | 3270 | |
| ... | @@ -3363,17 +3366,8 @@ pub fn populateTestFunctions( | ... | @@ -3363,17 +3366,8 @@ pub fn populateTestFunctions( |
| 3363 | } }); | 3366 | } }); |
| 3364 | ip.mutateVarInit(test_fns_val.toIntern(), new_init); | 3367 | ip.mutateVarInit(test_fns_val.toIntern(), new_init); |
| 3365 | } | 3368 | } |
| 3366 | { | 3369 | // The linker thread is not running, so we actually need to dispatch this task directly. |
| 3367 | assert(zcu.codegen_prog_node.index == .none); | 3370 | @import("../link.zig").linkTestFunctionsNav(pt, nav_index); |
| 3368 | zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0); | | |
| 3369 | defer { | | |
| 3370 | zcu.codegen_prog_node.end(); | | |
| 3371 | zcu.codegen_prog_node = std.Progress.Node.none; | | |
| 3372 | } | | |
| 3373 | | | |
| 3374 | // The linker thread is not running, so we actually need to dispatch this task directly. | | |
| 3375 | @import("../link.zig").linkTestFunctionsNav(pt, nav_index); | | |
| 3376 | } | | |
| 3377 | } | 3371 | } |
| 3378 | | 3372 | |
| 3379 | /// Stores an error in `pt.zcu.failed_files` for this file, and sets the file | 3373 | /// Stores an error in `pt.zcu.failed_files` for this file, and sets the file |