diff --git a/src/Compilation.zig b/src/Compilation.zig index b0af925e29..98e38f4305 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1610,6 +1610,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { const builtin_pkg = try Package.createWithDir( gpa, + "builtin", zig_cache_artifact_directory, null, "builtin.zig", @@ -1618,6 +1619,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { const std_pkg = try Package.createWithDir( gpa, + "std", options.zig_lib_directory, "std", "std.zig", @@ -1625,11 +1627,14 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { errdefer std_pkg.destroy(gpa); const root_pkg = if (options.is_test) root_pkg: { + // TODO: we currently have two packages named 'root' here, which is weird. This + // should be changed as part of the resolution of #12201 const test_pkg = if (options.test_runner_path) |test_runner| - try Package.create(gpa, null, test_runner) + try Package.create(gpa, "root", null, test_runner) else try Package.createWithDir( gpa, + "root", options.zig_lib_directory, null, "test_runner.zig", @@ -1640,9 +1645,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { } else main_pkg; errdefer if (options.is_test) root_pkg.destroy(gpa); - try main_pkg.addAndAdopt(gpa, "builtin", builtin_pkg); - try main_pkg.add(gpa, "root", root_pkg); - try main_pkg.addAndAdopt(gpa, "std", std_pkg); + try main_pkg.addAndAdopt(gpa, builtin_pkg); + try main_pkg.add(gpa, root_pkg); + try main_pkg.addAndAdopt(gpa, std_pkg); const main_pkg_is_std = m: { const std_path = try std.fs.path.resolve(arena, &[_][]const u8{ @@ -5320,6 +5325,7 @@ fn buildOutputFromZig( var main_pkg: Package = .{ .root_src_directory = comp.zig_lib_directory, .root_src_path = src_basename, + .name = "root", }; defer main_pkg.deinitTable(comp.gpa); const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len]; diff --git a/src/Module.zig b/src/Module.zig index f2f51907cb..93325bfec5 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3220,16 +3220,11 @@ pub fn deinit(mod: *Module) void { // The callsite of `Compilation.create` owns the `main_pkg`, however // Module owns the builtin and std packages that it adds. if (mod.main_pkg.table.fetchRemove("builtin")) |kv| { - gpa.free(kv.key); kv.value.destroy(gpa); } if (mod.main_pkg.table.fetchRemove("std")) |kv| { - gpa.free(kv.key); kv.value.destroy(gpa); } - if (mod.main_pkg.table.fetchRemove("root")) |kv| { - gpa.free(kv.key); - } if (mod.root_pkg != mod.main_pkg) { mod.root_pkg.destroy(gpa); } diff --git a/src/Package.zig b/src/Package.zig index 23a0549aa7..f8823cc74e 100644 --- a/src/Package.zig +++ b/src/Package.zig @@ -24,10 +24,13 @@ table: Table = .{}, parent: ?*Package = null, /// Whether to free `root_src_directory` on `destroy`. root_src_directory_owned: bool = false, +/// This information can be recovered from 'table', but it's more convenient to store on the package. +name: []const u8, /// Allocate a Package. No references to the slices passed are kept. pub fn create( gpa: Allocator, + name: []const u8, /// Null indicates the current working directory root_src_dir_path: ?[]const u8, /// Relative to root_src_dir_path @@ -42,6 +45,9 @@ pub fn create( const owned_src_path = try gpa.dupe(u8, root_src_path); errdefer gpa.free(owned_src_path); + const owned_name = try gpa.dupe(u8, name); + errdefer gpa.free(owned_name); + ptr.* = .{ .root_src_directory = .{ .path = owned_dir_path, @@ -49,6 +55,7 @@ pub fn create( }, .root_src_path = owned_src_path, .root_src_directory_owned = true, + .name = owned_name, }; return ptr; @@ -56,6 +63,7 @@ pub fn create( pub fn createWithDir( gpa: Allocator, + name: []const u8, directory: Compilation.Directory, /// Relative to `directory`. If null, means `directory` is the root src dir /// and is owned externally. @@ -69,6 +77,9 @@ pub fn createWithDir( const owned_src_path = try gpa.dupe(u8, root_src_path); errdefer gpa.free(owned_src_path); + const owned_name = try gpa.dupe(u8, name); + errdefer gpa.free(owned_name); + if (root_src_dir_path) |p| { const owned_dir_path = try directory.join(gpa, &[1][]const u8{p}); errdefer gpa.free(owned_dir_path); @@ -80,12 +91,14 @@ pub fn createWithDir( }, .root_src_directory_owned = true, .root_src_path = owned_src_path, + .name = owned_name, }; } else { ptr.* = .{ .root_src_directory = directory, .root_src_directory_owned = false, .root_src_path = owned_src_path, + .name = owned_name, }; } return ptr; @@ -95,6 +108,7 @@ pub fn createWithDir( /// inside its table; the caller is responsible for calling destroy() on them. pub fn destroy(pkg: *Package, gpa: Allocator) void { gpa.free(pkg.root_src_path); + gpa.free(pkg.name); if (pkg.root_src_directory_owned) { // If root_src_directory.path is null then the handle is the cwd() @@ -111,24 +125,18 @@ pub fn destroy(pkg: *Package, gpa: Allocator) void { /// Only frees memory associated with the table. pub fn deinitTable(pkg: *Package, gpa: Allocator) void { - var it = pkg.table.keyIterator(); - while (it.next()) |key| { - gpa.free(key.*); - } - pkg.table.deinit(gpa); } -pub fn add(pkg: *Package, gpa: Allocator, name: []const u8, package: *Package) !void { +pub fn add(pkg: *Package, gpa: Allocator, package: *Package) !void { try pkg.table.ensureUnusedCapacity(gpa, 1); - const name_dupe = try gpa.dupe(u8, name); - pkg.table.putAssumeCapacityNoClobber(name_dupe, package); + pkg.table.putAssumeCapacityNoClobber(package.name, package); } -pub fn addAndAdopt(parent: *Package, gpa: Allocator, name: []const u8, child: *Package) !void { +pub fn addAndAdopt(parent: *Package, gpa: Allocator, child: *Package) !void { assert(child.parent == null); // make up your mind, who is the parent?? child.parent = parent; - return parent.add(gpa, name, child); + return parent.add(gpa, child); } pub const build_zig_basename = "build.zig"; @@ -237,7 +245,7 @@ pub fn fetchAndAddDependencies( sub_prefix, ); - try addAndAdopt(pkg, gpa, fqn, sub_pkg); + try addAndAdopt(pkg, gpa, sub_pkg); try dependencies_source.writer().print(" pub const {s} = @import(\"{}\");\n", .{ std.zig.fmtId(fqn), std.zig.fmtEscapes(fqn), @@ -249,6 +257,7 @@ pub fn fetchAndAddDependencies( pub fn createFilePkg( gpa: Allocator, + name: []const u8, cache_directory: Compilation.Directory, basename: []const u8, contents: []const u8, @@ -269,7 +278,7 @@ pub fn createFilePkg( const o_dir_sub_path = "o" ++ fs.path.sep_str ++ hex_digest; try renameTmpIntoCache(cache_directory.handle, tmp_dir_sub_path, o_dir_sub_path); - return createWithDir(gpa, cache_directory, o_dir_sub_path, basename); + return createWithDir(gpa, name, cache_directory, o_dir_sub_path, basename); } fn fetchAndUnpack( @@ -312,6 +321,9 @@ fn fetchAndUnpack( const owned_src_path = try gpa.dupe(u8, build_zig_basename); errdefer gpa.free(owned_src_path); + const owned_name = try gpa.dupe(u8, fqn); + errdefer gpa.free(owned_name); + const build_root = try global_cache_directory.join(gpa, &.{pkg_dir_sub_path}); errdefer gpa.free(build_root); @@ -326,6 +338,7 @@ fn fetchAndUnpack( }, .root_src_directory_owned = true, .root_src_path = owned_src_path, + .name = owned_name, }; return ptr; @@ -414,7 +427,7 @@ fn fetchAndUnpack( std.zig.fmtId(fqn), std.zig.fmtEscapes(build_root), }); - return createWithDir(gpa, global_cache_directory, pkg_dir_sub_path, build_zig_basename); + return createWithDir(gpa, fqn, global_cache_directory, pkg_dir_sub_path, build_zig_basename); } fn reportError( diff --git a/src/Sema.zig b/src/Sema.zig index 124af6c131..2e57de2406 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5211,6 +5211,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr } const c_import_pkg = Package.create( sema.gpa, + "c_import", // TODO: should we make this unique? null, c_import_res.out_zig_path, ) catch |err| switch (err) { @@ -11663,20 +11664,7 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. }, error.PackageNotFound => { const cur_pkg = block.getFileScope().pkg; - const parent = if (cur_pkg == sema.mod.main_pkg or cur_pkg == sema.mod.root_pkg) - "root" - else if (cur_pkg.parent) |parent| blk: { - var it = parent.table.iterator(); - while (it.next()) |pkg| { - if (pkg.value_ptr.* == cur_pkg) { - break :blk pkg.key_ptr.*; - } - } - unreachable; - } else { - return sema.fail(block, operand_src, "no package named '{s}' available", .{operand}); - }; - return sema.fail(block, operand_src, "no package named '{s}' available within package '{s}'", .{ operand, parent }); + return sema.fail(block, operand_src, "no package named '{s}' available within package '{s}'", .{ operand, cur_pkg.name }); }, else => { // TODO: these errors are file system errors; make sure an update() will diff --git a/src/main.zig b/src/main.zig index 9455bc328a..49bc14353c 100644 --- a/src/main.zig +++ b/src/main.zig @@ -857,6 +857,7 @@ fn buildOutputType( var pkg_tree_root: Package = .{ .root_src_directory = .{ .path = null, .handle = fs.cwd() }, .root_src_path = &[0]u8{}, + .name = &[0]u8{}, }; defer freePkgTree(gpa, &pkg_tree_root, false); var cur_pkg: *Package = &pkg_tree_root; @@ -947,6 +948,7 @@ fn buildOutputType( const new_cur_pkg = Package.create( gpa, + pkg_name, fs.path.dirname(pkg_path), fs.path.basename(pkg_path), ) catch |err| { @@ -958,7 +960,7 @@ fn buildOutputType( } else if (cur_pkg.table.get(pkg_name)) |prev| { fatal("unable to add package '{s}' -> '{s}': already exists as '{s}", .{ pkg_name, pkg_path, prev.root_src_path }); } - try cur_pkg.addAndAdopt(gpa, pkg_name, new_cur_pkg); + try cur_pkg.addAndAdopt(gpa, new_cur_pkg); cur_pkg = new_cur_pkg; } else if (mem.eql(u8, arg, "--pkg-end")) { cur_pkg = cur_pkg.parent orelse @@ -2841,14 +2843,14 @@ fn buildOutputType( if (main_pkg_path) |unresolved_main_pkg_path| { const p = try introspect.resolvePath(arena, unresolved_main_pkg_path); if (p.len == 0) { - break :blk try Package.create(gpa, null, src_path); + break :blk try Package.create(gpa, "root", null, src_path); } else { const rel_src_path = try fs.path.relative(arena, p, src_path); - break :blk try Package.create(gpa, p, rel_src_path); + break :blk try Package.create(gpa, "root", p, rel_src_path); } } else { const root_src_dir_path = fs.path.dirname(src_path); - break :blk Package.create(gpa, root_src_dir_path, fs.path.basename(src_path)) catch |err| { + break :blk Package.create(gpa, "root", root_src_dir_path, fs.path.basename(src_path)) catch |err| { if (root_src_dir_path) |p| { fatal("unable to open '{s}': {s}", .{ p, @errorName(err) }); } else { @@ -4093,6 +4095,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi var main_pkg: Package = .{ .root_src_directory = zig_lib_directory, .root_src_path = "build_runner.zig", + .name = "root", }; if (!build_options.omit_pkg_fetching_code) { @@ -4133,20 +4136,22 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi const deps_pkg = try Package.createFilePkg( gpa, + "@dependencies", local_cache_directory, "dependencies.zig", dependencies_source.items, ); mem.swap(Package.Table, &main_pkg.table, &deps_pkg.table); - try main_pkg.addAndAdopt(gpa, "@dependencies", deps_pkg); + try main_pkg.addAndAdopt(gpa, deps_pkg); } var build_pkg: Package = .{ .root_src_directory = build_directory, .root_src_path = build_zig_basename, + .name = "@build", }; - try main_pkg.addAndAdopt(gpa, "@build", &build_pkg); + try main_pkg.addAndAdopt(gpa, &build_pkg); const comp = Compilation.create(gpa, .{ .zig_lib_directory = zig_lib_directory, @@ -4381,7 +4386,7 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void .root_decl = .none, }; - file.pkg = try Package.create(gpa, null, file.sub_file_path); + file.pkg = try Package.create(gpa, "root", null, file.sub_file_path); defer file.pkg.destroy(gpa); file.zir = try AstGen.generate(gpa, file.tree); @@ -4591,7 +4596,7 @@ fn fmtPathFile( .root_decl = .none, }; - file.pkg = try Package.create(fmt.gpa, null, file.sub_file_path); + file.pkg = try Package.create(fmt.gpa, "root", null, file.sub_file_path); defer file.pkg.destroy(fmt.gpa); if (stat.size > max_src_size) @@ -5303,7 +5308,7 @@ pub fn cmdAstCheck( file.stat.size = source.len; } - file.pkg = try Package.create(gpa, null, file.sub_file_path); + file.pkg = try Package.create(gpa, "root", null, file.sub_file_path); defer file.pkg.destroy(gpa); file.tree = try std.zig.parse(gpa, file.source); @@ -5422,7 +5427,7 @@ pub fn cmdChangelist( .root_decl = .none, }; - file.pkg = try Package.create(gpa, null, file.sub_file_path); + file.pkg = try Package.create(gpa, "root", null, file.sub_file_path); defer file.pkg.destroy(gpa); const source = try arena.allocSentinel(u8, @intCast(usize, stat.size), 0); diff --git a/src/test.zig b/src/test.zig index 08a62b891f..b25a6c1e78 100644 --- a/src/test.zig +++ b/src/test.zig @@ -1497,6 +1497,7 @@ pub const TestContext = struct { var main_pkg: Package = .{ .root_src_directory = .{ .path = tmp_dir_path, .handle = tmp.dir }, .root_src_path = tmp_src_path, + .name = "root", }; defer main_pkg.table.deinit(allocator);