mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Zcu: handle unreferenced test_functions correctly
Previously, `PerThread.populateTestFunctions` was analyzing the `test_functions` declaration if it hadn't already been analyzed, so that it could then populate it. However, the logic for doing this wasn't actually correct, because it didn't trigger the necessary type resolution. I could have tried to fix this, but there's actually a simpler solution! If the `test_functions` declaration isn't referenced or has a compile error, then we simply don't need to update it; either it's unreferenced so its value doesn't matter, or we're going to get a compile error anyway. Either way, we can just give up early. This avoids doing semantic analysis after `performAllTheWork` finishes. Also, get rid of the "Code Generation" progress node while updating the test decl: this is a linking task.
This commit is contained in:
parent
4d2b216121
commit
d7afd797cc
2 changed files with 27 additions and 33 deletions
|
|
@ -2817,7 +2817,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
|
||||||
// The `test_functions` decl has been intentionally postponed until now,
|
// The `test_functions` decl has been intentionally postponed until now,
|
||||||
// at which point we must populate it with the list of test functions that
|
// at which point we must populate it with the list of test functions that
|
||||||
// have been discovered and not filtered out.
|
// have been discovered and not filtered out.
|
||||||
try pt.populateTestFunctions(main_progress_node);
|
try pt.populateTestFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
try pt.processExports();
|
try pt.processExports();
|
||||||
|
|
|
||||||
|
|
@ -3229,39 +3229,42 @@ fn processExportsInner(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn populateTestFunctions(
|
pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {
|
||||||
pt: Zcu.PerThread,
|
|
||||||
main_progress_node: std.Progress.Node,
|
|
||||||
) Allocator.Error!void {
|
|
||||||
const zcu = pt.zcu;
|
const zcu = pt.zcu;
|
||||||
const gpa = zcu.gpa;
|
const gpa = zcu.gpa;
|
||||||
const ip = &zcu.intern_pool;
|
const ip = &zcu.intern_pool;
|
||||||
|
|
||||||
|
// Our job is to correctly set the value of the `test_functions` declaration if it has been
|
||||||
|
// analyzed and sent to codegen, It usually will have been, because the test runner will
|
||||||
|
// reference it, and `std.builtin` shouldn't have type errors. However, if it hasn't been
|
||||||
|
// analyzed, we will just terminate early, since clearly the test runner hasn't referenced
|
||||||
|
// `test_functions` so there's no point populating it. More to the the point, we potentially
|
||||||
|
// *can't* populate it without doing some type resolution, and... let's try to leave Sema in
|
||||||
|
// the past here.
|
||||||
|
|
||||||
const builtin_mod = zcu.builtin_modules.get(zcu.root_mod.getBuiltinOptions(zcu.comp.config).hash()).?;
|
const builtin_mod = zcu.builtin_modules.get(zcu.root_mod.getBuiltinOptions(zcu.comp.config).hash()).?;
|
||||||
const builtin_file_index = zcu.module_roots.get(builtin_mod).?.unwrap().?;
|
const builtin_file_index = zcu.module_roots.get(builtin_mod).?.unwrap().?;
|
||||||
pt.ensureFileAnalyzed(builtin_file_index) catch |err| switch (err) {
|
const builtin_root_type = zcu.fileRootType(builtin_file_index);
|
||||||
error.AnalysisFail => unreachable, // builtin module is generated so cannot be corrupt
|
if (builtin_root_type == .none) return; // `@import("builtin")` never analyzed
|
||||||
error.OutOfMemory => |e| return e,
|
const builtin_namespace = Type.fromInterned(builtin_root_type).getNamespace(zcu).unwrap().?;
|
||||||
};
|
// We know that the namespace has a `test_functions`...
|
||||||
const builtin_root_type = Type.fromInterned(zcu.fileRootType(builtin_file_index));
|
|
||||||
const builtin_namespace = builtin_root_type.getNamespace(zcu).unwrap().?;
|
|
||||||
const nav_index = zcu.namespacePtr(builtin_namespace).pub_decls.getKeyAdapted(
|
const nav_index = zcu.namespacePtr(builtin_namespace).pub_decls.getKeyAdapted(
|
||||||
try ip.getOrPutString(gpa, pt.tid, "test_functions", .no_embedded_nulls),
|
try ip.getOrPutString(gpa, pt.tid, "test_functions", .no_embedded_nulls),
|
||||||
Zcu.Namespace.NameAdapter{ .zcu = zcu },
|
Zcu.Namespace.NameAdapter{ .zcu = zcu },
|
||||||
).?;
|
).?;
|
||||||
|
// ...but it might not be populated, so let's check that!
|
||||||
|
if (zcu.failed_analysis.contains(.wrap(.{ .nav_val = nav_index })) or
|
||||||
|
zcu.transitive_failed_analysis.contains(.wrap(.{ .nav_val = nav_index })) or
|
||||||
|
ip.getNav(nav_index).status != .fully_resolved)
|
||||||
{
|
{
|
||||||
// We have to call `ensureNavValUpToDate` here in case `builtin.test_functions`
|
// The value of `builtin.test_functions` was either never referenced, or failed analysis.
|
||||||
// was not referenced by start code.
|
// Either way, we don't need to do anything.
|
||||||
zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
|
return;
|
||||||
defer {
|
|
||||||
zcu.sema_prog_node.end();
|
|
||||||
zcu.sema_prog_node = std.Progress.Node.none;
|
|
||||||
}
|
|
||||||
pt.ensureNavValUpToDate(nav_index) catch |err| switch (err) {
|
|
||||||
error.AnalysisFail => return,
|
|
||||||
error.OutOfMemory => return error.OutOfMemory,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Okay, `builtin.test_functions` is (potentially) referenced and valid. Our job now is to swap
|
||||||
|
// its placeholder `&.{}` value for the actual list of all test functions.
|
||||||
|
|
||||||
const test_fns_val = zcu.navValue(nav_index);
|
const test_fns_val = zcu.navValue(nav_index);
|
||||||
const test_fn_ty = test_fns_val.typeOf(zcu).slicePtrFieldType(zcu).childType(zcu);
|
const test_fn_ty = test_fns_val.typeOf(zcu).slicePtrFieldType(zcu).childType(zcu);
|
||||||
|
|
||||||
|
|
@ -3363,17 +3366,8 @@ pub fn populateTestFunctions(
|
||||||
} });
|
} });
|
||||||
ip.mutateVarInit(test_fns_val.toIntern(), new_init);
|
ip.mutateVarInit(test_fns_val.toIntern(), new_init);
|
||||||
}
|
}
|
||||||
{
|
// The linker thread is not running, so we actually need to dispatch this task directly.
|
||||||
assert(zcu.codegen_prog_node.index == .none);
|
@import("../link.zig").linkTestFunctionsNav(pt, nav_index);
|
||||||
zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0);
|
|
||||||
defer {
|
|
||||||
zcu.codegen_prog_node.end();
|
|
||||||
zcu.codegen_prog_node = std.Progress.Node.none;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The linker thread is not running, so we actually need to dispatch this task directly.
|
|
||||||
@import("../link.zig").linkTestFunctionsNav(pt, nav_index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stores an error in `pt.zcu.failed_files` for this file, and sets the file
|
/// Stores an error in `pt.zcu.failed_files` for this file, and sets the file
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue