stages_test: use directory symlink for Air comparison source files

Instead of writing file content to /tmp (which broke relative imports
like codecs/asn1.zig), symlink the original file's directory into
.zig-cache/tmp/zig0_test. This keeps the module root outside lib/std/
(avoiding module path conflicts) while preserving subdirectory import
resolution through the symlink.

In verbose_air.zig, use Compilation.Path.fromUnresolved to construct the
module root so it gets the same canonical root enum (.local_cache, etc.)
as file paths computed during import resolution, avoiding isNested
root mismatches.

Fixes the codecs.zig test failure (434/434 tests now pass).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 19:13:08 +00:00
parent 882ad78257
commit 63a4e708ee
2 changed files with 23 additions and 15 deletions

View File

@@ -204,11 +204,14 @@ fn zigCompareAirImpl(
.is_test = false,
});
// Split src_path into directory and filename for the Module.
// Construct the module root path through fromUnresolved so it gets the same
// canonical root (.zig_lib, .local_cache, etc.) as file paths computed later.
// This avoids root mismatches in isNested checks, and also avoids resolving
// symlinks — the caller may use a directory symlink to keep the module root
// outside lib/std/ while preserving relative import resolution.
const src_dir = std.fs.path.dirname(src_path) orelse ".";
const src_basename = std.fs.path.basename(src_path);
const abs_src_dir = try std.fs.cwd().realpathAlloc(arena, src_dir);
const root_path: Compilation.Path = .{ .root = .none, .sub_path = abs_src_dir };
const root_path = try Compilation.Path.fromUnresolved(arena, dirs, &.{src_dir});
const root_mod = try Package.Module.create(arena, .{
.paths = .{

View File

@@ -20,14 +20,14 @@ test "stages: corpus" {
@setEvalBranchQuota(corpus_files.len * 2);
const gpa = std.testing.allocator;
inline for (corpus_files) |path| {
stagesCheck(gpa, @embedFile(path)) catch {
stagesCheck(gpa, path, @embedFile(path)) catch {
std.debug.print("FAIL: {s}\n", .{path});
return error.TestFailed;
};
}
}
fn stagesCheck(gpa: Allocator, source: [:0]const u8) !void {
fn stagesCheck(gpa: Allocator, comptime path: []const u8, source: [:0]const u8) !void {
// Parse once with C parser
var c_ast = c.astParse(source.ptr, @intCast(source.len));
defer c.astDeinit(&c_ast);
@@ -71,17 +71,22 @@ fn stagesCheck(gpa: Allocator, source: [:0]const u8) !void {
var c_func_air_list = sc.semaAnalyze(&c_sema);
defer sc.semaFuncAirListDeinit(&c_func_air_list);
// Write source to a temp file to avoid module path conflicts
// (source files inside lib/std/ conflict with the 'std' module).
const tmp_path = "/tmp/zig0_stages_test_tmp.zig";
{
const f = std.fs.cwd().createFile(tmp_path, .{}) catch return error.TmpFileCreate;
defer f.close();
f.writeAll(source) catch return error.TmpFileWrite;
}
defer std.fs.cwd().deleteFile(tmp_path) catch {};
// Symlink the original file's directory to avoid module path conflicts
// (source files inside lib/std/ conflict with the 'std' module)
// while preserving relative import resolution for subdirectory imports.
const this_dir = comptime std.fs.path.dirname(@src().file) orelse ".";
const original_dir = comptime std.fs.path.dirname(this_dir ++ "/" ++ path) orelse ".";
const symlink_path = ".zig-cache/tmp/zig0_test";
var cmp_result = zig_compare_air(tmp_path, @ptrCast(c_func_air_list.items), c_func_air_list.len);
const abs_original_dir = std.fs.cwd().realpathAlloc(gpa, original_dir) catch return error.ResolvePath;
defer gpa.free(abs_original_dir);
std.fs.cwd().deleteFile(symlink_path) catch {};
std.fs.cwd().symLink(abs_original_dir, symlink_path, .{ .is_directory = true }) catch return error.SymlinkCreate;
defer std.fs.cwd().deleteFile(symlink_path) catch {};
const test_src: [:0]const u8 = symlink_path ++ "/" ++ comptime std.fs.path.basename(path);
var cmp_result = zig_compare_air(test_src.ptr, @ptrCast(c_func_air_list.items), c_func_air_list.len);
defer zig_compare_result_free(&cmp_result);
if (cmp_result.error_msg) |e| {
std.debug.print("zig_compare_air error: {s}\n", .{std.mem.span(e)});