diff --git a/build.zig b/build.zig index b3aeb967d..23a2b3d6f 100644 --- a/build.zig +++ b/build.zig @@ -6,10 +6,10 @@ const zls_version = std.SemanticVersion.parse(@import("build.zig.zon").version) const minimum_build_zig_version = @import("build.zig.zon").minimum_zig_version; /// Specify the minimum Zig version that is usable with ZLS: -/// std: migrate getcwd to Io +/// std.Thread sync primitives roundup /// /// A breaking change to the Zig Build System should be handled by updating ZLS's build runner (see src\build_runner) -const minimum_runtime_zig_version = "0.16.0-dev.2365+377bb8f23"; +const minimum_runtime_zig_version = "0.16.0-dev.2475+e7e700334"; const release_targets = [_]std.Target.Query{ .{ .cpu_arch = .aarch64, .os_tag = .linux }, diff --git a/build.zig.zon b/build.zig.zon index 0e253fc65..b4d6f4135 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -10,7 +10,7 @@ // nix flake update --commit-lock-file // ``` // If you do not use Nix, a ZLS maintainer can take care of this. - .minimum_zig_version = "0.16.0-dev.2471+e9eadee00", + .minimum_zig_version = "0.16.0-dev.2510+bcb5218a2", // If you do not use Nix, a ZLS maintainer can take care of this. // Whenever the dependencies are updated, run the following command: // ```bash @@ -23,12 +23,12 @@ .hash = "known_folders-0.0.0-Fy-PJqHJAAB43zDJmOdlr3nViu69IFI9pNFt7hkHjKk4", }, .diffz = .{ - .url = "https://github.com/ziglibs/diffz/archive/669e6ed7470100bfd9d2aa9f6f96b93c45996179.tar.gz", - .hash = "diffz-0.0.1-G2tlISLPAQDzXkUIRWWUfdgIsIb1dAyVwRPXMt5kRpui", + .url = "https://github.com/ziglibs/diffz/archive/aa11caef328a3f20f2493f8fd676a1dfa7819246.tar.gz", + .hash = "diffz-0.0.1-G2tlIYrNAQAQx3cuIp7EVs0xvxbv9DCPf4YuHmvubsrZ", }, .lsp_kit = .{ - .url = "https://github.com/zigtools/lsp-kit/archive/922e9c2fc00741b167a19277d737b8eb890f0253.tar.gz", - .hash = "lsp_kit-0.1.0-bi_PL94yDABlKrIbUTtVALYWLeFt6XAzHS6R12Tp83_Z", + .url = "https://github.com/zigtools/lsp-kit/archive/7b03f0b6801babffe76608cf3db59793902a21d6.tar.gz", + .hash = "lsp_kit-0.1.0-bi_PLw8zDABvCWe2rD4Aqb9gx0sRXBKO0a7M0vg3AbR3", }, .tracy = .{ .url = "https://github.com/wolfpld/tracy/archive/refs/tags/v0.13.1.tar.gz", diff --git a/deps.nix b/deps.nix index c95dcc83d..6a9afa6cf 100644 --- a/deps.nix +++ b/deps.nix @@ -4,10 +4,10 @@ linkFarm "zig-packages" [ { - name = "diffz-0.0.1-G2tlISLPAQDzXkUIRWWUfdgIsIb1dAyVwRPXMt5kRpui"; + name = "diffz-0.0.1-G2tlIYrNAQAQx3cuIp7EVs0xvxbv9DCPf4YuHmvubsrZ"; path = fetchzip { - url = "https://github.com/ziglibs/diffz/archive/669e6ed7470100bfd9d2aa9f6f96b93c45996179.tar.gz"; - hash = "sha256-tEMWxY7jhp5OGJHejfGCkXuMtpbnp6hFetms8Zk3PYs="; + url = "https://github.com/ziglibs/diffz/archive/aa11caef328a3f20f2493f8fd676a1dfa7819246.tar.gz"; + hash = "sha256-bdL+xLnYVzYS6T3zsw7xfLKTUCUFI0pIpQaOxV6oTis="; }; } { @@ -18,10 +18,10 @@ linkFarm "zig-packages" [ }; } { - name = "lsp_kit-0.1.0-bi_PL94yDABlKrIbUTtVALYWLeFt6XAzHS6R12Tp83_Z"; + name = "lsp_kit-0.1.0-bi_PLw8zDABvCWe2rD4Aqb9gx0sRXBKO0a7M0vg3AbR3"; path = fetchzip { - url = "https://github.com/zigtools/lsp-kit/archive/922e9c2fc00741b167a19277d737b8eb890f0253.tar.gz"; - hash = "sha256-bDPbYY59HvgHtaHPfTTCqjMEx8tDJoyyld9lkONUHVY="; + url = "https://github.com/zigtools/lsp-kit/archive/7b03f0b6801babffe76608cf3db59793902a21d6.tar.gz"; + hash = "sha256-CjWrp8fERKS5VldRvYtDFk1g4heIkX4YrpLw/eC12Q4="; }; } ] diff --git a/src/Server.zig b/src/Server.zig index 59b6fe439..3d4833da2 100644 --- a/src/Server.zig +++ b/src/Server.zig @@ -1443,7 +1443,7 @@ fn formattingHandler(server: *Server, arena: std.mem.Allocator, request: types.d if (std.mem.eql(u8, handle.tree.source, formatted)) return null; - const text_edits = try diff.edits(arena, handle.tree.source, formatted, server.offset_encoding); + const text_edits = try diff.edits(server.io, arena, handle.tree.source, formatted, server.offset_encoding); return text_edits.items; } @@ -1690,7 +1690,7 @@ pub fn create(options: CreateOptions) std.mem.Allocator.Error!*Server { }; server.document_store.config = createDocumentStoreConfig(server.config_manager); - server.ip = try InternPool.init(allocator); + server.ip = try InternPool.init(io, allocator); errdefer server.ip.deinit(allocator); if (options.transport) |transport| { diff --git a/src/analyser/InternPool.zig b/src/analyser/InternPool.zig index fb692a2b0..78f8e7b94 100644 --- a/src/analyser/InternPool.zig +++ b/src/analyser/InternPool.zig @@ -1,11 +1,14 @@ //! Based on src/InternPool.zig from the zig codebase //! https://github.com/ziglang/zig/blob/master/src/InternPool.zig +io: std.Io, +gpa: Allocator, + map: std.AutoArrayHashMapUnmanaged(void, void), items: std.MultiArrayList(Item), extra: std.ArrayList(u32), string_pool: StringPool, -lock: RwLock, +lock: std.Io.RwLock, limbs: std.ArrayList(usize), @@ -27,11 +30,6 @@ pub const String = StringPool.String; const ErrorMsg = @import("error_msg.zig").ErrorMsg; const SegmentedList = @import("segmented_list.zig").SegmentedList; -pub const RwLock = if (builtin.single_threaded) - std.Thread.RwLock.SingleThreadedRwLock -else - std.Thread.RwLock.DefaultRwLock; - pub const Key = union(enum) { simple_type: SimpleType, simple_value: SimpleValue, @@ -439,8 +437,8 @@ pub const Key = union(enum) { if (a_info.names.len != b_info.names.len) return false; - if (should_lock) ip.lock.lockShared(); - defer if (should_lock) ip.lock.unlockShared(); + if (should_lock) ip.lock.lockSharedUncancelable(ip.io); + defer if (should_lock) ip.lock.unlockShared(ip.io); for ( a_info.names.getUnprotectedSlice(ip), @@ -466,8 +464,8 @@ pub const Key = union(enum) { if (a_info.args.len != b_info.args.len) return false; - if (should_lock) ip.lock.lockShared(); - defer if (should_lock) ip.lock.unlockShared(); + if (should_lock) ip.lock.lockSharedUncancelable(ip.io); + defer if (should_lock) ip.lock.unlockShared(ip.io); for ( a_info.args.getUnprotectedSlice(ip), @@ -485,8 +483,8 @@ pub const Key = union(enum) { if (a_info.types.len != b_info.types.len) return false; if (a_info.values.len != b_info.values.len) return false; - if (should_lock) ip.lock.lockShared(); - defer if (should_lock) ip.lock.unlockShared(); + if (should_lock) ip.lock.lockSharedUncancelable(ip.io); + defer if (should_lock) ip.lock.unlockShared(ip.io); for ( a_info.types.getUnprotectedSlice(ip), @@ -504,8 +502,8 @@ pub const Key = union(enum) { if (a_info.ty != b_info.ty) return false; - if (should_lock) ip.lock.lockShared(); - defer if (should_lock) ip.lock.unlockShared(); + if (should_lock) ip.lock.lockSharedUncancelable(ip.io); + defer if (should_lock) ip.lock.unlockShared(ip.io); if (!a_info.getConst(ip).eql(b_info.getConst(ip))) return false; @@ -518,8 +516,8 @@ pub const Key = union(enum) { if (a_info.values.len != b_info.values.len) return false; - if (should_lock) ip.lock.lockShared(); - defer if (should_lock) ip.lock.unlockShared(); + if (should_lock) ip.lock.lockSharedUncancelable(ip.io); + defer if (should_lock) ip.lock.unlockShared(ip.io); for ( a_info.values.getUnprotectedSlice(ip), @@ -664,23 +662,23 @@ pub const Index = enum(u32) { /// prefer using `dupe` when iterating over all elements. pub fn at(slice: Slice, index: u32, ip: *InternPool) Index { assert(index < slice.len); - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); return @enumFromInt(ip.extra.items[slice.start + index]); } - pub fn dupe(slice: Slice, gpa: Allocator, ip: *InternPool) error{OutOfMemory}![]Index { + pub fn dupe(slice: Slice, allocator: Allocator, ip: *InternPool) error{OutOfMemory}![]Index { if (slice.len == 0) return &.{}; - ip.lock.lockShared(); - defer ip.lock.unlockShared(); - return try gpa.dupe(Index, slice.getUnprotectedSlice(ip)); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); + return try allocator.dupe(Index, slice.getUnprotectedSlice(ip)); } pub fn hashWithHasher(slice: Slice, hasher: anytype, ip: *InternPool) void { std.hash.autoHash(hasher, slice.len); if (slice.len == 0) return; - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); hasher.update(std.mem.sliceAsBytes(slice.getUnprotectedSlice(ip))); } @@ -722,23 +720,23 @@ pub const StringSlice = struct { /// prefer using `dupe` when iterating over all elements. pub fn at(slice: StringSlice, index: u32, ip: *InternPool) String { assert(index < slice.len); - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); return @enumFromInt(ip.extra.items[slice.start + index]); } - pub fn dupe(slice: StringSlice, gpa: Allocator, ip: *InternPool) error{OutOfMemory}![]String { + pub fn dupe(slice: StringSlice, allocator: Allocator, ip: *InternPool) error{OutOfMemory}![]String { if (slice.len == 0) return &.{}; - ip.lock.lockShared(); - defer ip.lock.unlockShared(); - return try gpa.dupe(String, slice.getUnprotectedSlice(ip)); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); + return try allocator.dupe(String, slice.getUnprotectedSlice(ip)); } pub fn hashWithHasher(slice: StringSlice, hasher: anytype, ip: *InternPool) void { std.hash.autoHash(hasher, slice.len); if (slice.len == 0) return; - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); hasher.update(std.mem.sliceAsBytes(slice.getUnprotectedSlice(ip))); } @@ -760,8 +758,8 @@ pub const LimbSlice = struct { pub fn hashWithHasher(slice: LimbSlice, hasher: anytype, ip: *InternPool) void { std.hash.autoHash(hasher, slice.len); if (slice.len == 0) return; - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); hasher.update(std.mem.sliceAsBytes(slice.getUnprotectedSlice(ip))); } @@ -1034,13 +1032,15 @@ pub const Union = struct { pub const Index = enum(u32) { _ }; }; -pub fn init(gpa: Allocator) Allocator.Error!InternPool { +pub fn init(io: std.Io, gpa: Allocator) Allocator.Error!InternPool { var ip: InternPool = .{ + .io = io, + .gpa = gpa, .map = .empty, .items = .empty, .extra = .empty, .string_pool = .empty, - .lock = .{}, + .lock = .init, .limbs = .empty, .decls = .{}, .structs = .{}, @@ -1153,15 +1153,7 @@ pub fn init(gpa: Allocator) Allocator.Error!InternPool { for (items, 0..) |item, i| { assert(@intFromEnum(item.index) == i); - if (builtin.is_test or builtin.mode == .Debug) { - var failing_allocator: std.testing.FailingAllocator = .init(undefined, .{ - .fail_index = 0, - .resize_fail_index = 0, - }); - assert(item.index == ip.get(failing_allocator.allocator(), item.key) catch unreachable); - } else { - assert(item.index == ip.get(undefined, item.key) catch unreachable); - } + assert(item.index == ip.get(item.key) catch unreachable); } return ip; @@ -1196,8 +1188,8 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { pub fn indexToKey(ip: *InternPool, index: Index) Key { assert(index != .none); - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); return ip.indexToKeyNoLock(index); } @@ -1259,24 +1251,24 @@ fn indexToKeyNoLock(ip: *const InternPool, index: Index) Key { }; } -pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { +pub fn get(ip: *InternPool, key: Key) Allocator.Error!Index { const adapter: KeyAdapter = .{ .ip = ip, .precomputed_hash = key.hash32(ip), }; not_found: { - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); const index = ip.map.getIndexAdapted(key, adapter) orelse break :not_found; return @enumFromInt(index); } - ip.lock.lock(); - defer ip.lock.unlock(); + ip.lock.lockUncancelable(ip.io); + defer ip.lock.unlock(ip.io); - const gop = try ip.map.getOrPutAdapted(gpa, key, adapter); + const gop = try ip.map.getOrPutAdapted(ip.gpa, key, adapter); if (gop.found_existing) return @enumFromInt(gop.index); const item: Item = switch (key) { @@ -1294,11 +1286,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { }, .pointer_type => |pointer_ty| .{ .tag = .type_pointer, - .data = try ip.addExtra(gpa, Key.Pointer, pointer_ty), + .data = try ip.addExtra(Key.Pointer, pointer_ty), }, .array_type => |array_ty| .{ .tag = .type_array, - .data = try ip.addExtra(gpa, Key.Array, array_ty), + .data = try ip.addExtra(Key.Array, array_ty), }, .struct_type => |struct_index| .{ .tag = .type_struct, @@ -1310,11 +1302,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { }, .error_union_type => |error_union_ty| .{ .tag = .type_error_union, - .data = try ip.addExtra(gpa, Key.ErrorUnion, error_union_ty), + .data = try ip.addExtra(Key.ErrorUnion, error_union_ty), }, .error_set_type => |error_set_ty| .{ .tag = .type_error_set, - .data = try ip.addExtra(gpa, Key.ErrorSet, error_set_ty), + .data = try ip.addExtra(Key.ErrorSet, error_set_ty), }, .enum_type => |enum_index| .{ .tag = .type_enum, @@ -1322,7 +1314,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { }, .function_type => |function_ty| .{ .tag = .type_function, - .data = try ip.addExtra(gpa, Key.Function, function_ty), + .data = try ip.addExtra(Key.Function, function_ty), }, .union_type => |union_index| .{ .tag = .type_union, @@ -1330,11 +1322,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { }, .tuple_type => |tuple_ty| .{ .tag = .type_tuple, - .data = try ip.addExtra(gpa, Key.Tuple, tuple_ty), + .data = try ip.addExtra(Key.Tuple, tuple_ty), }, .vector_type => |vector_ty| .{ .tag = .type_vector, - .data = try ip.addExtra(gpa, Key.Vector, vector_ty), + .data = try ip.addExtra(Key.Vector, vector_ty), }, .anyframe_type => |anyframe_ty| .{ .tag = .type_anyframe, @@ -1343,18 +1335,18 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { .int_u64_value => |int_val| .{ .tag = .int_u64, - .data = try ip.addExtra(gpa, Key.U64Value, int_val), + .data = try ip.addExtra(Key.U64Value, int_val), }, .int_i64_value => |int_val| .{ .tag = .int_i64, - .data = try ip.addExtra(gpa, Key.I64Value, int_val), + .data = try ip.addExtra(Key.I64Value, int_val), }, .int_big_value => |big_int_val| .{ .tag = if (big_int_val.isPositive()) .int_big_positive else .int_big_negative, - .data = try ip.addExtra(gpa, Key.BigIntInternal, .{ + .data = try ip.addExtra(Key.BigIntInternal, .{ .ty = big_int_val.ty, .limbs = switch (big_int_val.storage) { - .external => |int| try ip.getLimbSlice(gpa, int.limbs), + .external => |int| try ip.getLimbSlice(int.limbs), .internal => |int| int.limbs, }, }), @@ -1369,40 +1361,40 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { }, .float_64_value => |float_val| .{ .tag = .float_f64, - .data = try ip.addExtra(gpa, Key.F64Value, Key.F64Value.pack(float_val)), + .data = try ip.addExtra(Key.F64Value, Key.F64Value.pack(float_val)), }, .float_80_value => |float_val| .{ .tag = .float_f80, - .data = try ip.addExtra(gpa, Key.F80Value, Key.F80Value.pack(float_val)), + .data = try ip.addExtra(Key.F80Value, Key.F80Value.pack(float_val)), }, .float_128_value => |float_val| .{ .tag = .float_f128, - .data = try ip.addExtra(gpa, Key.F128Value, Key.F128Value.pack(float_val)), + .data = try ip.addExtra(Key.F128Value, Key.F128Value.pack(float_val)), }, .float_comptime_value => |float_val| .{ .tag = .float_comptime, - .data = try ip.addExtra(gpa, Key.F128Value, Key.F128Value.pack(float_val)), + .data = try ip.addExtra(Key.F128Value, Key.F128Value.pack(float_val)), }, .optional_value => |optional_val| .{ .tag = .optional_value, - .data = try ip.addExtra(gpa, Key.OptionalValue, optional_val), + .data = try ip.addExtra(Key.OptionalValue, optional_val), }, .slice => |slice_val| .{ .tag = .slice_value, - .data = try ip.addExtra(gpa, Key.Slice, slice_val), + .data = try ip.addExtra(Key.Slice, slice_val), }, .aggregate => |aggregate_val| .{ .tag = .aggregate_value, - .data = try ip.addExtra(gpa, Key.Aggregate, aggregate_val), + .data = try ip.addExtra(Key.Aggregate, aggregate_val), }, .union_value => |union_val| .{ .tag = .union_value, - .data = try ip.addExtra(gpa, Key.UnionValue, union_val), + .data = try ip.addExtra(Key.UnionValue, union_val), }, .error_value => |error_val| .{ .tag = .error_value, - .data = try ip.addExtra(gpa, Key.ErrorValue, error_val), + .data = try ip.addExtra(Key.ErrorValue, error_val), }, .null_value => |null_val| .{ .tag = .null_value, @@ -1421,7 +1413,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { }, }; - try ip.items.append(gpa, item); + try ip.items.append(ip.gpa, item); return @enumFromInt(ip.items.len - 1); } @@ -1430,20 +1422,20 @@ pub fn contains(ip: *InternPool, key: Key) ?Index { .ip = ip, .precomputed_hash = key.hash32(ip), }; - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); const index = ip.map.getIndexAdapted(key, adapter) orelse return null; return @enumFromInt(index); } -pub fn getIndexSlice(ip: *InternPool, gpa: Allocator, data: []const Index) error{OutOfMemory}!Index.Slice { +pub fn getIndexSlice(ip: *InternPool, data: []const Index) error{OutOfMemory}!Index.Slice { if (data.len == 0) return Index.Slice.empty; - ip.lock.lock(); - defer ip.lock.unlock(); + ip.lock.lockUncancelable(ip.io); + defer ip.lock.unlock(ip.io); const start: u32 = @intCast(ip.extra.items.len); - try ip.extra.appendSlice(gpa, @ptrCast(data)); + try ip.extra.appendSlice(ip.gpa, @ptrCast(data)); return .{ .start = start, @@ -1451,14 +1443,14 @@ pub fn getIndexSlice(ip: *InternPool, gpa: Allocator, data: []const Index) error }; } -pub fn getStringSlice(ip: *InternPool, gpa: Allocator, data: []const String) error{OutOfMemory}!StringSlice { +pub fn getStringSlice(ip: *InternPool, data: []const String) error{OutOfMemory}!StringSlice { if (data.len == 0) return StringSlice.empty; - ip.lock.lock(); - defer ip.lock.unlock(); + ip.lock.lockUncancelable(ip.io); + defer ip.lock.unlock(ip.io); const start: u32 = @intCast(ip.extra.items.len); - try ip.extra.appendSlice(gpa, @ptrCast(data)); + try ip.extra.appendSlice(ip.gpa, @ptrCast(data)); return .{ .start = start, @@ -1466,11 +1458,11 @@ pub fn getStringSlice(ip: *InternPool, gpa: Allocator, data: []const String) err }; } -fn getLimbSlice(ip: *InternPool, gpa: Allocator, data: []const std.math.big.Limb) error{OutOfMemory}!LimbSlice { +fn getLimbSlice(ip: *InternPool, data: []const std.math.big.Limb) error{OutOfMemory}!LimbSlice { if (data.len == 0) return LimbSlice.empty; const start: u32 = @intCast(ip.limbs.items.len); - try ip.limbs.appendSlice(gpa, data); + try ip.limbs.appendSlice(ip.gpa, data); return .{ .start = start, @@ -1479,72 +1471,72 @@ fn getLimbSlice(ip: *InternPool, gpa: Allocator, data: []const std.math.big.Limb } pub fn getDecl(ip: *InternPool, index: InternPool.Decl.Index) *const InternPool.Decl { - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); return ip.decls.at(@intFromEnum(index)); } pub fn getDeclMut(ip: *InternPool, index: InternPool.Decl.Index) *InternPool.Decl { - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); return ip.decls.at(@intFromEnum(index)); } pub fn getStruct(ip: *InternPool, index: Struct.Index) *const Struct { - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); return ip.structs.at(@intFromEnum(index)); } pub fn getStructMut(ip: *InternPool, index: Struct.Index) *Struct { - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); return ip.structs.at(@intFromEnum(index)); } pub fn getEnum(ip: *InternPool, index: Enum.Index) *const Enum { - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); return ip.enums.at(@intFromEnum(index)); } pub fn getEnumMut(ip: *InternPool, index: Enum.Index) *Enum { - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); return ip.enums.at(@intFromEnum(index)); } pub fn getUnion(ip: *InternPool, index: Union.Index) *const Union { - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); return ip.unions.at(@intFromEnum(index)); } pub fn getUnionMut(ip: *InternPool, index: Union.Index) *Union { - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); return ip.unions.at(@intFromEnum(index)); } -pub fn createDecl(ip: *InternPool, gpa: Allocator, decl: Decl) Allocator.Error!Decl.Index { - ip.lock.lock(); - defer ip.lock.unlock(); - try ip.decls.append(gpa, decl); +pub fn createDecl(ip: *InternPool, decl: Decl) Allocator.Error!Decl.Index { + ip.lock.lockUncancelable(ip.io); + defer ip.lock.unlock(ip.io); + try ip.decls.append(ip.gpa, decl); return @enumFromInt(ip.decls.count() - 1); } -pub fn createStruct(ip: *InternPool, gpa: Allocator, struct_info: Struct) Allocator.Error!Struct.Index { - ip.lock.lock(); - defer ip.lock.unlock(); - try ip.structs.append(gpa, struct_info); +pub fn createStruct(ip: *InternPool, struct_info: Struct) Allocator.Error!Struct.Index { + ip.lock.lockUncancelable(ip.io); + defer ip.lock.unlock(ip.io); + try ip.structs.append(ip.gpa, struct_info); return @enumFromInt(ip.structs.count() - 1); } -pub fn createEnum(ip: *InternPool, gpa: Allocator, enum_info: Enum) Allocator.Error!Enum.Index { - ip.lock.lock(); - defer ip.lock.unlock(); - try ip.enums.append(gpa, enum_info); +pub fn createEnum(ip: *InternPool, enum_info: Enum) Allocator.Error!Enum.Index { + ip.lock.lockUncancelable(ip.io); + defer ip.lock.unlock(ip.io); + try ip.enums.append(ip.gpa, enum_info); return @enumFromInt(ip.enums.count() - 1); } -pub fn createUnion(ip: *InternPool, gpa: Allocator, union_info: Union) Allocator.Error!Union.Index { - ip.lock.lock(); - defer ip.lock.unlock(); - try ip.unions.append(gpa, union_info); +pub fn createUnion(ip: *InternPool, union_info: Union) Allocator.Error!Union.Index { + ip.lock.lockUncancelable(ip.io); + defer ip.lock.unlock(ip.io); + try ip.unions.append(ip.gpa, union_info); return @enumFromInt(ip.unions.count() - 1); } -fn addExtra(ip: *InternPool, gpa: Allocator, comptime T: type, extra: T) Allocator.Error!u32 { +fn addExtra(ip: *InternPool, comptime T: type, extra: T) Allocator.Error!u32 { comptime if (@sizeOf(T) <= 4) { @compileError(@typeName(T) ++ " fits into a u32! Consider directly storing this extra in Item's data field"); }; @@ -1553,7 +1545,7 @@ fn addExtra(ip: *InternPool, gpa: Allocator, comptime T: type, extra: T) Allocat const size = @divExact(@sizeOf(T), 4); - try ip.extra.ensureUnusedCapacity(gpa, size); + try ip.extra.ensureUnusedCapacity(ip.gpa, size); inline for (std.meta.fields(T)) |field| { const item = @field(extra, field.name); switch (field.type) { @@ -1662,7 +1654,6 @@ const KeyAdapter = struct { /// @as(dest_ty, inst); pub fn coerce( ip: *InternPool, - gpa: Allocator, arena: Allocator, dest_ty: Index, inst: Index, @@ -1681,34 +1672,34 @@ pub fn coerce( const inst_ty = ip.typeOf(inst); if (inst_ty == dest_ty) return inst; - if (inst_ty == .undefined_type) return try ip.getUndefined(gpa, dest_ty); - if (inst_ty == .unknown_type) return try ip.getUnknown(gpa, dest_ty); + if (inst_ty == .undefined_type) return try ip.getUndefined(dest_ty); + if (inst_ty == .unknown_type) return try ip.getUnknown(dest_ty); - const dest_tag = ip.zigTypeTag(dest_ty) orelse return try ip.getUnknown(gpa, dest_ty); - const inst_tag = ip.zigTypeTag(inst_ty) orelse return try ip.getUnknown(gpa, dest_ty); + const dest_tag = ip.zigTypeTag(dest_ty) orelse return try ip.getUnknown(dest_ty); + const inst_tag = ip.zigTypeTag(inst_ty) orelse return try ip.getUnknown(dest_ty); - var in_memory_result = try ip.coerceInMemoryAllowed(gpa, arena, dest_ty, inst_ty, false, builtin.target); - if (in_memory_result == .ok) return try ip.getUnknown(gpa, dest_ty); + var in_memory_result = try ip.coerceInMemoryAllowed(arena, dest_ty, inst_ty, false, builtin.target); + if (in_memory_result == .ok) return try ip.getUnknown(dest_ty); switch (dest_tag) { .optional => optional: { // null to ?T if (inst_ty == .null_type) { - return try ip.getNull(gpa, dest_ty); + return try ip.getNull(dest_ty); } const child_type = ip.indexToKey(dest_ty).optional_type.payload_type; // TODO cast from ?*T and ?[*]T to ?*anyopaque // but don't do it if the source type is a double pointer if (child_type == .anyopaque_type) { - return try ip.getUnknown(gpa, dest_ty); // TODO + return try ip.getUnknown(dest_ty); // TODO } // T to ?T - const intermediate = try ip.coerce(gpa, arena, child_type, inst, target, err_msg); + const intermediate = try ip.coerce(arena, child_type, inst, target, err_msg); if (intermediate == .none) break :optional; - return try ip.get(gpa, .{ .optional_value = .{ + return try ip.get(.{ .optional_value = .{ .ty = dest_ty, .val = intermediate, } }); @@ -1718,7 +1709,7 @@ pub fn coerce( // Function body to function pointer. if (inst_tag == .@"fn") { - return try ip.getUnknown(gpa, dest_ty); + return try ip.getUnknown(dest_ty); } const inst_ty_key = ip.indexToKey(inst_ty); @@ -1730,11 +1721,11 @@ pub fn coerce( const array_ty = ip.indexToKey(dest_info.elem_type); if (array_ty != .array_type) break :single_item; const array_elem_ty = array_ty.array_type.child; - if (try ip.coerceInMemoryAllowed(gpa, arena, array_elem_ty, ptr_elem_ty, dest_info.flags.is_const, target) != .ok) { + if (try ip.coerceInMemoryAllowed(arena, array_elem_ty, ptr_elem_ty, dest_info.flags.is_const, target) != .ok) { break :single_item; } - return try ip.getUnknown(gpa, dest_ty); - // return ip.coerceCompatiblePtrs(gpa, arena, dest_ty, inst); + return try ip.getUnknown(dest_ty); + // return ip.coerceCompatiblePtrs(arena, dest_ty, inst); } // Coercions where the source is a single pointer to an array. @@ -1746,7 +1737,7 @@ pub fn coerce( if (array_ty != .array_type) break :src_array_ptr; const array_elem_type = array_ty.array_type.child; - const elem_res = try ip.coerceInMemoryAllowed(gpa, arena, dest_info.elem_type, array_elem_type, dest_info.flags.is_const, target); + const elem_res = try ip.coerceInMemoryAllowed(arena, dest_info.elem_type, array_elem_type, dest_info.flags.is_const, target); if (elem_res != .ok) { in_memory_result = .{ .ptr_child = .{ .child = try elem_res.dupe(arena), @@ -1767,14 +1758,14 @@ pub fn coerce( break :src_array_ptr; } - return try ip.getUnknown(gpa, dest_ty); + return try ip.getUnknown(dest_ty); // switch (dest_info.flags.size) { // // *[N]T to []T - // .Slice => return ip.coerceArrayPtrToSlice(gpa, arena, dest_ty, inst), + // .Slice => return ip.coerceArrayPtrToSlice(arena, dest_ty, inst), // // *[N]T to [*c]T - // .C => return ip.coerceCompatiblePtrs(gpa, arena, dest_ty, inst), + // .C => return ip.coerceCompatiblePtrs(arena, dest_ty, inst), // // *[N]T to [*]T - // .Many => return ip.coerceCompatiblePtrs(gpa, arena, dest_ty, inst), + // .Many => return ip.coerceCompatiblePtrs(arena, dest_ty, inst), // .One => {}, // } } @@ -1784,11 +1775,11 @@ pub fn coerce( // TODO if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :src_c_ptr; const src_elem_ty = ip.indexToKey(inst_ty).pointer_type.elem_type; - if (try ip.coerceInMemoryAllowed(gpa, arena, dest_info.elem_type, src_elem_ty, dest_info.flags.is_const, target) != .ok) { + if (try ip.coerceInMemoryAllowed(arena, dest_info.elem_type, src_elem_ty, dest_info.flags.is_const, target) != .ok) { break :src_c_ptr; } - return try ip.getUnknown(gpa, dest_ty); - // return ip.coerceCompatiblePtrs(gpa, arena, dest_ty, inst); + return try ip.getUnknown(dest_ty); + // return ip.coerceCompatiblePtrs(arena, dest_ty, inst); } // cast from *T and [*]T to *anyopaque @@ -1804,17 +1795,17 @@ pub fn coerce( } }; break :pointer; } - return try ip.getUnknown(gpa, dest_ty); - // return ip.coerceCompatiblePtrs(gpa, arena, dest_ty, inst); + return try ip.getUnknown(dest_ty); + // return ip.coerceCompatiblePtrs(arena, dest_ty, inst); } - return try ip.getUnknown(gpa, dest_ty); + return try ip.getUnknown(dest_ty); }, .int, .comptime_int => switch (inst_tag) { - .float, .comptime_float => return try ip.getUnknown(gpa, dest_ty), + .float, .comptime_float => return try ip.getUnknown(dest_ty), .int, .comptime_int => { if (try ip.intFitsInType(inst, dest_ty, target)) { - return try ip.coerceInt(gpa, dest_ty, inst); + return try ip.coerceInt(dest_ty, inst); } else { err_msg.* = .{ .integer_out_of_range = .{ .dest_ty = dest_ty, @@ -1825,12 +1816,12 @@ pub fn coerce( }, else => {}, }, - .float, .comptime_float => return try ip.getUnknown(gpa, dest_ty), - .@"enum" => return try ip.getUnknown(gpa, dest_ty), - .error_union => return try ip.getUnknown(gpa, dest_ty), - .@"union" => return try ip.getUnknown(gpa, dest_ty), + .float, .comptime_float => return try ip.getUnknown(dest_ty), + .@"enum" => return try ip.getUnknown(dest_ty), + .error_union => return try ip.getUnknown(dest_ty), + .@"union" => return try ip.getUnknown(dest_ty), .array => switch (inst_tag) { - .vector => return try ip.getUnknown(gpa, dest_ty), + .vector => return try ip.getUnknown(dest_ty), .@"struct" => { if (inst_ty == Index.empty_struct_type) { const len = ip.indexToKey(dest_ty).array_type.len; @@ -1842,14 +1833,14 @@ pub fn coerce( return .none; } // TODO - return try ip.getUnknown(gpa, dest_ty); + return try ip.getUnknown(dest_ty); } - return try ip.getUnknown(gpa, dest_ty); + return try ip.getUnknown(dest_ty); }, else => {}, }, - .vector => return try ip.getUnknown(gpa, dest_ty), - .@"struct" => return try ip.getUnknown(gpa, dest_ty), + .vector => return try ip.getUnknown(dest_ty), + .@"struct" => return try ip.getUnknown(dest_ty), else => {}, } @@ -1879,14 +1870,13 @@ fn intFitsInType( fn coerceInt( ip: *InternPool, - gpa: Allocator, dest_ty: Index, val: Index, ) Allocator.Error!Index { switch (ip.indexToKey(val)) { - .int_i64_value => |int| return try ip.get(gpa, .{ .int_i64_value = .{ .int = int.int, .ty = dest_ty } }), - .int_u64_value => |int| return try ip.get(gpa, .{ .int_u64_value = .{ .int = int.int, .ty = dest_ty } }), - .int_big_value => |int| return try ip.get(gpa, .{ + .int_i64_value => |int| return try ip.get(.{ .int_i64_value = .{ .int = int.int, .ty = dest_ty } }), + .int_u64_value => |int| return try ip.get(.{ .int_u64_value = .{ .int = int.int, .ty = dest_ty } }), + .int_big_value => |int| return try ip.get(.{ .int_big_value = .{ .ty = dest_ty, .storage = .{ @@ -1897,13 +1887,13 @@ fn coerceInt( }, }, }), - .undefined_value => |info| return try ip.getUndefined(gpa, info.ty), - .unknown_value => |info| return try ip.getUnknown(gpa, info.ty), + .undefined_value => |info| return try ip.getUndefined(info.ty), + .unknown_value => |info| return try ip.getUnknown(info.ty), else => unreachable, } } -pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, target: std.Target) Allocator.Error!Index { +pub fn resolvePeerTypes(ip: *InternPool, types: []const Index, target: std.Target) Allocator.Error!Index { if (builtin.mode == .Debug) { for (types) |ty| { assert(ip.isType(ty)); @@ -1916,7 +1906,7 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t else => {}, } - var arena_allocator: std.heap.ArenaAllocator = .init(gpa); + var arena_allocator: std.heap.ArenaAllocator = .init(ip.gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); @@ -1937,10 +1927,10 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t // If the candidate can coerce into our chosen type, we're done. // If the chosen type can coerce into the candidate, use that. - if ((try ip.coerceInMemoryAllowed(gpa, arena, chosen, candidate, true, target)) == .ok) { + if ((try ip.coerceInMemoryAllowed(arena, chosen, candidate, true, target)) == .ok) { continue; } - if ((try ip.coerceInMemoryAllowed(gpa, arena, candidate, chosen, true, target)) == .ok) { + if ((try ip.coerceInMemoryAllowed(arena, candidate, chosen, true, target)) == .ok) { chosen = candidate; continue; } @@ -2148,13 +2138,13 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t const chosen_elem_ty = chosen_elem_info.array_type.child; const cand_elem_ty = candidate_elem_info.array_type.child; - const chosen_ok = .ok == try ip.coerceInMemoryAllowed(gpa, arena, chosen_elem_ty, cand_elem_ty, chosen_info.flags.is_const, target); + const chosen_ok = .ok == try ip.coerceInMemoryAllowed(arena, chosen_elem_ty, cand_elem_ty, chosen_info.flags.is_const, target); if (chosen_ok) { convert_to_slice = true; continue; } - const cand_ok = .ok == try ip.coerceInMemoryAllowed(gpa, arena, cand_elem_ty, chosen_elem_ty, candidate_info.flags.is_const, target); + const cand_ok = .ok == try ip.coerceInMemoryAllowed(arena, cand_elem_ty, chosen_elem_ty, candidate_info.flags.is_const, target); if (cand_ok) { convert_to_slice = true; chosen = candidate; @@ -2173,8 +2163,8 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t // the one we will keep. If they're both OK then we keep the // C pointer since it matches both single and many pointers. if (candidate_info.flags.size == .c or chosen_info.flags.size == .c) { - const cand_ok = .ok == try ip.coerceInMemoryAllowed(gpa, arena, candidate_info.elem_type, chosen_info.elem_type, candidate_info.flags.is_const, target); - const chosen_ok = .ok == try ip.coerceInMemoryAllowed(gpa, arena, chosen_info.elem_type, candidate_info.elem_type, chosen_info.flags.is_const, target); + const cand_ok = .ok == try ip.coerceInMemoryAllowed(arena, candidate_info.elem_type, chosen_info.elem_type, candidate_info.flags.is_const, target); + const chosen_ok = .ok == try ip.coerceInMemoryAllowed(arena, chosen_info.elem_type, candidate_info.elem_type, chosen_info.flags.is_const, target); if (cand_ok) { if (!chosen_ok or chosen_info.flags.size != .c) { @@ -2232,7 +2222,7 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t .function_type => { if (candidate_info.flags.is_const and ip.zigTypeTag(candidate_info.elem_type) == .@"fn" and - .ok == try ip.coerceInMemoryAllowedFns(gpa, arena, chosen, candidate_info.elem_type, target)) + .ok == try ip.coerceInMemoryAllowedFns(arena, chosen, candidate_info.elem_type, target)) { chosen = candidate; continue; @@ -2245,7 +2235,7 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t else => {}, }, .optional_type => |candidate_info| { - if ((try ip.coerceInMemoryAllowed(gpa, arena, chosen, candidate_info.payload_type, true, target)) == .ok) { + if ((try ip.coerceInMemoryAllowed(arena, chosen, candidate_info.payload_type, true, target)) == .ok) { seen_const = seen_const or ip.isConstPointer(candidate_info.payload_type); any_are_null = true; continue; @@ -2265,7 +2255,7 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t }, .error_set_type => switch (chosen_key) { .error_set_type => { - chosen = try ip.errorSetMerge(gpa, chosen, candidate); + chosen = try ip.errorSetMerge(chosen, candidate); continue; }, else => {}, @@ -2289,17 +2279,17 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t else => {}, }, .optional_type => |chosen_info| { - if ((try ip.coerceInMemoryAllowed(gpa, arena, chosen_info.payload_type, candidate, true, target)) == .ok) { + if ((try ip.coerceInMemoryAllowed(arena, chosen_info.payload_type, candidate, true, target)) == .ok) { continue; } - if ((try ip.coerceInMemoryAllowed(gpa, arena, candidate, chosen_info.payload_type, true, target)) == .ok) { + if ((try ip.coerceInMemoryAllowed(arena, candidate, chosen_info.payload_type, true, target)) == .ok) { any_are_null = true; chosen = candidate; continue; } }, .error_union_type => |chosen_info| { - if ((try ip.coerceInMemoryAllowed(gpa, arena, chosen_info.payload_type, candidate, true, target)) == .ok) { + if ((try ip.coerceInMemoryAllowed(arena, chosen_info.payload_type, candidate, true, target)) == .ok) { continue; } }, @@ -2319,10 +2309,10 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t info.flags.is_const = seen_const or ip.isConstPointer(info.elem_type); info.elem_type = ip.elemType(info.elem_type); - const new_ptr_ty = try ip.get(gpa, .{ .pointer_type = info }); - const opt_ptr_ty = if (any_are_null) try ip.get(gpa, .{ .optional_type = .{ .payload_type = new_ptr_ty } }) else new_ptr_ty; + const new_ptr_ty = try ip.get(.{ .pointer_type = info }); + const opt_ptr_ty = if (any_are_null) try ip.get(.{ .optional_type = .{ .payload_type = new_ptr_ty } }) else new_ptr_ty; const set_ty = if (err_set_ty != .none) err_set_ty else return opt_ptr_ty; - return try ip.get(gpa, .{ .error_union_type = .{ + return try ip.get(.{ .error_union_type = .{ .error_set_type = set_ty, .payload_type = opt_ptr_ty, } }); @@ -2335,10 +2325,10 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t var info = ip.indexToKey(error_union_info.payload_type).pointer_type; info.flags.is_const = true; - const new_ptr_ty = try ip.get(gpa, .{ .pointer_type = info }); - const opt_ptr_ty = if (any_are_null) try ip.get(gpa, .{ .optional_type = .{ .payload_type = new_ptr_ty } }) else new_ptr_ty; + const new_ptr_ty = try ip.get(.{ .pointer_type = info }); + const opt_ptr_ty = if (any_are_null) try ip.get(.{ .optional_type = .{ .payload_type = new_ptr_ty } }) else new_ptr_ty; const set_ty = if (err_set_ty != .none) err_set_ty else error_union_info.error_set_type; - return try ip.get(gpa, .{ .error_union_type = .{ + return try ip.get(.{ .error_union_type = .{ .error_set_type = set_ty, .payload_type = opt_ptr_ty, } }); @@ -2347,10 +2337,10 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t var info = pointer_info; info.flags.is_const = true; - const new_ptr_ty = try ip.get(gpa, .{ .pointer_type = info }); - const opt_ptr_ty = if (any_are_null) try ip.get(gpa, .{ .optional_type = .{ .payload_type = new_ptr_ty } }) else new_ptr_ty; + const new_ptr_ty = try ip.get(.{ .pointer_type = info }); + const opt_ptr_ty = if (any_are_null) try ip.get(.{ .optional_type = .{ .payload_type = new_ptr_ty } }) else new_ptr_ty; const set_ty = if (err_set_ty != .none) err_set_ty else return opt_ptr_ty; - return try ip.get(gpa, .{ .error_union_type = .{ + return try ip.get(.{ .error_union_type = .{ .error_set_type = set_ty, .payload_type = opt_ptr_ty, } }); @@ -2363,13 +2353,13 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t const opt_ty = switch (ip.indexToKey(chosen)) { .simple_type => |simple| switch (simple) { .null_type => chosen, - else => try ip.get(gpa, .{ .optional_type = .{ .payload_type = chosen } }), + else => try ip.get(.{ .optional_type = .{ .payload_type = chosen } }), }, .optional_type => chosen, - else => try ip.get(gpa, .{ .optional_type = .{ .payload_type = chosen } }), + else => try ip.get(.{ .optional_type = .{ .payload_type = chosen } }), }; const set_ty = if (err_set_ty != .none) err_set_ty else return opt_ty; - return try ip.get(gpa, .{ .error_union_type = .{ + return try ip.get(.{ .error_union_type = .{ .error_set_type = set_ty, .payload_type = opt_ty, } }); @@ -2498,7 +2488,6 @@ const InMemoryCoercionResult = union(enum) { /// * array: same shape and coerceable child fn coerceInMemoryAllowed( ip: *InternPool, - gpa: Allocator, arena: Allocator, dest_ty: Index, src_ty: Index, @@ -2566,14 +2555,14 @@ fn coerceInMemoryAllowed( } }; }, .pointer => { - return try ip.coerceInMemoryAllowedPtrs(gpa, arena, dest_ty, src_ty, dest_is_const, target); + return try ip.coerceInMemoryAllowedPtrs(arena, dest_ty, src_ty, dest_is_const, target); }, .optional => { // Pointer-like Optionals const maybe_dest_ptr_ty = ip.optionalPtrTy(dest_ty); const maybe_src_ptr_ty = ip.optionalPtrTy(src_ty); if (maybe_dest_ptr_ty != .none and maybe_src_ptr_ty != .none) { - return try ip.coerceInMemoryAllowedPtrs(gpa, arena, dest_ty, src_ty, dest_is_const, target); + return try ip.coerceInMemoryAllowedPtrs(arena, dest_ty, src_ty, dest_is_const, target); } if (maybe_dest_ptr_ty != maybe_src_ptr_ty) { @@ -2586,7 +2575,7 @@ fn coerceInMemoryAllowed( const dest_child_type = dest_key.optional_type.payload_type; const src_child_type = src_key.optional_type.payload_type; - const child = try ip.coerceInMemoryAllowed(gpa, arena, dest_child_type, src_child_type, dest_is_const, target); + const child = try ip.coerceInMemoryAllowed(arena, dest_child_type, src_child_type, dest_is_const, target); if (child != .ok) { return .{ .optional_child = .{ .child = try child.dupe(arena), @@ -2598,12 +2587,12 @@ fn coerceInMemoryAllowed( return .ok; }, .@"fn" => { - return try ip.coerceInMemoryAllowedFns(gpa, arena, dest_ty, src_ty, target); + return try ip.coerceInMemoryAllowedFns(arena, dest_ty, src_ty, target); }, .error_union => { const dest_payload = dest_key.error_union_type.payload_type; const src_payload = src_key.error_union_type.payload_type; - const child = try ip.coerceInMemoryAllowed(gpa, arena, dest_payload, src_payload, dest_is_const, target); + const child = try ip.coerceInMemoryAllowed(arena, dest_payload, src_payload, dest_is_const, target); if (child != .ok) { return .{ .error_union_payload = .{ .child = try child.dupe(arena), @@ -2614,10 +2603,10 @@ fn coerceInMemoryAllowed( const dest_set = dest_key.error_union_type.error_set_type; const src_set = src_key.error_union_type.error_set_type; if (dest_set == .none or src_set == .none) return .ok; - return try ip.coerceInMemoryAllowedErrorSets(gpa, arena, dest_set, src_set); + return try ip.coerceInMemoryAllowedErrorSets(arena, dest_set, src_set); }, .error_set => { - return try ip.coerceInMemoryAllowedErrorSets(gpa, arena, dest_ty, src_ty); + return try ip.coerceInMemoryAllowedErrorSets(arena, dest_ty, src_ty); }, .array => { const dest_info = dest_key.array_type; @@ -2629,7 +2618,7 @@ fn coerceInMemoryAllowed( } }; } - const child = try ip.coerceInMemoryAllowed(gpa, arena, dest_info.child, src_info.child, dest_is_const, target); + const child = try ip.coerceInMemoryAllowed(arena, dest_info.child, src_info.child, dest_is_const, target); if (child != .ok) { return .{ .array_elem = .{ .child = try child.dupe(arena), @@ -2663,7 +2652,7 @@ fn coerceInMemoryAllowed( const dest_elem_ty = dest_key.vector_type.child; const src_elem_ty = src_key.vector_type.child; - const child = try ip.coerceInMemoryAllowed(gpa, arena, dest_elem_ty, src_elem_ty, dest_is_const, target); + const child = try ip.coerceInMemoryAllowed(arena, dest_elem_ty, src_elem_ty, dest_is_const, target); if (child != .ok) { return .{ .vector_elem = .{ .child = try child.dupe(arena), @@ -2685,7 +2674,6 @@ fn coerceInMemoryAllowed( fn coerceInMemoryAllowedErrorSets( ip: *InternPool, - gpa: Allocator, arena: Allocator, dest_ty: Index, src_ty: Index, @@ -2694,18 +2682,18 @@ fn coerceInMemoryAllowedErrorSets( if (dest_ty == .anyerror_type) return .ok; if (src_ty == .anyerror_type) return .from_anyerror; - const dest_set_names = try ip.indexToKey(dest_ty).error_set_type.names.dupe(gpa, ip); - defer gpa.free(dest_set_names); + const dest_set_names = try ip.indexToKey(dest_ty).error_set_type.names.dupe(ip.gpa, ip); + defer ip.gpa.free(dest_set_names); - const src_set_names = try ip.indexToKey(src_ty).error_set_type.names.dupe(gpa, ip); - defer gpa.free(src_set_names); + const src_set_names = try ip.indexToKey(src_ty).error_set_type.names.dupe(ip.gpa, ip); + defer ip.gpa.free(src_set_names); var missing_error_buf: std.ArrayList(String) = .empty; - defer missing_error_buf.deinit(gpa); + defer missing_error_buf.deinit(ip.gpa); for (src_set_names) |name| { if (std.mem.findScalar(String, dest_set_names, name) == null) { - try missing_error_buf.append(gpa, name); + try missing_error_buf.append(ip.gpa, name); } } @@ -2718,7 +2706,6 @@ fn coerceInMemoryAllowedErrorSets( fn coerceInMemoryAllowedFns( ip: *InternPool, - gpa: Allocator, arena: Allocator, dest_ty: Index, src_ty: Index, @@ -2743,7 +2730,7 @@ fn coerceInMemoryAllowedFns( } if (src_info.return_type != Index.noreturn_type) { - const rt = try ip.coerceInMemoryAllowed(gpa, arena, dest_info.return_type, src_info.return_type, true, target); + const rt = try ip.coerceInMemoryAllowed(arena, dest_info.return_type, src_info.return_type, true, target); if (rt != .ok) { return .{ .fn_return_type = .{ .child = try rt.dupe(arena), @@ -2775,15 +2762,15 @@ fn coerceInMemoryAllowedFns( } }; } - const dest_arg_types = try dest_info.args.dupe(gpa, ip); - defer gpa.free(dest_arg_types); + const dest_arg_types = try dest_info.args.dupe(ip.gpa, ip); + defer ip.gpa.free(dest_arg_types); - const src_arg_types = try src_info.args.dupe(gpa, ip); - defer gpa.free(src_arg_types); + const src_arg_types = try src_info.args.dupe(ip.gpa, ip); + defer ip.gpa.free(src_arg_types); for (dest_arg_types, src_arg_types, 0..) |dest_arg_ty, src_arg_ty, i| { // Note: Cast direction is reversed here. - const param = try ip.coerceInMemoryAllowed(gpa, arena, src_arg_ty, dest_arg_ty, true, target); + const param = try ip.coerceInMemoryAllowed(arena, src_arg_ty, dest_arg_ty, true, target); if (param != .ok) { return .{ .fn_param = .{ .child = try param.dupe(arena), @@ -2807,7 +2794,6 @@ fn coerceInMemoryAllowedFns( /// * sentinel-terminated pointers can coerce into `[*]` fn coerceInMemoryAllowedPtrs( ip: *InternPool, - gpa: Allocator, arena: Allocator, dest_ty: Index, src_ty: Index, @@ -2846,7 +2832,7 @@ fn coerceInMemoryAllowedPtrs( } }; } - const child = try ip.coerceInMemoryAllowed(gpa, arena, dest_info.elem_type, src_info.elem_type, dest_info.flags.is_const, target); + const child = try ip.coerceInMemoryAllowed(arena, dest_info.elem_type, src_info.elem_type, dest_info.flags.is_const, target); if (child != .ok) { return .{ .ptr_child = .{ .child = try child.dupe(arena), @@ -2953,8 +2939,8 @@ fn panicOrElse(comptime T: type, message: []const u8, value: T) T { // --------------------------------------------- pub fn zigTypeTag(ip: *InternPool, index: Index) ?std.builtin.TypeId { - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); return switch (ip.items.items(.tag)[@intFromEnum(index)]) { .simple_type => switch (@as(SimpleType, @enumFromInt(ip.items.items(.data)[@intFromEnum(index)]))) { .f16, @@ -3046,8 +3032,8 @@ pub fn zigTypeTag(ip: *InternPool, index: Index) ?std.builtin.TypeId { } pub fn typeOf(ip: *InternPool, index: Index) Index { - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); const data = ip.items.items(.data)[@intFromEnum(index)]; return switch (ip.items.items(.tag)[@intFromEnum(index)]) { .simple_value => switch (@as(SimpleValue, @enumFromInt(data))) { @@ -3105,8 +3091,8 @@ pub fn typeOf(ip: *InternPool, index: Index) Index { } pub fn isType(ip: *InternPool, ty: Index) bool { - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); return switch (ip.items.items(.tag)[@intFromEnum(ty)]) { .simple_type, .type_int_signed, @@ -3152,26 +3138,25 @@ pub fn isUnknown(ip: *InternPool, index: Index) bool { switch (index) { .unknown_type, .unknown_unknown => return true, else => { - ip.lock.lockShared(); - defer ip.lock.unlockShared(); + ip.lock.lockSharedUncancelable(ip.io); + defer ip.lock.unlockShared(ip.io); return ip.items.items(.tag)[@intFromEnum(index)] == .unknown_value; }, } } -pub fn isUnknownDeep(ip: *InternPool, gpa: Allocator, index: Index) Allocator.Error!bool { +pub fn isUnknownDeep(ip: *InternPool, index: Index) Allocator.Error!bool { var set: std.AutoHashMapUnmanaged(Index, void) = .empty; - defer set.deinit(gpa); - return try ip.isUnknownDeepInternal(index, gpa, &set); + defer set.deinit(ip.gpa); + return try ip.isUnknownDeepInternal(index, &set); } fn isUnknownDeepInternal( ip: *InternPool, index: Index, - gpa: Allocator, set: *std.AutoHashMapUnmanaged(Index, void), ) Allocator.Error!bool { - const gop = try set.getOrPut(gpa, index); + const gop = try set.getOrPut(ip.gpa, index); if (gop.found_existing) return false; return switch (ip.indexToKey(index)) { .simple_type => |simple| switch (simple) { @@ -3182,31 +3167,31 @@ fn isUnknownDeepInternal( .int_type => false, .pointer_type => |pointer_info| { - if (try ip.isUnknownDeepInternal(pointer_info.elem_type, gpa, set)) return true; - if (pointer_info.sentinel != .none and try ip.isUnknownDeepInternal(pointer_info.sentinel, gpa, set)) return true; + if (try ip.isUnknownDeepInternal(pointer_info.elem_type, set)) return true; + if (pointer_info.sentinel != .none and try ip.isUnknownDeepInternal(pointer_info.sentinel, set)) return true; return false; }, .array_type => |array_info| { - if (try ip.isUnknownDeepInternal(array_info.child, gpa, set)) return true; - if (array_info.sentinel != .none and try ip.isUnknownDeepInternal(array_info.sentinel, gpa, set)) return true; + if (try ip.isUnknownDeepInternal(array_info.child, set)) return true; + if (array_info.sentinel != .none and try ip.isUnknownDeepInternal(array_info.sentinel, set)) return true; return false; }, .struct_type => |struct_index| { const struct_info = ip.getStruct(struct_index); for (struct_info.fields.values()) |field| { - if (try ip.isUnknownDeepInternal(field.ty, gpa, set)) return true; - if (field.default_value != .none and try ip.isUnknownDeepInternal(field.default_value, gpa, set)) return true; + if (try ip.isUnknownDeepInternal(field.ty, set)) return true; + if (field.default_value != .none and try ip.isUnknownDeepInternal(field.default_value, set)) return true; } // TODO namespace return false; }, - .optional_type => |optional_info| try ip.isUnknownDeepInternal(optional_info.payload_type, gpa, set), - .error_union_type => |error_union_info| try ip.isUnknownDeepInternal(error_union_info.payload_type, gpa, set), + .optional_type => |optional_info| try ip.isUnknownDeepInternal(optional_info.payload_type, set), + .error_union_type => |error_union_info| try ip.isUnknownDeepInternal(error_union_info.payload_type, set), .error_set_type => false, .enum_type => |enum_index| { const enum_info = ip.getEnum(enum_index); for (enum_info.values.keys()) |val| { - if (try ip.isUnknownDeepInternal(val, gpa, set)) return true; + if (try ip.isUnknownDeepInternal(val, set)) return true; } // TODO namespace return false; @@ -3214,15 +3199,15 @@ fn isUnknownDeepInternal( .function_type => |function_info| { for (0..function_info.args.len) |i| { const arg_ty = function_info.args.at(@intCast(i), ip); - if (try ip.isUnknownDeepInternal(arg_ty, gpa, set)) return true; + if (try ip.isUnknownDeepInternal(arg_ty, set)) return true; } - if (try ip.isUnknownDeepInternal(function_info.return_type, gpa, set)) return true; + if (try ip.isUnknownDeepInternal(function_info.return_type, set)) return true; return false; }, .union_type => |union_index| { const union_info = ip.getUnion(union_index); for (union_info.fields.values()) |field| { - if (try ip.isUnknownDeepInternal(field.ty, gpa, set)) return true; + if (try ip.isUnknownDeepInternal(field.ty, set)) return true; } // TODO namespace return false; @@ -3233,13 +3218,13 @@ fn isUnknownDeepInternal( for (0..tuple_info.types.len) |i| { const ty = tuple_info.types.at(@intCast(i), ip); const val = tuple_info.values.at(@intCast(i), ip); - if (try ip.isUnknownDeepInternal(ty, gpa, set)) return true; - if (try ip.isUnknownDeepInternal(val, gpa, set)) return true; + if (try ip.isUnknownDeepInternal(ty, set)) return true; + if (try ip.isUnknownDeepInternal(val, set)) return true; } return false; }, - .vector_type => |vector_info| try ip.isUnknownDeepInternal(vector_info.child, gpa, set), - .anyframe_type => |anyframe_info| try ip.isUnknownDeepInternal(anyframe_info.child, gpa, set), + .vector_type => |vector_info| try ip.isUnknownDeepInternal(vector_info.child, set), + .anyframe_type => |anyframe_info| try ip.isUnknownDeepInternal(anyframe_info.child, set), .int_u64_value, .int_i64_value, @@ -3259,7 +3244,7 @@ fn isUnknownDeepInternal( .error_value, .null_value, .undefined_value, - => try ip.isUnknownDeepInternal(ip.typeOf(index), gpa, set), + => try ip.isUnknownDeepInternal(ip.typeOf(index), set), .unknown_value => true, }; } @@ -3345,7 +3330,7 @@ pub fn intInfo(ip: *InternPool, ty: Index, target: std.Target) std.builtin.Type. } /// Asserts the type is an integer or vector of integers. -pub fn toUnsigned(ip: *InternPool, gpa: Allocator, ty: Index, target: std.Target) Allocator.Error!Index { +pub fn toUnsigned(ip: *InternPool, ty: Index, target: std.Target) Allocator.Error!Index { const tag = ip.zigTypeTag(ty) orelse unreachable; return switch (ty) { .usize_type, .isize_type => .usize_type, @@ -3354,13 +3339,13 @@ pub fn toUnsigned(ip: *InternPool, gpa: Allocator, ty: Index, target: std.Target .c_ulong_type, .c_long_type => .c_ulong_type, .c_ulonglong_type, .c_longlong_type => .c_ulonglong_type, else => switch (tag) { - .int => try ip.get(gpa, .{ .int_type = .{ + .int => try ip.get(.{ .int_type = .{ .signedness = .unsigned, .bits = ip.intInfo(ty, target).bits, } }), - .vector => try ip.get(gpa, .{ .vector_type = .{ + .vector => try ip.get(.{ .vector_type = .{ .len = ip.vectorLen(ty), - .child = try ip.toUnsigned(gpa, ip.childType(ty), target), + .child = try ip.toUnsigned(ip.childType(ty), target), } }), else => unreachable, }, @@ -3524,7 +3509,7 @@ pub fn scalarType(ip: *InternPool, ty: Index) Index { }; } -pub fn errorSetMerge(ip: *InternPool, gpa: Allocator, a_ty: Index, b_ty: Index) Allocator.Error!Index { +pub fn errorSetMerge(ip: *InternPool, a_ty: Index, b_ty: Index) Allocator.Error!Index { assert(ip.zigTypeTag(a_ty) == .error_set); assert(ip.zigTypeTag(b_ty) == .error_set); @@ -3535,24 +3520,24 @@ pub fn errorSetMerge(ip: *InternPool, gpa: Allocator, a_ty: Index, b_ty: Index) if (a_ty == b_ty) return a_ty; - const a_names = try ip.indexToKey(a_ty).error_set_type.names.dupe(gpa, ip); - defer gpa.free(a_names); + const a_names = try ip.indexToKey(a_ty).error_set_type.names.dupe(ip.gpa, ip); + defer ip.gpa.free(a_names); - const b_names = try ip.indexToKey(b_ty).error_set_type.names.dupe(gpa, ip); - defer gpa.free(b_names); + const b_names = try ip.indexToKey(b_ty).error_set_type.names.dupe(ip.gpa, ip); + defer ip.gpa.free(b_names); var set: std.AutoArrayHashMapUnmanaged(String, void) = .empty; - defer set.deinit(gpa); + defer set.deinit(ip.gpa); - try set.ensureTotalCapacity(gpa, a_names.len + b_names.len); + try set.ensureTotalCapacity(ip.gpa, a_names.len + b_names.len); for (a_names) |name| set.putAssumeCapacityNoClobber(name, {}); for (b_names) |name| set.putAssumeCapacity(name, {}); - return try ip.get(gpa, .{ + return try ip.get(.{ .error_set_type = .{ .owner_decl = .none, - .names = try ip.getStringSlice(gpa, set.keys()), + .names = try ip.getStringSlice(set.keys()), }, }); } @@ -3827,29 +3812,29 @@ pub fn toInt(ip: *InternPool, val: Index, comptime T: type) ?T { }; } -pub fn getBigInt(ip: *InternPool, gpa: Allocator, ty: Index, int: std.math.big.int.Const) Allocator.Error!Index { +pub fn getBigInt(ip: *InternPool, ty: Index, int: std.math.big.int.Const) Allocator.Error!Index { assert(ip.isType(ty)); - return try ip.get(gpa, .{ + return try ip.get(.{ .int_big_value = .{ .ty = ty, .storage = .{ .external = int } }, }); } -pub fn getNull(ip: *InternPool, gpa: Allocator, ty: Index) Allocator.Error!Index { +pub fn getNull(ip: *InternPool, ty: Index) Allocator.Error!Index { if (ty == .none) return Index.null_value; assert(ip.isType(ty)); - return try ip.get(gpa, .{ .null_value = .{ .ty = ty } }); + return try ip.get(.{ .null_value = .{ .ty = ty } }); } -pub fn getUndefined(ip: *InternPool, gpa: Allocator, ty: Index) Allocator.Error!Index { +pub fn getUndefined(ip: *InternPool, ty: Index) Allocator.Error!Index { assert(ip.isType(ty)); - return try ip.get(gpa, .{ .undefined_value = .{ .ty = ty } }); + return try ip.get(.{ .undefined_value = .{ .ty = ty } }); } -pub fn getUnknown(ip: *InternPool, gpa: Allocator, ty: Index) Allocator.Error!Index { +pub fn getUnknown(ip: *InternPool, ty: Index) Allocator.Error!Index { assert(ip.isType(ty)); if (ty == .type_type) return Index.unknown_type; if (ty == .unknown_type) return Index.unknown_unknown; - return try ip.get(gpa, .{ .unknown_value = .{ .ty = ty } }); + return try ip.get(.{ .unknown_value = .{ .ty = ty } }); } // --------------------------------------------- @@ -4170,8 +4155,8 @@ const FormatId = struct { string: String, fn render(ctx: FormatId, writer: *std.Io.Writer) std.Io.Writer.Error!void { - const locked_string = ctx.ip.string_pool.stringToSliceLock(ctx.string); - defer locked_string.release(&ctx.ip.string_pool); + const locked_string = ctx.ip.string_pool.stringToSliceLock(ctx.ip.io, ctx.string); + defer locked_string.release(ctx.ip.io, &ctx.ip.string_pool); try writer.print("{f}", .{std.zig.fmtId(locked_string.slice)}); } }; @@ -4186,20 +4171,21 @@ pub fn fmtId(ip: *InternPool, string: String) std.fmt.Alt(FormatId, FormatId.ren test "simple types" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const null_type = try ip.get(gpa, .{ .simple_type = .null_type }); - const undefined_type = try ip.get(gpa, .{ .simple_type = .undefined_type }); - const enum_literal_type = try ip.get(gpa, .{ .simple_type = .enum_literal_type }); + const null_type = try ip.get(.{ .simple_type = .null_type }); + const undefined_type = try ip.get(.{ .simple_type = .undefined_type }); + const enum_literal_type = try ip.get(.{ .simple_type = .enum_literal_type }); - const undefined_value = try ip.get(gpa, .{ .simple_value = .undefined_value }); - const void_value = try ip.get(gpa, .{ .simple_value = .void_value }); - const unreachable_value = try ip.get(gpa, .{ .simple_value = .unreachable_value }); - const null_value = try ip.get(gpa, .{ .simple_value = .null_value }); - const bool_true = try ip.get(gpa, .{ .simple_value = .bool_true }); - const bool_false = try ip.get(gpa, .{ .simple_value = .bool_false }); + const undefined_value = try ip.get(.{ .simple_value = .undefined_value }); + const void_value = try ip.get(.{ .simple_value = .void_value }); + const unreachable_value = try ip.get(.{ .simple_value = .unreachable_value }); + const null_value = try ip.get(.{ .simple_value = .null_value }); + const bool_true = try ip.get(.{ .simple_value = .bool_true }); + const bool_false = try ip.get(.{ .simple_value = .bool_false }); try expectFmt("@TypeOf(null)", "{f}", .{null_type.fmt(&ip)}); try expectFmt("@TypeOf(undefined)", "{f}", .{undefined_type.fmt(&ip)}); @@ -4223,14 +4209,15 @@ test "simple types" { test "int type" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const i32_type = try ip.get(gpa, .{ .int_type = .{ .signedness = .signed, .bits = 32 } }); - const i16_type = try ip.get(gpa, .{ .int_type = .{ .signedness = .signed, .bits = 16 } }); - const u7_type = try ip.get(gpa, .{ .int_type = .{ .signedness = .unsigned, .bits = 7 } }); - const another_i32_type = try ip.get(gpa, .{ .int_type = .{ .signedness = .signed, .bits = 32 } }); + const i32_type = try ip.get(.{ .int_type = .{ .signedness = .signed, .bits = 32 } }); + const i16_type = try ip.get(.{ .int_type = .{ .signedness = .signed, .bits = 16 } }); + const u7_type = try ip.get(.{ .int_type = .{ .signedness = .unsigned, .bits = 7 } }); + const another_i32_type = try ip.get(.{ .int_type = .{ .signedness = .signed, .bits = 32 } }); try expect(i32_type == another_i32_type); try expect(i32_type != u7_type); @@ -4261,10 +4248,10 @@ test "int type" { try expect(ip.isUnsignedInt(u7_type, builtin.target)); try expect(!ip.isSignedInt(u7_type, builtin.target)); - try expect(.u32_type == try ip.toUnsigned(gpa, i32_type, builtin.target)); - try expect(.u16_type == try ip.toUnsigned(gpa, i16_type, builtin.target)); - try expect(.u16_type == try ip.toUnsigned(gpa, .u16_type, builtin.target)); - try expect(u7_type == try ip.toUnsigned(gpa, u7_type, builtin.target)); + try expect(.u32_type == try ip.toUnsigned(i32_type, builtin.target)); + try expect(.u16_type == try ip.toUnsigned(i16_type, builtin.target)); + try expect(.u16_type == try ip.toUnsigned(.u16_type, builtin.target)); + try expect(u7_type == try ip.toUnsigned(u7_type, builtin.target)); try expect(i32_type == ip.scalarType(i32_type)); try expect(i16_type == ip.scalarType(i16_type)); @@ -4273,18 +4260,19 @@ test "int type" { test "int value" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const unsigned_zero_value = try ip.get(gpa, .{ .int_u64_value = .{ .ty = .u64_type, .int = 0 } }); - const unsigned_one_value = try ip.get(gpa, .{ .int_u64_value = .{ .ty = .u64_type, .int = 1 } }); - const signed_zero_value = try ip.get(gpa, .{ .int_u64_value = .{ .ty = .i64_type, .int = 0 } }); - const signed_one_value = try ip.get(gpa, .{ .int_u64_value = .{ .ty = .i64_type, .int = 1 } }); + const unsigned_zero_value = try ip.get(.{ .int_u64_value = .{ .ty = .u64_type, .int = 0 } }); + const unsigned_one_value = try ip.get(.{ .int_u64_value = .{ .ty = .u64_type, .int = 1 } }); + const signed_zero_value = try ip.get(.{ .int_u64_value = .{ .ty = .i64_type, .int = 0 } }); + const signed_one_value = try ip.get(.{ .int_u64_value = .{ .ty = .i64_type, .int = 1 } }); - const u64_max_value = try ip.get(gpa, .{ .int_u64_value = .{ .ty = .u64_type, .int = std.math.maxInt(u64) } }); - const i64_max_value = try ip.get(gpa, .{ .int_i64_value = .{ .ty = .i64_type, .int = std.math.maxInt(i64) } }); - const i64_min_value = try ip.get(gpa, .{ .int_i64_value = .{ .ty = .i64_type, .int = std.math.minInt(i64) } }); + const u64_max_value = try ip.get(.{ .int_u64_value = .{ .ty = .u64_type, .int = std.math.maxInt(u64) } }); + const i64_max_value = try ip.get(.{ .int_i64_value = .{ .ty = .i64_type, .int = std.math.maxInt(i64) } }); + const i64_min_value = try ip.get(.{ .int_i64_value = .{ .ty = .i64_type, .int = std.math.minInt(i64) } }); try expect(unsigned_zero_value != unsigned_one_value); try expect(unsigned_one_value != signed_zero_value); @@ -4306,8 +4294,9 @@ test "int value" { test "big int value" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); var result: std.math.big.int.Managed = try .init(gpa); @@ -4317,10 +4306,10 @@ test "big int value" { try result.pow(&a, 128); - const positive_big_int_value = try ip.getBigInt(gpa, .comptime_int_type, result.toConst()); - const negative_big_int_value = try ip.getBigInt(gpa, .comptime_int_type, result.toConst().negate()); + const positive_big_int_value = try ip.getBigInt(.comptime_int_type, result.toConst()); + const negative_big_int_value = try ip.getBigInt(.comptime_int_type, result.toConst().negate()); - const another_positive_big_int_value = try ip.getBigInt(gpa, .comptime_int_type, result.toConst()); + const another_positive_big_int_value = try ip.getBigInt(.comptime_int_type, result.toConst()); try std.testing.expect(positive_big_int_value != negative_big_int_value); try std.testing.expectEqual(positive_big_int_value, another_positive_big_int_value); @@ -4335,18 +4324,19 @@ test "big int value" { test "float type" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const f16_type = try ip.get(gpa, .{ .simple_type = .f16 }); - const f32_type = try ip.get(gpa, .{ .simple_type = .f32 }); - const f64_type = try ip.get(gpa, .{ .simple_type = .f64 }); - const f80_type = try ip.get(gpa, .{ .simple_type = .f80 }); - const f128_type = try ip.get(gpa, .{ .simple_type = .f128 }); + const f16_type = try ip.get(.{ .simple_type = .f16 }); + const f32_type = try ip.get(.{ .simple_type = .f32 }); + const f64_type = try ip.get(.{ .simple_type = .f64 }); + const f80_type = try ip.get(.{ .simple_type = .f80 }); + const f128_type = try ip.get(.{ .simple_type = .f128 }); - const another_f32_type = try ip.get(gpa, .{ .simple_type = .f32 }); - const another_f64_type = try ip.get(gpa, .{ .simple_type = .f64 }); + const another_f32_type = try ip.get(.{ .simple_type = .f32 }); + const another_f64_type = try ip.get(.{ .simple_type = .f64 }); try expect(f16_type != f32_type); try expect(f32_type != f64_type); @@ -4365,24 +4355,25 @@ test "float type" { test "float value" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const f16_value = try ip.get(gpa, .{ .float_16_value = 0.25 }); - const f32_value = try ip.get(gpa, .{ .float_32_value = 0.5 }); - const f64_value = try ip.get(gpa, .{ .float_64_value = 1.0 }); - const f80_value = try ip.get(gpa, .{ .float_80_value = 2.0 }); - const f128_value = try ip.get(gpa, .{ .float_128_value = 2.75 }); + const f16_value = try ip.get(.{ .float_16_value = 0.25 }); + const f32_value = try ip.get(.{ .float_32_value = 0.5 }); + const f64_value = try ip.get(.{ .float_64_value = 1.0 }); + const f80_value = try ip.get(.{ .float_80_value = 2.0 }); + const f128_value = try ip.get(.{ .float_128_value = 2.75 }); - const f32_snan_value = try ip.get(gpa, .{ .float_32_value = std.math.snan(f32) }); - const f32_qnan_value = try ip.get(gpa, .{ .float_32_value = std.math.nan(f32) }); + const f32_snan_value = try ip.get(.{ .float_32_value = std.math.snan(f32) }); + const f32_qnan_value = try ip.get(.{ .float_32_value = std.math.nan(f32) }); - const f32_inf_value = try ip.get(gpa, .{ .float_32_value = std.math.inf(f32) }); - const f32_ninf_value = try ip.get(gpa, .{ .float_32_value = -std.math.inf(f32) }); + const f32_inf_value = try ip.get(.{ .float_32_value = std.math.inf(f32) }); + const f32_ninf_value = try ip.get(.{ .float_32_value = -std.math.inf(f32) }); - const f32_zero_value = try ip.get(gpa, .{ .float_32_value = 0.0 }); - const f32_nzero_value = try ip.get(gpa, .{ .float_32_value = -0.0 }); + const f32_zero_value = try ip.get(.{ .float_32_value = 0.0 }); + const f32_nzero_value = try ip.get(.{ .float_32_value = -0.0 }); try expect(f16_value != f32_value); try expect(f32_value != f64_value); @@ -4423,19 +4414,20 @@ test "float value" { test "pointer type" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip = try InternPool.init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"*i32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"*i32" = try ip.get(.{ .pointer_type = .{ .elem_type = .i32_type, .flags = .{ .size = .one }, } }); - const @"*u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"*u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .one }, } }); - const @"*const volatile u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"*const volatile u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .one, @@ -4443,7 +4435,7 @@ test "pointer type" { .is_volatile = true, }, } }); - const @"*align(4:2:3) u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"*align(4:2:3) u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .one, @@ -4454,7 +4446,7 @@ test "pointer type" { .host_size = 3, }, } }); - const @"*allowzero addrspace(.shared) const u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"*allowzero addrspace(.shared) const u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .one, @@ -4464,25 +4456,25 @@ test "pointer type" { }, } }); - const @"[*]u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"[*]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .many }, } }); - const @"[*:0]u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"[*:0]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .sentinel = .zero_comptime_int, .flags = .{ .size = .many }, } }); - const @"[]u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"[]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .slice }, } }); - const @"[:0]u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"[:0]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .sentinel = .zero_comptime_int, .flags = .{ .size = .slice }, } }); - const @"[*c]u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"[*c]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .c }, } }); @@ -4512,12 +4504,13 @@ test "pointer type" { test "optional type" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const i32_optional_type = try ip.get(gpa, .{ .optional_type = .{ .payload_type = .i32_type } }); - const u32_optional_type = try ip.get(gpa, .{ .optional_type = .{ .payload_type = .u32_type } }); + const i32_optional_type = try ip.get(.{ .optional_type = .{ .payload_type = .i32_type } }); + const u32_optional_type = try ip.get(.{ .optional_type = .{ .payload_type = .u32_type } }); try expect(i32_optional_type != u32_optional_type); @@ -4527,41 +4520,43 @@ test "optional type" { test "optional value" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const u32_optional_type = try ip.get(gpa, .{ .optional_type = .{ .payload_type = .u32_type } }); + const u32_optional_type = try ip.get(.{ .optional_type = .{ .payload_type = .u32_type } }); - const u64_42_value = try ip.get(gpa, .{ .int_u64_value = .{ .ty = .u64_type, .int = 42 } }); - const optional_42_value = try ip.get(gpa, .{ .optional_value = .{ .ty = u32_optional_type, .val = u64_42_value } }); + const u64_42_value = try ip.get(.{ .int_u64_value = .{ .ty = .u64_type, .int = 42 } }); + const optional_42_value = try ip.get(.{ .optional_value = .{ .ty = u32_optional_type, .val = u64_42_value } }); try expectFmt("42", "{f}", .{optional_42_value.fmt(&ip)}); } test "error set type" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const foo_name = try ip.string_pool.getOrPutString(gpa, "foo"); - const bar_name = try ip.string_pool.getOrPutString(gpa, "bar"); - const baz_name = try ip.string_pool.getOrPutString(gpa, "baz"); + const foo_name = try ip.string_pool.getOrPutString(io, gpa, "foo"); + const bar_name = try ip.string_pool.getOrPutString(io, gpa, "bar"); + const baz_name = try ip.string_pool.getOrPutString(io, gpa, "baz"); - const empty_error_set = try ip.get(gpa, .{ .error_set_type = .{ + const empty_error_set = try ip.get(.{ .error_set_type = .{ .owner_decl = .none, .names = StringSlice.empty, } }); - const foo_bar_baz_set = try ip.get(gpa, .{ .error_set_type = .{ + const foo_bar_baz_set = try ip.get(.{ .error_set_type = .{ .owner_decl = .none, - .names = try ip.getStringSlice(gpa, &.{ foo_name, bar_name, baz_name }), + .names = try ip.getStringSlice(&.{ foo_name, bar_name, baz_name }), } }); - const foo_bar_set = try ip.get(gpa, .{ .error_set_type = .{ + const foo_bar_set = try ip.get(.{ .error_set_type = .{ .owner_decl = .none, - .names = try ip.getStringSlice(gpa, &.{ foo_name, bar_name }), + .names = try ip.getStringSlice(&.{ foo_name, bar_name }), } }); try expect(empty_error_set != foo_bar_baz_set); @@ -4574,17 +4569,18 @@ test "error set type" { test "error union type" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const empty_error_set = try ip.get(gpa, .{ .error_set_type = .{ + const empty_error_set = try ip.get(.{ .error_set_type = .{ .owner_decl = .none, .names = StringSlice.empty, } }); - const bool_type = try ip.get(gpa, .{ .simple_type = .bool }); + const bool_type = try ip.get(.{ .simple_type = .bool }); - const @"error{}!bool" = try ip.get(gpa, .{ .error_union_type = .{ + const @"error{}!bool" = try ip.get(.{ .error_union_type = .{ .error_set_type = empty_error_set, .payload_type = bool_type, } }); @@ -4594,15 +4590,16 @@ test "error union type" { test "array type" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const i32_3_array_type = try ip.get(gpa, .{ .array_type = .{ + const i32_3_array_type = try ip.get(.{ .array_type = .{ .len = 3, .child = .i32_type, } }); - const u32_0_0_array_type = try ip.get(gpa, .{ .array_type = .{ + const u32_0_0_array_type = try ip.get(.{ .array_type = .{ .len = 3, .child = .u32_type, .sentinel = .zero_comptime_int, @@ -4616,14 +4613,15 @@ test "array type" { test "struct value" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const foo_name_index = try ip.string_pool.getOrPutString(gpa, "foo"); - const bar_name_index = try ip.string_pool.getOrPutString(gpa, "bar"); + const foo_name_index = try ip.string_pool.getOrPutString(io, gpa, "foo"); + const bar_name_index = try ip.string_pool.getOrPutString(io, gpa, "bar"); - const struct_index = try ip.createStruct(gpa, .{ + const struct_index = try ip.createStruct(.{ .fields = .empty, .owner_decl = .none, .namespace = .none, @@ -4631,14 +4629,14 @@ test "struct value" { .backing_int_ty = .none, .status = .none, }); - const struct_type = try ip.get(gpa, .{ .struct_type = struct_index }); + const struct_type = try ip.get(.{ .struct_type = struct_index }); const struct_info = ip.getStructMut(struct_index); try struct_info.fields.put(gpa, foo_name_index, .{ .ty = .usize_type }); try struct_info.fields.put(gpa, bar_name_index, .{ .ty = .bool_type }); - const aggregate_value = try ip.get(gpa, .{ .aggregate = .{ + const aggregate_value = try ip.get(.{ .aggregate = .{ .ty = struct_type, - .values = try ip.getIndexSlice(gpa, &.{ .one_usize, .bool_true }), + .values = try ip.getIndexSlice(&.{ .one_usize, .bool_true }), } }); try expectFmt(".{.foo = 1, .bar = true}", "{f}", .{aggregate_value.fmt(&ip)}); @@ -4646,12 +4644,13 @@ test "struct value" { test "function type" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"fn(i32) bool" = try ip.get(gpa, .{ .function_type = .{ - .args = try ip.getIndexSlice(gpa, &.{.i32_type}), + const @"fn(i32) bool" = try ip.get(.{ .function_type = .{ + .args = try ip.getIndexSlice(&.{.i32_type}), .return_type = .bool_type, } }); @@ -4660,22 +4659,22 @@ test "function type" { var args_is_noalias: std.StaticBitSet(32) = .initEmpty(); args_is_noalias.set(1); - const @"fn(comptime type, noalias i32) type" = try ip.get(gpa, .{ .function_type = .{ - .args = try ip.getIndexSlice(gpa, &.{ .type_type, .i32_type }), + const @"fn(comptime type, noalias i32) type" = try ip.get(.{ .function_type = .{ + .args = try ip.getIndexSlice(&.{ .type_type, .i32_type }), .args_is_comptime = args_is_comptime, .args_is_noalias = args_is_noalias, .return_type = .type_type, } }); - const @"fn(i32, ...) type" = try ip.get(gpa, .{ .function_type = .{ - .args = try ip.getIndexSlice(gpa, &.{.i32_type}), + const @"fn(i32, ...) type" = try ip.get(.{ .function_type = .{ + .args = try ip.getIndexSlice(&.{.i32_type}), .return_type = .type_type, .flags = .{ .is_var_args = true, }, } }); - const @"fn() align(4) callconv(.c) type" = try ip.get(gpa, .{ .function_type = .{ + const @"fn() align(4) callconv(.c) type" = try ip.get(.{ .function_type = .{ .args = .empty, .return_type = .type_type, .flags = .{ @@ -4692,33 +4691,34 @@ test "function type" { test "union value" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const int_name_index = try ip.string_pool.getOrPutString(gpa, "int"); - const float_name_index = try ip.string_pool.getOrPutString(gpa, "float"); + const int_name_index = try ip.string_pool.getOrPutString(io, gpa, "int"); + const float_name_index = try ip.string_pool.getOrPutString(io, gpa, "float"); - const f16_value = try ip.get(gpa, .{ .float_16_value = 0.25 }); + const f16_value = try ip.get(.{ .float_16_value = 0.25 }); - const union_index = try ip.createUnion(gpa, .{ + const union_index = try ip.createUnion(.{ .tag_type = .none, .fields = .empty, .namespace = .none, .layout = .auto, .status = .none, }); - const union_type = try ip.get(gpa, .{ .union_type = union_index }); + const union_type = try ip.get(.{ .union_type = union_index }); const union_info = ip.getUnionMut(union_index); try union_info.fields.put(gpa, int_name_index, .{ .ty = .usize_type, .alignment = 0 }); try union_info.fields.put(gpa, float_name_index, .{ .ty = .f16_type, .alignment = 0 }); - const union_value1 = try ip.get(gpa, .{ .union_value = .{ + const union_value1 = try ip.get(.{ .union_value = .{ .ty = union_type, .field_index = 0, .val = .one_usize, } }); - const union_value2 = try ip.get(gpa, .{ .union_value = .{ + const union_value2 = try ip.get(.{ .union_value = .{ .ty = union_type, .field_index = 1, .val = f16_value, @@ -4730,12 +4730,13 @@ test "union value" { test "anyframe type" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"anyframe->i32" = try ip.get(gpa, .{ .anyframe_type = .{ .child = .i32_type } }); - const @"anyframe->bool" = try ip.get(gpa, .{ .anyframe_type = .{ .child = .bool_type } }); + const @"anyframe->i32" = try ip.get(.{ .anyframe_type = .{ .child = .i32_type } }); + const @"anyframe->bool" = try ip.get(.{ .anyframe_type = .{ .child = .bool_type } }); try expect(@"anyframe->i32" != @"anyframe->bool"); @@ -4745,19 +4746,20 @@ test "anyframe type" { test "vector type" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"@Vector(2,i32)" = try ip.get(gpa, .{ .vector_type = .{ + const @"@Vector(2,i32)" = try ip.get(.{ .vector_type = .{ .len = 2, .child = .i32_type, } }); - const @"@Vector(2,u32)" = try ip.get(gpa, .{ .vector_type = .{ + const @"@Vector(2,u32)" = try ip.get(.{ .vector_type = .{ .len = 2, .child = .u32_type, } }); - const @"@Vector(2,bool)" = try ip.get(gpa, .{ .vector_type = .{ + const @"@Vector(2,bool)" = try ip.get(.{ .vector_type = .{ .len = 2, .child = .bool_type, } }); @@ -4768,8 +4770,8 @@ test "vector type" { try expectFmt("@Vector(2,u32)", "{f}", .{@"@Vector(2,u32)".fmt(&ip)}); try expectFmt("@Vector(2,bool)", "{f}", .{@"@Vector(2,bool)".fmt(&ip)}); - try expect(@"@Vector(2,u32)" == try ip.toUnsigned(gpa, @"@Vector(2,i32)", builtin.target)); - try expect(@"@Vector(2,u32)" == try ip.toUnsigned(gpa, @"@Vector(2,u32)", builtin.target)); + try expect(@"@Vector(2,u32)" == try ip.toUnsigned(@"@Vector(2,i32)", builtin.target)); + try expect(@"@Vector(2,u32)" == try ip.toUnsigned(@"@Vector(2,u32)", builtin.target)); try expect(.i32_type == ip.scalarType(@"@Vector(2,i32)")); try expect(.u32_type == ip.scalarType(@"@Vector(2,u32)")); @@ -4782,13 +4784,14 @@ test "vector type" { test "Index.Slice" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - _ = try ip.getIndexSlice(gpa, &.{ .none, .c_ulonglong_type, .call_modifier_type }); - const index_slice = try ip.getIndexSlice(gpa, &.{ .bool_type, .f32_type, .one_u8 }); - _ = try ip.getIndexSlice(gpa, &.{ .bool_false, .none, .anyerror_type }); + _ = try ip.getIndexSlice(&.{ .none, .c_ulonglong_type, .call_modifier_type }); + const index_slice = try ip.getIndexSlice(&.{ .bool_type, .f32_type, .one_u8 }); + _ = try ip.getIndexSlice(&.{ .bool_false, .none, .anyerror_type }); try std.testing.expectEqual(@as(u32, 3), index_slice.len); try std.testing.expectEqual(Index.bool_type, index_slice.at(0, &ip)); @@ -4808,17 +4811,18 @@ test "Index.Slice" { test StringSlice { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const str1 = try ip.string_pool.getOrPutString(gpa, "aaa"); - const str2 = try ip.string_pool.getOrPutString(gpa, "bbb"); - const str3 = try ip.string_pool.getOrPutString(gpa, "ccc"); + const str1 = try ip.string_pool.getOrPutString(io, gpa, "aaa"); + const str2 = try ip.string_pool.getOrPutString(io, gpa, "bbb"); + const str3 = try ip.string_pool.getOrPutString(io, gpa, "ccc"); - _ = try ip.getStringSlice(gpa, &.{ str2, str1, str3 }); - const string_slice = try ip.getStringSlice(gpa, &.{ str1, str2, str3 }); - _ = try ip.getStringSlice(gpa, &.{ str3, str2, str1 }); + _ = try ip.getStringSlice(&.{ str2, str1, str3 }); + const string_slice = try ip.getStringSlice(&.{ str1, str2, str3 }); + _ = try ip.getStringSlice(&.{ str3, str2, str1 }); try std.testing.expectEqual(@as(u32, 3), string_slice.len); try std.testing.expectEqual(str1, string_slice.at(0, &ip)); @@ -4842,7 +4846,7 @@ test "test thread safety of InternPool" { const gpa = std.testing.allocator; const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); const index_start = ip.map.count(); @@ -4852,12 +4856,11 @@ test "test thread safety of InternPool" { const funcs = struct { fn do( intern_pool: *InternPool, - allocator: std.mem.Allocator, count: usize, ) void { // insert float_32_value from 0 to count + random work for (0..count) |i| { - _ = intern_pool.get(allocator, .{ .float_32_value = @floatFromInt(i) }) catch @panic("OOM"); + _ = intern_pool.get(.{ .float_32_value = @floatFromInt(i) }) catch @panic("OOM"); _ = intern_pool.indexToKey(@enumFromInt(i)); } for (0..count) |i| { @@ -4870,7 +4873,7 @@ test "test thread safety of InternPool" { var wait_group: std.Io.Group = .init; for (0..cpu_count) |_| { - wait_group.async(io, funcs.do, .{ &ip, gpa, size }); + wait_group.async(io, funcs.do, .{ &ip, size }); } try wait_group.await(io); @@ -4899,94 +4902,97 @@ test "test thread safety of InternPool" { test "coerceInMemoryAllowed integers and floats" { const gpa = std.testing.allocator; + const io = std.testing.io; + + var ip: InternPool = try .init(io, gpa); + defer ip.deinit(gpa); var arena_allocator: std.heap.ArenaAllocator = .init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - var ip: InternPool = try .init(gpa); - defer ip.deinit(gpa); - - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .u32_type, .u32_type, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .u32_type, .u16_type, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .u16_type, .u32_type, true, builtin.target) == .int_not_coercible); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .i32_type, .u32_type, true, builtin.target) == .int_not_coercible); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .u32_type, .i32_type, true, builtin.target) == .int_not_coercible); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .u32_type, .i16_type, true, builtin.target) == .int_not_coercible); - - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .f32_type, .f32_type, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .f64_type, .f32_type, true, builtin.target) == .no_match); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .f32_type, .f64_type, true, builtin.target) == .no_match); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .u32_type, .f32_type, true, builtin.target) == .no_match); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .f32_type, .u32_type, true, builtin.target) == .no_match); + try expect(try ip.coerceInMemoryAllowed(arena, .u32_type, .u32_type, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, .u32_type, .u16_type, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, .u16_type, .u32_type, true, builtin.target) == .int_not_coercible); + try expect(try ip.coerceInMemoryAllowed(arena, .i32_type, .u32_type, true, builtin.target) == .int_not_coercible); + try expect(try ip.coerceInMemoryAllowed(arena, .u32_type, .i32_type, true, builtin.target) == .int_not_coercible); + try expect(try ip.coerceInMemoryAllowed(arena, .u32_type, .i16_type, true, builtin.target) == .int_not_coercible); + + try expect(try ip.coerceInMemoryAllowed(arena, .f32_type, .f32_type, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, .f64_type, .f32_type, true, builtin.target) == .no_match); + try expect(try ip.coerceInMemoryAllowed(arena, .f32_type, .f64_type, true, builtin.target) == .no_match); + try expect(try ip.coerceInMemoryAllowed(arena, .u32_type, .f32_type, true, builtin.target) == .no_match); + try expect(try ip.coerceInMemoryAllowed(arena, .f32_type, .u32_type, true, builtin.target) == .no_match); } test "coerceInMemoryAllowed error set" { const gpa = std.testing.allocator; + const io = std.testing.io; + + var ip: InternPool = try .init(io, gpa); + defer ip.deinit(gpa); var arena_allocator: std.heap.ArenaAllocator = .init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - var ip: InternPool = try .init(gpa); - defer ip.deinit(gpa); - - const foo_name = try ip.string_pool.getOrPutString(gpa, "foo"); - const bar_name = try ip.string_pool.getOrPutString(gpa, "bar"); - const baz_name = try ip.string_pool.getOrPutString(gpa, "baz"); + const foo_name = try ip.string_pool.getOrPutString(io, gpa, "foo"); + const bar_name = try ip.string_pool.getOrPutString(io, gpa, "bar"); + const baz_name = try ip.string_pool.getOrPutString(io, gpa, "baz"); - const foo_bar_baz_set = try ip.get(gpa, .{ .error_set_type = .{ + const foo_bar_baz_set = try ip.get(.{ .error_set_type = .{ .owner_decl = .none, - .names = try ip.getStringSlice(gpa, &.{ baz_name, bar_name, foo_name }), + .names = try ip.getStringSlice(&.{ baz_name, bar_name, foo_name }), } }); - const foo_bar_set = try ip.get(gpa, .{ .error_set_type = .{ + const foo_bar_set = try ip.get(.{ .error_set_type = .{ .owner_decl = .none, - .names = try ip.getStringSlice(gpa, &.{ foo_name, bar_name }), + .names = try ip.getStringSlice(&.{ foo_name, bar_name }), } }); - const foo_set = try ip.get(gpa, .{ .error_set_type = .{ + const foo_set = try ip.get(.{ .error_set_type = .{ .owner_decl = .none, - .names = try ip.getStringSlice(gpa, &.{foo_name}), + .names = try ip.getStringSlice(&.{foo_name}), } }); - const empty_set = try ip.get(gpa, .{ .error_set_type = .{ + const empty_set = try ip.get(.{ .error_set_type = .{ .owner_decl = .none, .names = StringSlice.empty, } }); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .anyerror_type, foo_bar_baz_set, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .anyerror_type, foo_bar_set, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .anyerror_type, foo_set, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .anyerror_type, empty_set, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, .anyerror_type, .anyerror_type, true, builtin.target) == .ok); - - try expect(try ip.coerceInMemoryAllowed(gpa, arena, foo_bar_baz_set, .anyerror_type, true, builtin.target) == .from_anyerror); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, empty_set, .anyerror_type, true, builtin.target) == .from_anyerror); - - try expect(try ip.coerceInMemoryAllowed(gpa, arena, foo_bar_baz_set, foo_bar_baz_set, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, foo_bar_baz_set, foo_bar_set, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, foo_bar_baz_set, foo_set, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, foo_bar_baz_set, empty_set, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, foo_bar_set, foo_bar_set, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, foo_bar_set, foo_set, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, foo_bar_set, empty_set, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, foo_set, foo_set, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, foo_set, empty_set, true, builtin.target) == .ok); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, empty_set, empty_set, true, builtin.target) == .ok); - - try expect(try ip.coerceInMemoryAllowed(gpa, arena, empty_set, foo_set, true, builtin.target) == .missing_error); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, empty_set, foo_bar_baz_set, true, builtin.target) == .missing_error); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, foo_set, foo_bar_set, true, builtin.target) == .missing_error); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, foo_set, foo_bar_baz_set, true, builtin.target) == .missing_error); - try expect(try ip.coerceInMemoryAllowed(gpa, arena, foo_bar_set, foo_bar_baz_set, true, builtin.target) == .missing_error); + try expect(try ip.coerceInMemoryAllowed(arena, .anyerror_type, foo_bar_baz_set, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, .anyerror_type, foo_bar_set, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, .anyerror_type, foo_set, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, .anyerror_type, empty_set, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, .anyerror_type, .anyerror_type, true, builtin.target) == .ok); + + try expect(try ip.coerceInMemoryAllowed(arena, foo_bar_baz_set, .anyerror_type, true, builtin.target) == .from_anyerror); + try expect(try ip.coerceInMemoryAllowed(arena, empty_set, .anyerror_type, true, builtin.target) == .from_anyerror); + + try expect(try ip.coerceInMemoryAllowed(arena, foo_bar_baz_set, foo_bar_baz_set, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, foo_bar_baz_set, foo_bar_set, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, foo_bar_baz_set, foo_set, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, foo_bar_baz_set, empty_set, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, foo_bar_set, foo_bar_set, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, foo_bar_set, foo_set, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, foo_bar_set, empty_set, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, foo_set, foo_set, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, foo_set, empty_set, true, builtin.target) == .ok); + try expect(try ip.coerceInMemoryAllowed(arena, empty_set, empty_set, true, builtin.target) == .ok); + + try expect(try ip.coerceInMemoryAllowed(arena, empty_set, foo_set, true, builtin.target) == .missing_error); + try expect(try ip.coerceInMemoryAllowed(arena, empty_set, foo_bar_baz_set, true, builtin.target) == .missing_error); + try expect(try ip.coerceInMemoryAllowed(arena, foo_set, foo_bar_set, true, builtin.target) == .missing_error); + try expect(try ip.coerceInMemoryAllowed(arena, foo_set, foo_bar_baz_set, true, builtin.target) == .missing_error); + try expect(try ip.coerceInMemoryAllowed(arena, foo_bar_set, foo_bar_baz_set, true, builtin.target) == .missing_error); } test "resolvePeerTypes" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - try expect(.noreturn_type == try ip.resolvePeerTypes(gpa, &.{}, builtin.target)); - try expect(.type_type == try ip.resolvePeerTypes(gpa, &.{.type_type}, builtin.target)); + try expect(.noreturn_type == try ip.resolvePeerTypes(&.{}, builtin.target)); + try expect(.type_type == try ip.resolvePeerTypes(&.{.type_type}, builtin.target)); try ip.testResolvePeerTypes(.bool_type, .bool_type, .bool_type); try ip.testResolvePeerTypes(.bool_type, .noreturn_type, .bool_type); @@ -4997,8 +5003,9 @@ test "resolvePeerTypes" { test "resolvePeerTypes integers and floats" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); try ip.testResolvePeerTypes(.i16_type, .i16_type, .i16_type); @@ -5082,12 +5089,13 @@ test "resolvePeerTypes integers and floats" { test "resolvePeerTypes optionals" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"?u32" = try ip.get(gpa, .{ .optional_type = .{ .payload_type = .u32_type } }); - const @"?bool" = try ip.get(gpa, .{ .optional_type = .{ .payload_type = .bool_type } }); + const @"?u32" = try ip.get(.{ .optional_type = .{ .payload_type = .u32_type } }); + const @"?bool" = try ip.get(.{ .optional_type = .{ .payload_type = .bool_type } }); try ip.testResolvePeerTypes(.u32_type, .null_type, @"?u32"); try ip.testResolvePeerTypes(.bool_type, .null_type, @"?bool"); @@ -5095,44 +5103,45 @@ test "resolvePeerTypes optionals" { test "resolvePeerTypes pointers" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"*u32" = try ip.get(gpa, .{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .one } } }); - const @"[*]u32" = try ip.get(gpa, .{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .many } } }); - const @"[]u32" = try ip.get(gpa, .{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .slice } } }); - const @"[*c]u32" = try ip.get(gpa, .{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .c } } }); + const @"*u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .one } } }); + const @"[*]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .many } } }); + const @"[]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .slice } } }); + const @"[*c]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .c } } }); - const @"?*u32" = try ip.get(gpa, .{ .optional_type = .{ .payload_type = @"*u32" } }); - const @"?[*]u32" = try ip.get(gpa, .{ .optional_type = .{ .payload_type = @"[*]u32" } }); - const @"?[]u32" = try ip.get(gpa, .{ .optional_type = .{ .payload_type = @"[]u32" } }); + const @"?*u32" = try ip.get(.{ .optional_type = .{ .payload_type = @"*u32" } }); + const @"?[*]u32" = try ip.get(.{ .optional_type = .{ .payload_type = @"[*]u32" } }); + const @"?[]u32" = try ip.get(.{ .optional_type = .{ .payload_type = @"[]u32" } }); - const @"**u32" = try ip.get(gpa, .{ .pointer_type = .{ .elem_type = @"*u32", .flags = .{ .size = .one } } }); - const @"*[*]u32" = try ip.get(gpa, .{ .pointer_type = .{ .elem_type = @"[*]u32", .flags = .{ .size = .one } } }); - const @"*[]u32" = try ip.get(gpa, .{ .pointer_type = .{ .elem_type = @"[]u32", .flags = .{ .size = .one } } }); - const @"*[*c]u32" = try ip.get(gpa, .{ .pointer_type = .{ .elem_type = @"[*c]u32", .flags = .{ .size = .one } } }); + const @"**u32" = try ip.get(.{ .pointer_type = .{ .elem_type = @"*u32", .flags = .{ .size = .one } } }); + const @"*[*]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = @"[*]u32", .flags = .{ .size = .one } } }); + const @"*[]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = @"[]u32", .flags = .{ .size = .one } } }); + const @"*[*c]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = @"[*c]u32", .flags = .{ .size = .one } } }); - const @"?*[*]u32" = try ip.get(gpa, .{ .optional_type = .{ .payload_type = @"*[*]u32" } }); - const @"?*[]u32" = try ip.get(gpa, .{ .optional_type = .{ .payload_type = @"*[]u32" } }); + const @"?*[*]u32" = try ip.get(.{ .optional_type = .{ .payload_type = @"*[*]u32" } }); + const @"?*[]u32" = try ip.get(.{ .optional_type = .{ .payload_type = @"*[]u32" } }); - const @"[1]u32" = try ip.get(gpa, .{ .array_type = .{ .len = 1, .child = .u32_type, .sentinel = .none } }); - const @"[2]u32" = try ip.get(gpa, .{ .array_type = .{ .len = 2, .child = .u32_type, .sentinel = .none } }); + const @"[1]u32" = try ip.get(.{ .array_type = .{ .len = 1, .child = .u32_type, .sentinel = .none } }); + const @"[2]u32" = try ip.get(.{ .array_type = .{ .len = 2, .child = .u32_type, .sentinel = .none } }); - const @"*[1]u32" = try ip.get(gpa, .{ .pointer_type = .{ .elem_type = @"[1]u32", .flags = .{ .size = .one } } }); - const @"*[2]u32" = try ip.get(gpa, .{ .pointer_type = .{ .elem_type = @"[2]u32", .flags = .{ .size = .one } } }); + const @"*[1]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = @"[1]u32", .flags = .{ .size = .one } } }); + const @"*[2]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = @"[2]u32", .flags = .{ .size = .one } } }); - const @"?*[1]u32" = try ip.get(gpa, .{ .optional_type = .{ .payload_type = @"*[1]u32" } }); - const @"?*[2]u32" = try ip.get(gpa, .{ .optional_type = .{ .payload_type = @"*[2]u32" } }); + const @"?*[1]u32" = try ip.get(.{ .optional_type = .{ .payload_type = @"*[1]u32" } }); + const @"?*[2]u32" = try ip.get(.{ .optional_type = .{ .payload_type = @"*[2]u32" } }); - const @"*const u32" = try ip.get(gpa, .{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .one, .is_const = true } } }); - const @"[*]const u32" = try ip.get(gpa, .{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .many, .is_const = true } } }); - const @"[]const u32" = try ip.get(gpa, .{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .slice, .is_const = true } } }); - const @"[*c]const u32" = try ip.get(gpa, .{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .c, .is_const = true } } }); + const @"*const u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .one, .is_const = true } } }); + const @"[*]const u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .many, .is_const = true } } }); + const @"[]const u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .slice, .is_const = true } } }); + const @"[*c]const u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .c, .is_const = true } } }); - const @"?*const u32" = try ip.get(gpa, .{ .optional_type = .{ .payload_type = @"*const u32" } }); - const @"?[*]const u32" = try ip.get(gpa, .{ .optional_type = .{ .payload_type = @"[*]const u32" } }); - const @"?[]const u32" = try ip.get(gpa, .{ .optional_type = .{ .payload_type = @"[]const u32" } }); + const @"?*const u32" = try ip.get(.{ .optional_type = .{ .payload_type = @"*const u32" } }); + const @"?[*]const u32" = try ip.get(.{ .optional_type = .{ .payload_type = @"[*]const u32" } }); + const @"?[]const u32" = try ip.get(.{ .optional_type = .{ .payload_type = @"[]const u32" } }); _ = @"**u32"; _ = @"*[*c]u32"; @@ -5188,15 +5197,16 @@ test "resolvePeerTypes pointers" { test "resolvePeerTypes function pointers" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"*u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"*u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .one }, } }); - const @"*const u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"*const u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .one, @@ -5204,13 +5214,13 @@ test "resolvePeerTypes function pointers" { }, } }); - const @"fn(*u32) void" = try ip.get(gpa, .{ .function_type = .{ - .args = try ip.getIndexSlice(gpa, &.{@"*u32"}), + const @"fn(*u32) void" = try ip.get(.{ .function_type = .{ + .args = try ip.getIndexSlice(&.{@"*u32"}), .return_type = .void_type, } }); - const @"fn(*const u32) void" = try ip.get(gpa, .{ .function_type = .{ - .args = try ip.getIndexSlice(gpa, &.{@"*const u32"}), + const @"fn(*const u32) void" = try ip.get(.{ .function_type = .{ + .args = try ip.getIndexSlice(&.{@"*const u32"}), .return_type = .void_type, } }); @@ -5220,31 +5230,32 @@ test "resolvePeerTypes function pointers" { test "resolvePeerTypes error sets" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const foo_name = try ip.string_pool.getOrPutString(gpa, "foo"); - const bar_name = try ip.string_pool.getOrPutString(gpa, "bar"); + const foo_name = try ip.string_pool.getOrPutString(io, gpa, "foo"); + const bar_name = try ip.string_pool.getOrPutString(io, gpa, "bar"); - const @"error{foo}" = try ip.get(gpa, .{ .error_set_type = .{ + const @"error{foo}" = try ip.get(.{ .error_set_type = .{ .owner_decl = .none, - .names = try ip.getStringSlice(gpa, &.{foo_name}), + .names = try ip.getStringSlice(&.{foo_name}), } }); - const @"error{bar}" = try ip.get(gpa, .{ .error_set_type = .{ + const @"error{bar}" = try ip.get(.{ .error_set_type = .{ .owner_decl = .none, - .names = try ip.getStringSlice(gpa, &.{bar_name}), + .names = try ip.getStringSlice(&.{bar_name}), } }); - const @"error{foo,bar}" = try ip.get(gpa, .{ .error_set_type = .{ + const @"error{foo,bar}" = try ip.get(.{ .error_set_type = .{ .owner_decl = .none, - .names = try ip.getStringSlice(gpa, &.{ foo_name, bar_name }), + .names = try ip.getStringSlice(&.{ foo_name, bar_name }), } }); - const @"error{bar,foo}" = try ip.get(gpa, .{ .error_set_type = .{ + const @"error{bar,foo}" = try ip.get(.{ .error_set_type = .{ .owner_decl = .none, - .names = try ip.getStringSlice(gpa, &.{ bar_name, foo_name }), + .names = try ip.getStringSlice(&.{ bar_name, foo_name }), } }); try ip.testResolvePeerTypesInOrder(@"error{foo}", @"error{bar}", @"error{foo,bar}"); @@ -5257,7 +5268,7 @@ fn testResolvePeerTypes(ip: *InternPool, a: Index, b: Index, expected: Index) !v } fn testResolvePeerTypesInOrder(ip: *InternPool, lhs: Index, rhs: Index, expected: Index) !void { - const actual = try resolvePeerTypes(ip, std.testing.allocator, &.{ lhs, rhs }, builtin.target); + const actual = try resolvePeerTypes(ip, &.{ lhs, rhs }, builtin.target); if (expected == actual) return; std.debug.print("expected `{f}`, found `{f}`\n", .{ expected.fmtDebug(ip), actual.fmtDebug(ip) }); return error.TestExpectedEqual; @@ -5265,14 +5276,15 @@ fn testResolvePeerTypesInOrder(ip: *InternPool, lhs: Index, rhs: Index, expected test "coerce int" { const gpa = std.testing.allocator; + const io = std.testing.io; - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"as(comptime_int, 1)" = try ip.get(gpa, .{ .int_u64_value = .{ .ty = .comptime_int_type, .int = 1 } }); - const @"as(u1, 1)" = try ip.get(gpa, .{ .int_u64_value = .{ .ty = .u1_type, .int = 1 } }); - const @"as(comptime_int, -1)" = try ip.get(gpa, .{ .int_i64_value = .{ .ty = .comptime_int_type, .int = -1 } }); - const @"as(i64, 32000)" = try ip.get(gpa, .{ .int_i64_value = .{ .ty = .i64_type, .int = 32000 } }); + const @"as(comptime_int, 1)" = try ip.get(.{ .int_u64_value = .{ .ty = .comptime_int_type, .int = 1 } }); + const @"as(u1, 1)" = try ip.get(.{ .int_u64_value = .{ .ty = .u1_type, .int = 1 } }); + const @"as(comptime_int, -1)" = try ip.get(.{ .int_i64_value = .{ .ty = .comptime_int_type, .int = -1 } }); + const @"as(i64, 32000)" = try ip.get(.{ .int_i64_value = .{ .ty = .i64_type, .int = 32000 } }); try ip.testCoerce(.u1_type, @"as(comptime_int, 1)", @"as(u1, 1)"); try ip.testCoerce(.u1_type, @"as(comptime_int, -1)", .none); @@ -5288,7 +5300,7 @@ fn testCoerce(ip: *InternPool, dest_ty: Index, inst: Index, expected: Index) !vo const arena = arena_allocator.allocator(); var err_msg: ErrorMsg = undefined; - const actual = try ip.coerce(gpa, arena, dest_ty, inst, builtin.target, &err_msg); + const actual = try ip.coerce(arena, dest_ty, inst, builtin.target, &err_msg); if (expected == actual) return; std.debug.print( diff --git a/src/analyser/completions.zig b/src/analyser/completions.zig index 272a85029..7fd627af3 100644 --- a/src/analyser/completions.zig +++ b/src/analyser/completions.zig @@ -61,7 +61,7 @@ pub fn dotCompletions( try completions.ensureUnusedCapacity(arena, enum_info.fields.count()); for (enum_info.fields.keys()) |name| { completions.appendAssumeCapacity(.{ - .label = try std.fmt.allocPrint(arena, "{f}", .{name.fmt(&ip.string_pool)}), + .label = try std.fmt.allocPrint(arena, "{f}", .{name.fmt(ip.io, &ip.string_pool)}), .kind = .EnumMember, // include field.val? }); @@ -123,7 +123,7 @@ pub fn dotCompletions( .label = try std.fmt.allocPrint(arena, "{f}", .{ip.fmtId(name)}), .kind = .Field, .detail = try std.fmt.allocPrint(arena, "{f}: {f}", .{ - name.fmt(&ip.string_pool), + name.fmt(ip.io, &ip.string_pool), fmtFieldDetail(ip, field), }), }); @@ -231,7 +231,8 @@ pub fn fmtFieldDetail(ip: *InternPool, field: InternPool.Struct.Field) std.fmt.A test "dotCompletions - primitives" { const gpa = std.testing.allocator; - var ip: InternPool = try .init(gpa); + const io = std.testing.io; + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); try testCompletion(&ip, .bool_type, &.{}); @@ -243,11 +244,12 @@ test "dotCompletions - primitives" { test "dotCompletions - optional types" { const gpa = std.testing.allocator; - var ip: InternPool = try .init(gpa); + const io = std.testing.io; + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"?u32" = try ip.get(gpa, .{ .optional_type = .{ .payload_type = .u32_type } }); - try testCompletion(&ip, try ip.getUnknown(gpa, @"?u32"), &.{ + const @"?u32" = try ip.get(.{ .optional_type = .{ .payload_type = .u32_type } }); + try testCompletion(&ip, try ip.getUnknown(@"?u32"), &.{ .{ .label = "?", .kind = .Operator, @@ -258,20 +260,21 @@ test "dotCompletions - optional types" { test "dotCompletions - array types" { const gpa = std.testing.allocator; - var ip: InternPool = try .init(gpa); + const io = std.testing.io; + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"[3]u32" = try ip.get(gpa, .{ .array_type = .{ .child = .u32_type, .len = 3 } }); - const @"[1]u8" = try ip.get(gpa, .{ .array_type = .{ .child = .u8_type, .len = 1 } }); + const @"[3]u32" = try ip.get(.{ .array_type = .{ .child = .u32_type, .len = 3 } }); + const @"[1]u8" = try ip.get(.{ .array_type = .{ .child = .u8_type, .len = 1 } }); - try testCompletion(&ip, try ip.getUnknown(gpa, @"[3]u32"), &.{ + try testCompletion(&ip, try ip.getUnknown(@"[3]u32"), &.{ .{ .label = "len", .kind = .Field, .detail = "usize = 3", }, }); - try testCompletion(&ip, try ip.getUnknown(gpa, @"[1]u8"), &.{ + try testCompletion(&ip, try ip.getUnknown(@"[1]u8"), &.{ .{ .label = "len", .kind = .Field, @@ -282,43 +285,44 @@ test "dotCompletions - array types" { test "dotCompletions - pointer types" { const gpa = std.testing.allocator; - var ip: InternPool = try .init(gpa); + const io = std.testing.io; + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"*u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"*u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .one, }, } }); - const @"[]u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"[]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .slice, }, } }); - const @"[]const u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"[]const u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .slice, .is_const = true, }, } }); - const @"[*c]u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"[*c]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .c, }, } }); - try testCompletion(&ip, try ip.getUnknown(gpa, @"*u32"), &.{ + try testCompletion(&ip, try ip.getUnknown(@"*u32"), &.{ .{ .label = "*", .kind = .Operator, .detail = "u32", }, }); - try testCompletion(&ip, try ip.getUnknown(gpa, @"[]u32"), &.{ + try testCompletion(&ip, try ip.getUnknown(@"[]u32"), &.{ .{ .label = "ptr", .kind = .Field, @@ -330,7 +334,7 @@ test "dotCompletions - pointer types" { .detail = "len: usize", }, }); - try testCompletion(&ip, try ip.getUnknown(gpa, @"[]const u32"), &.{ + try testCompletion(&ip, try ip.getUnknown(@"[]const u32"), &.{ .{ .label = "ptr", .kind = .Field, @@ -342,7 +346,7 @@ test "dotCompletions - pointer types" { .detail = "len: usize", }, }); - try testCompletion(&ip, try ip.getUnknown(gpa, @"[*c]u32"), &.{ + try testCompletion(&ip, try ip.getUnknown(@"[*c]u32"), &.{ .{ .label = "*", .kind = .Operator, @@ -358,42 +362,43 @@ test "dotCompletions - pointer types" { test "dotCompletions - single pointer indirection" { const gpa = std.testing.allocator; - var ip: InternPool = try .init(gpa); + const io = std.testing.io; + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"[1]u32" = try ip.get(gpa, .{ .array_type = .{ .child = .u32_type, .len = 1 } }); - const @"*[1]u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"[1]u32" = try ip.get(.{ .array_type = .{ .child = .u32_type, .len = 1 } }); + const @"*[1]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = @"[1]u32", .flags = .{ .size = .one, }, } }); - const @"[*c]u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"[*c]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = .u32_type, .flags = .{ .size = .c, }, } }); - const @"**[1]u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"**[1]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = @"*[1]u32", .flags = .{ .size = .one, }, } }); - const @"[*][1]u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"[*][1]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = @"[1]u32", .flags = .{ .size = .many, }, } }); - const @"*[*c]u32" = try ip.get(gpa, .{ .pointer_type = .{ + const @"*[*c]u32" = try ip.get(.{ .pointer_type = .{ .elem_type = @"[*c]u32", .flags = .{ .size = .one, }, } }); - try testCompletion(&ip, try ip.getUnknown(gpa, @"*[1]u32"), &.{ + try testCompletion(&ip, try ip.getUnknown(@"*[1]u32"), &.{ .{ .label = "*", .kind = .Operator, @@ -405,16 +410,16 @@ test "dotCompletions - single pointer indirection" { .detail = "usize = 1", }, }); - try testCompletion(&ip, try ip.getUnknown(gpa, @"**[1]u32"), &.{ + try testCompletion(&ip, try ip.getUnknown(@"**[1]u32"), &.{ .{ .label = "*", .kind = .Operator, .detail = "*[1]u32", }, }); - try testCompletion(&ip, try ip.getUnknown(gpa, @"[*][1]u32"), &.{}); + try testCompletion(&ip, try ip.getUnknown(@"[*][1]u32"), &.{}); - try testCompletion(&ip, try ip.getUnknown(gpa, @"*[*c]u32"), &.{ + try testCompletion(&ip, try ip.getUnknown(@"*[*c]u32"), &.{ .{ .label = "*", .kind = .Operator, diff --git a/src/analyser/degibberish.zig b/src/analyser/degibberish.zig index ba7f9fe30..3daf9a122 100644 --- a/src/analyser/degibberish.zig +++ b/src/analyser/degibberish.zig @@ -150,7 +150,8 @@ fn formatDegibberish(data: FormatDegibberishData, writer: *std.Io.Writer) std.Io test "degibberish - simple types" { const gpa = std.testing.allocator; - var ip: InternPool = try .init(gpa); + const io = std.testing.io; + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); try std.testing.expectFmt("u32", "{f}", .{fmtDegibberish(&ip, .u32_type)}); @@ -159,7 +160,8 @@ test "degibberish - simple types" { test "degibberish - pointer types" { const gpa = std.testing.allocator; - var ip: InternPool = try .init(gpa); + const io = std.testing.io; + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); try std.testing.expectFmt("many-item pointer to u8", "{f}", .{fmtDegibberish(&ip, .manyptr_u8_type)}); @@ -172,11 +174,12 @@ test "degibberish - pointer types" { test "degibberish - array types" { const gpa = std.testing.allocator; - var ip: InternPool = try .init(gpa); + const io = std.testing.io; + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"[3:0]u8" = try ip.get(gpa, .{ .array_type = .{ .len = 3, .child = .u8_type, .sentinel = .zero_u8 } }); - const @"[0]u32" = try ip.get(gpa, .{ .array_type = .{ .len = 0, .child = .u32_type } }); + const @"[3:0]u8" = try ip.get(.{ .array_type = .{ .len = 3, .child = .u8_type, .sentinel = .zero_u8 } }); + const @"[0]u32" = try ip.get(.{ .array_type = .{ .len = 0, .child = .u32_type } }); try std.testing.expectFmt("0 terminated array 3 of u8", "{f}", .{fmtDegibberish(&ip, @"[3:0]u8")}); try std.testing.expectFmt("array 0 of u32", "{f}", .{fmtDegibberish(&ip, @"[0]u32")}); @@ -184,29 +187,31 @@ test "degibberish - array types" { test "degibberish - optional types" { const gpa = std.testing.allocator; - var ip: InternPool = try .init(gpa); + const io = std.testing.io; + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"?u32" = try ip.get(gpa, .{ .optional_type = .{ .payload_type = .u32_type } }); + const @"?u32" = try ip.get(.{ .optional_type = .{ .payload_type = .u32_type } }); try std.testing.expectFmt("optional of u32", "{f}", .{fmtDegibberish(&ip, @"?u32")}); } test "degibberish - error union types" { const gpa = std.testing.allocator; - var ip: InternPool = try .init(gpa); + const io = std.testing.io; + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const foo_string = try ip.string_pool.getOrPutString(gpa, "foo"); - const bar_string = try ip.string_pool.getOrPutString(gpa, "bar"); - const baz_string = try ip.string_pool.getOrPutString(gpa, "baz"); + const foo_string = try ip.string_pool.getOrPutString(io, gpa, "foo"); + const bar_string = try ip.string_pool.getOrPutString(io, gpa, "bar"); + const baz_string = try ip.string_pool.getOrPutString(io, gpa, "baz"); - const @"error{foo,bar,baz}" = try ip.get(gpa, .{ .error_set_type = .{ - .names = try ip.getStringSlice(gpa, &.{ foo_string, bar_string, baz_string }), + const @"error{foo,bar,baz}" = try ip.get(.{ .error_set_type = .{ + .names = try ip.getStringSlice(&.{ foo_string, bar_string, baz_string }), .owner_decl = .none, } }); - const @"error{foo,bar,baz}!u32" = try ip.get(gpa, .{ .error_union_type = .{ + const @"error{foo,bar,baz}!u32" = try ip.get(.{ .error_union_type = .{ .error_set_type = @"error{foo,bar,baz}", .payload_type = .u32_type, } }); @@ -216,15 +221,16 @@ test "degibberish - error union types" { test "degibberish - error set types" { const gpa = std.testing.allocator; - var ip: InternPool = try .init(gpa); + const io = std.testing.io; + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const foo_string = try ip.string_pool.getOrPutString(gpa, "foo"); - const bar_string = try ip.string_pool.getOrPutString(gpa, "bar"); - const baz_string = try ip.string_pool.getOrPutString(gpa, "baz"); + const foo_string = try ip.string_pool.getOrPutString(io, gpa, "foo"); + const bar_string = try ip.string_pool.getOrPutString(io, gpa, "bar"); + const baz_string = try ip.string_pool.getOrPutString(io, gpa, "baz"); - const @"error{foo,bar,baz}" = try ip.get(gpa, .{ .error_set_type = .{ - .names = try ip.getStringSlice(gpa, &.{ foo_string, bar_string, baz_string }), + const @"error{foo,bar,baz}" = try ip.get(.{ .error_set_type = .{ + .names = try ip.getStringSlice(&.{ foo_string, bar_string, baz_string }), .owner_decl = .none, } }); @@ -233,11 +239,12 @@ test "degibberish - error set types" { test "degibberish - function types" { const gpa = std.testing.allocator; - var ip: InternPool = try .init(gpa); + const io = std.testing.io; + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"fn(u32, void) type" = try ip.get(gpa, .{ .function_type = .{ - .args = try ip.getIndexSlice(gpa, &.{ .u32_type, .void_type }), + const @"fn(u32, void) type" = try ip.get(.{ .function_type = .{ + .args = try ip.getIndexSlice(&.{ .u32_type, .void_type }), .return_type = .type_type, } }); @@ -248,12 +255,13 @@ test "degibberish - function types" { test "degibberish - tuple types" { const gpa = std.testing.allocator; - var ip: InternPool = try .init(gpa); + const io = std.testing.io; + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"struct{u32, comptime_float, c_int}" = try ip.get(gpa, .{ .tuple_type = .{ - .types = try ip.getIndexSlice(gpa, &.{ .u32_type, .comptime_float_type, .c_int_type }), - .values = try ip.getIndexSlice(gpa, &.{ .none, .none, .none }), + const @"struct{u32, comptime_float, c_int}" = try ip.get(.{ .tuple_type = .{ + .types = try ip.getIndexSlice(&.{ .u32_type, .comptime_float_type, .c_int_type }), + .values = try ip.getIndexSlice(&.{ .none, .none, .none }), } }); try std.testing.expectFmt("tuple of (u32, comptime_float, c_int)", "{f}", .{fmtDegibberish(&ip, @"struct{u32, comptime_float, c_int}")}); @@ -261,11 +269,12 @@ test "degibberish - tuple types" { test "degibberish - vector types" { const gpa = std.testing.allocator; - var ip: InternPool = try .init(gpa); + const io = std.testing.io; + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"@Vector(3, u8)" = try ip.get(gpa, .{ .vector_type = .{ .len = 3, .child = .u8_type } }); - const @"@Vector(0, u32)" = try ip.get(gpa, .{ .vector_type = .{ .len = 0, .child = .u32_type } }); + const @"@Vector(3, u8)" = try ip.get(.{ .vector_type = .{ .len = 3, .child = .u8_type } }); + const @"@Vector(0, u32)" = try ip.get(.{ .vector_type = .{ .len = 0, .child = .u32_type } }); try std.testing.expectFmt("vector 3 of u8", "{f}", .{fmtDegibberish(&ip, @"@Vector(3, u8)")}); try std.testing.expectFmt("vector 0 of u32", "{f}", .{fmtDegibberish(&ip, @"@Vector(0, u32)")}); @@ -273,9 +282,10 @@ test "degibberish - vector types" { test "degibberish - anyframe types" { const gpa = std.testing.allocator; - var ip: InternPool = try .init(gpa); + const io = std.testing.io; + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); - const @"anyframe->u32" = try ip.get(gpa, .{ .anyframe_type = .{ .child = .u32_type } }); + const @"anyframe->u32" = try ip.get(.{ .anyframe_type = .{ .child = .u32_type } }); try std.testing.expectFmt("function frame returning u32", "{f}", .{fmtDegibberish(&ip, @"anyframe->u32")}); } diff --git a/src/analyser/error_msg.zig b/src/analyser/error_msg.zig index 4b9afb166..e62e74d84 100644 --- a/src/analyser/error_msg.zig +++ b/src/analyser/error_msg.zig @@ -124,7 +124,7 @@ pub const ErrorMsg = union(enum) { ), .duplicate_struct_field => |info| try writer.print( "duplicate struct field: '{f}'", - .{info.name.fmt(&ip.string_pool)}, + .{info.name.fmt(ip.io, &ip.string_pool)}, ), .unknown_field => |info| { const accessed_ty = ip.typeOf(info.accessed); diff --git a/src/analyser/string_pool.zig b/src/analyser/string_pool.zig index 084b0da54..53843dded 100644 --- a/src/analyser/string_pool.zig +++ b/src/analyser/string_pool.zig @@ -8,12 +8,12 @@ pub const Config = struct { thread_safe: bool = !builtin.single_threaded, /// What type of mutex you'd like to use, for thread safety. - /// when specified, the mutex type must have the same shape as `std.Thread.Mutex` and + /// when specified, the mutex type must have the same shape as `std.Io.Mutex` and /// `DummyMutex`, and have no required fields. Specifying this field causes /// the `thread_safe` field to be ignored. /// /// when null (default): - /// * the mutex type defaults to `std.Thread.Mutex` when thread_safe is enabled. + /// * the mutex type defaults to `std.Io.Mutex` when thread_safe is enabled. /// * the mutex type defaults to `DummyMutex` otherwise. MutexType: ?type = null, }; @@ -37,8 +37,8 @@ pub fn StringPool(comptime config: Config) type { return @enumFromInt(@intFromEnum(self)); } - pub fn fmt(self: String, pool: *Pool) std.fmt.Alt(FormatContext, print) { - return .{ .data = .{ .string = self, .pool = pool } }; + pub fn fmt(self: String, io: std.Io, pool: *Pool) std.fmt.Alt(FormatContext, print) { + return .{ .data = .{ .string = self, .io = io, .pool = pool } }; } }; @@ -53,14 +53,14 @@ pub fn StringPool(comptime config: Config) type { }; /// Asserts that `str` contains no null bytes. - pub fn getString(pool: *Pool, str: []const u8) ?String { + pub fn getString(pool: *Pool, io: std.Io, str: []const u8) ?String { assert(std.mem.findScalar(u8, str, 0) == null); // precompute the hash before acquiring the lock const precomputed_key_hash = std.hash_map.hashString(str); - pool.mutex.lock(); - defer pool.mutex.unlock(); + pool.mutex.lockUncancelable(io); + defer pool.mutex.unlock(io); const adapter: PrecomputedStringIndexAdapter = .{ .bytes = &pool.bytes, @@ -74,7 +74,7 @@ pub fn StringPool(comptime config: Config) type { /// Asserts that `str` contains no null bytes. /// Returns `error.OutOfMemory` if adding this new string would increase the amount of allocated bytes above std.math.maxInt(u32) - pub fn getOrPutString(pool: *Pool, allocator: Allocator, str: []const u8) error{OutOfMemory}!String { + pub fn getOrPutString(pool: *Pool, io: std.Io, allocator: Allocator, str: []const u8) error{OutOfMemory}!String { assert(std.mem.findScalar(u8, str, 0) == null); const start_index = std.math.cast(u32, pool.bytes.items.len) orelse return error.OutOfMemory; @@ -82,8 +82,8 @@ pub fn StringPool(comptime config: Config) type { // precompute the hash before acquiring the lock const precomputed_key_hash = std.hash_map.hashString(str); - pool.mutex.lock(); - defer pool.mutex.unlock(); + pool.mutex.lockUncancelable(io); + defer pool.mutex.unlock(io); const adapter: PrecomputedStringIndexAdapter = .{ .bytes = &pool.bytes, @@ -113,18 +113,18 @@ pub fn StringPool(comptime config: Config) type { } /// Caller owns the memory. - pub fn stringToSliceAlloc(pool: *Pool, allocator: Allocator, index: String) Allocator.Error![]const u8 { - pool.mutex.lock(); - defer pool.mutex.unlock(); + pub fn stringToSliceAlloc(pool: *Pool, io: std.Io, allocator: Allocator, index: String) Allocator.Error![]const u8 { + pool.mutex.lockUncancelable(io); + defer pool.mutex.unlock(io); const string_bytes: [*:0]u8 = @ptrCast(pool.bytes.items.ptr); const start = @intFromEnum(index); return try allocator.dupe(u8, std.mem.sliceTo(string_bytes + start, 0)); } /// Caller owns the memory. - pub fn stringToSliceAllocZ(pool: *Pool, allocator: Allocator, index: String) Allocator.Error![:0]const u8 { - pool.mutex.lock(); - defer pool.mutex.unlock(); + pub fn stringToSliceAllocZ(pool: *Pool, io: std.Io, allocator: Allocator, index: String) Allocator.Error![:0]const u8 { + pool.mutex.lockUncancelable(io); + defer pool.mutex.unlock(io); const string_bytes: [*:0]u8 = @ptrCast(pool.bytes.items.ptr); const start = @intFromEnum(index); return try allocator.dupeZ(u8, std.mem.sliceTo(string_bytes + start, 0)); @@ -137,9 +137,9 @@ pub fn StringPool(comptime config: Config) type { pub const LockedString = struct { slice: [:0]const u8, - pub fn release(locked_string: LockedString, pool: *Pool) void { + pub fn release(locked_string: LockedString, io: std.Io, pool: *Pool) void { _ = locked_string; - pool.mutex.unlock(); + pool.mutex.unlock(io); } }; @@ -147,8 +147,8 @@ pub fn StringPool(comptime config: Config) type { /// equal strings are guaranteed to share the same storage /// /// Will lock the `StringPool` until the `release` method is called on the returned locked string. - pub fn stringToSliceLock(pool: *Pool, index: String) LockedString { - pool.mutex.lock(); + pub fn stringToSliceLock(pool: *Pool, io: std.Io, index: String) LockedString { + pool.mutex.lockUncancelable(io); return .{ .slice = pool.stringToSliceUnsafe(index) }; } @@ -172,7 +172,7 @@ pub fn StringPool(comptime config: Config) type { map: std.HashMapUnmanaged(u32, void, std.hash_map.StringIndexContext, std.hash_map.default_max_load_percentage), pub const empty: Pool = .{ - .mutex = .{}, + .mutex = .init, .bytes = .empty, .map = .empty, }; @@ -183,21 +183,23 @@ pub fn StringPool(comptime config: Config) type { pool.* = undefined; } - pub const MutexType = config.MutexType orelse if (config.thread_safe) std.Thread.Mutex else DummyMutex; + pub const MutexType = config.MutexType orelse if (config.thread_safe) std.Io.Mutex else DummyMutex; const DummyMutex = struct { - pub fn lock(_: *@This()) void {} - pub fn unlock(_: *@This()) void {} + pub const init: DummyMutex = .{}; + pub fn lockUncancelable(_: *DummyMutex, _: std.Io) void {} + pub fn unlock(_: *DummyMutex, _: std.Io) void {} }; const FormatContext = struct { string: String, + io: std.Io, pool: *Pool, }; fn print(ctx: FormatContext, writer: *std.Io.Writer) std.Io.Writer.Error!void { - const locked_string = ctx.pool.stringToSliceLock(ctx.string); - defer locked_string.release(ctx.pool); + const locked_string = ctx.pool.stringToSliceLock(ctx.io, ctx.string); + defer locked_string.release(ctx.io, ctx.pool); try writer.writeAll(locked_string.slice); } }; @@ -222,30 +224,32 @@ const PrecomputedStringIndexAdapter = struct { test StringPool { const gpa = std.testing.allocator; + const io = std.testing.io; var pool: StringPool(.{}) = .empty; defer pool.deinit(gpa); const str = "All Your Codebase Are Belong To Us"; - const index = try pool.getOrPutString(gpa, str); + const index = try pool.getOrPutString(io, gpa, str); { - const locked_string = pool.stringToSliceLock(index); - defer locked_string.release(&pool); + const locked_string = pool.stringToSliceLock(io, index); + defer locked_string.release(io, &pool); try std.testing.expectEqualStrings(str, locked_string.slice); } - try std.testing.expectFmt(str, "{f}", .{index.fmt(&pool)}); + try std.testing.expectFmt(str, "{f}", .{index.fmt(io, &pool)}); } test "StringPool - check interning" { const gpa = std.testing.allocator; + const io = std.testing.io; var pool: StringPool(.{ .thread_safe = false }) = .empty; defer pool.deinit(gpa); const str = "All Your Codebase Are Belong To Us"; - const index1 = try pool.getOrPutString(gpa, str); - const index2 = try pool.getOrPutString(gpa, str); - const index3 = pool.getString(str).?; + const index1 = try pool.getOrPutString(io, gpa, str); + const index2 = try pool.getOrPutString(io, gpa, str); + const index3 = pool.getString(io, str).?; const storage1 = pool.stringToSlice(index1); const storage2 = pool.stringToSliceUnsafe(index2); @@ -259,14 +263,15 @@ test "StringPool - check interning" { test "StringPool - getOrPut on existing string without allocation" { const gpa = std.testing.allocator; + const io = std.testing.io; var failing_gpa: std.testing.FailingAllocator = .init(gpa, .{ .fail_index = 0 }); var pool: StringPool(.{}) = .empty; defer pool.deinit(gpa); try pool.bytes.ensureTotalCapacityPrecise(gpa, "hello".len + 1); - const hello_string = try pool.getOrPutString(gpa, "hello"); + const hello_string = try pool.getOrPutString(io, gpa, "hello"); - try std.testing.expectError(error.OutOfMemory, pool.getOrPutString(failing_gpa.allocator(), "world")); - try std.testing.expectEqual(hello_string, try pool.getOrPutString(failing_gpa.allocator(), "hello")); + try std.testing.expectError(error.OutOfMemory, pool.getOrPutString(io, failing_gpa.allocator(), "world")); + try std.testing.expectEqual(hello_string, try pool.getOrPutString(io, failing_gpa.allocator(), "hello")); } diff --git a/src/analysis.zig b/src/analysis.zig index af7bd88e2..d69683fee 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -1386,7 +1386,6 @@ pub fn resolvePropertyType(analyser: *Analyser, ty: Type, name: []const u8) erro if (std.mem.eql(u8, "len", name)) { if (info.elem_count) |elem_count| { const index = try analyser.ip.get( - analyser.gpa, .{ .int_u64_value = .{ .ty = .usize_type, .int = elem_count } }, ); return Type.fromIP(analyser, .usize_type, index); @@ -1398,7 +1397,6 @@ pub fn resolvePropertyType(analyser: *Analyser, ty: Type, name: []const u8) erro .tuple => |info| { if (std.mem.eql(u8, "len", name)) { const index = try analyser.ip.get( - analyser.gpa, .{ .int_u64_value = .{ .ty = .usize_type, .int = info.len } }, ); return Type.fromIP(analyser, .usize_type, index); @@ -1527,7 +1525,7 @@ pub fn resolvePrimitive(analyser: *Analyser, identifier_name: []const u8) error{ const bits = std.fmt.parseUnsigned(u16, identifier_name[1..], 10) catch return null; - return try analyser.ip.get(analyser.gpa, .{ .int_type = .{ + return try analyser.ip.get(.{ .int_type = .{ .bits = bits, .signedness = signedness, } }); @@ -1592,7 +1590,7 @@ fn resolvePeerTypes(analyser: *Analyser, a: Type, b: Type) error{OutOfMemory}!?T } fn resolvePeerTypesIP(analyser: *Analyser, a: InternPool.Index, b: InternPool.Index) error{OutOfMemory}!?InternPool.Index { - const resolved = try analyser.ip.resolvePeerTypes(analyser.gpa, &.{ a, b }, builtin.target); + const resolved = try analyser.ip.resolvePeerTypes(&.{ a, b }, builtin.target); if (resolved == .none) return null; return resolved; } @@ -1606,7 +1604,7 @@ fn resolvePeerErrorSets(analyser: *Analyser, a: Type, b: Type) error{OutOfMemory const b_index = b.data.ip_index.index orelse return null; if (analyser.ip.zigTypeTag(a_index) != .error_set) return null; if (analyser.ip.zigTypeTag(b_index) != .error_set) return null; - const resolved_index = try analyser.ip.errorSetMerge(analyser.gpa, a_index, b_index); + const resolved_index = try analyser.ip.errorSetMerge(a_index, b_index); return Type.fromIP(analyser, .type_type, resolved_index); } @@ -2198,7 +2196,7 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error const lhs, const rhs = tree.nodeData(node).node_and_node; const lhs_index = try analyser.resolveErrorSetIPIndex(.of(lhs, handle)) orelse return null; const rhs_index = try analyser.resolveErrorSetIPIndex(.of(rhs, handle)) orelse return null; - const ip_index = try analyser.ip.errorSetMerge(analyser.gpa, lhs_index, rhs_index); + const ip_index = try analyser.ip.errorSetMerge(lhs_index, rhs_index); return Type.fromIP(analyser, .type_type, ip_index); }, @@ -2212,11 +2210,11 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error const identifier_token: Ast.TokenIndex = @intCast(tok_i); defer i += 1; const name = offsets.tokenToSlice(tree, identifier_token); - const index = try analyser.ip.string_pool.getOrPutString(analyser.gpa, name); + const index = try analyser.ip.string_pool.getOrPutString(analyser.store.io, analyser.gpa, name); try strings.put(analyser.gpa, index, {}); } - const names = try analyser.ip.getStringSlice(analyser.gpa, strings.keys()); - const ip_index = try analyser.ip.get(analyser.gpa, .{ .error_set_type = .{ .owner_decl = .none, .names = names } }); + const names = try analyser.ip.getStringSlice(strings.keys()); + const ip_index = try analyser.ip.get(.{ .error_set_type = .{ .owner_decl = .none, .names = names } }); return Type.fromIP(analyser, .type_type, ip_index); }, @@ -2343,7 +2341,7 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error const result_ty = switch (scalar_tag) { .comptime_float, .float, .comptime_int => operand_ty, .int => if (analyser.ip.isSignedInt(scalar_ty, builtin.target)) - try analyser.ip.toUnsigned(analyser.gpa, operand_ty, builtin.target) + try analyser.ip.toUnsigned(operand_ty, builtin.target) else operand_ty, else => return null, @@ -2419,14 +2417,14 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error if (!child_ty.is_type_val) return null; const child_ty_ip_index = switch (child_ty.data) { - .ip_index => |payload| payload.index orelse try analyser.ip.getUnknown(analyser.gpa, payload.type), + .ip_index => |payload| payload.index orelse try analyser.ip.getUnknown(payload.type), else => return null, }; const len = try analyser.resolveIntegerLiteral(u32, .of(params[0], handle)) orelse return null; // `InternPool.Key.Vector.len` can't represent unknown length yet - const vector_ty_ip_index = try analyser.ip.get(analyser.gpa, .{ + const vector_ty_ip_index = try analyser.ip.get(.{ .vector_type = .{ .len = len, .child = child_ty_ip_index, @@ -2701,7 +2699,7 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error if (typeof.data == .ip_index and typeof.data.ip_index.index != null) { const key = analyser.ip.indexToKey(typeof.data.ip_index.index.?); if (key == .vector_type) { - const vector_ty_ip_index = try analyser.ip.get(analyser.gpa, .{ + const vector_ty_ip_index = try analyser.ip.get(.{ .vector_type = .{ .len = key.vector_type.len, .child = .bool_type, @@ -2734,8 +2732,8 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error length += slice.len - 2 + @intFromBool(i != 0); } - const string_literal_type = try analyser.ip.get(analyser.gpa, .{ .pointer_type = .{ - .elem_type = try analyser.ip.get(analyser.gpa, .{ .array_type = .{ + const string_literal_type = try analyser.ip.get(.{ .pointer_type = .{ + .elem_type = try analyser.ip.get(.{ .array_type = .{ .child = .u8_type, .len = length, .sentinel = .zero_u8, @@ -2759,8 +2757,8 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error .failure => return null, } - const string_literal_type = try analyser.ip.get(analyser.gpa, .{ .pointer_type = .{ - .elem_type = try analyser.ip.get(analyser.gpa, .{ .array_type = .{ + const string_literal_type = try analyser.ip.get(.{ .pointer_type = .{ + .elem_type = try analyser.ip.get(.{ .array_type = .{ .child = .u8_type, .len = discarding_writer.count, .sentinel = .zero_u8, @@ -2776,13 +2774,13 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error const name_token = tree.nodeMainToken(node) + 2; if (tree.tokenTag(name_token) != .identifier) return null; const name = offsets.identifierTokenToNameSlice(tree, name_token); - const name_index = try analyser.ip.string_pool.getOrPutString(analyser.gpa, name); + const name_index = try analyser.ip.string_pool.getOrPutString(analyser.store.io, analyser.gpa, name); - const error_set_type = try analyser.ip.get(analyser.gpa, .{ .error_set_type = .{ + const error_set_type = try analyser.ip.get(.{ .error_set_type = .{ .owner_decl = .none, - .names = try analyser.ip.getStringSlice(analyser.gpa, &.{name_index}), + .names = try analyser.ip.getStringSlice(&.{name_index}), } }); - const error_value = try analyser.ip.get(analyser.gpa, .{ .error_value = .{ + const error_value = try analyser.ip.get(.{ .error_value = .{ .ty = error_set_type, .error_tag_name = name_index, } }); @@ -2807,19 +2805,16 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error const value: ?InternPool.Index = switch (result) { .float => blk: { break :blk try analyser.ip.get( - analyser.gpa, .{ .float_comptime_value = std.fmt.parseFloat(f128, bytes) catch break :blk null }, ); }, .int => blk: { break :blk if (bytes[0] == '-') try analyser.ip.get( - analyser.gpa, .{ .int_i64_value = .{ .ty = ty, .int = std.fmt.parseInt(i64, bytes, 0) catch break :blk null } }, ) else try analyser.ip.get( - analyser.gpa, .{ .int_u64_value = .{ .ty = ty, .int = std.fmt.parseInt(u64, bytes, 0) catch break :blk null } }, ); }, @@ -2832,7 +2827,7 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error else => break :blk null, }; std.debug.assert(ty == .comptime_int_type); - break :blk try analyser.ip.getBigInt(analyser.gpa, ty, big_int.toConst()); + break :blk try analyser.ip.getBigInt(ty, big_int.toConst()); }, .failure => unreachable, // checked above }; @@ -3969,7 +3964,7 @@ pub const Type = struct { pub fn instanceTypeVal(self: Type, analyser: *Analyser) error{OutOfMemory}!?Type { if (!self.is_type_val) return null; return switch (self.data) { - .ip_index => |payload| fromIP(analyser, payload.index orelse try analyser.ip.getUnknown(analyser.gpa, payload.type), null), + .ip_index => |payload| fromIP(analyser, payload.index orelse try analyser.ip.getUnknown(payload.type), null), .either => |old_entries| { const new_entries = try analyser.arena.alloc(Type.Data.EitherEntry, old_entries.len); for (old_entries, new_entries) |old, *new| { @@ -4478,7 +4473,7 @@ pub const Type = struct { }); }, .ip_index => |payload| { - const ip_index = payload.index orelse try analyser.ip.getUnknown(analyser.gpa, payload.type); + const ip_index = payload.index orelse try analyser.ip.getUnknown(payload.type); try analyser.ip.print(ip_index, writer, .{ .truncate_container = options.truncate_container_decls, }); diff --git a/src/build_runner/build_runner.zig b/src/build_runner/build_runner.zig index 4a58a7527..deac1dd33 100644 --- a/src/build_runner/build_runner.zig +++ b/src/build_runner/build_runner.zig @@ -50,14 +50,6 @@ pub fn main(init: process.Init.Minimal) !void { defer _ = debug_gpa_state.deinit(); const gpa = debug_gpa_state.allocator(); - // ...but we'll back our arena by `std.heap.page_allocator` for efficiency. - var single_threaded_arena: std.heap.ArenaAllocator = .init(std.heap.page_allocator); - defer single_threaded_arena.deinit(); - var thread_safe_arena: std.heap.ThreadSafeAllocator = .{ .child_allocator = single_threaded_arena.allocator() }; - const arena = thread_safe_arena.allocator(); - - const args = try init.args.toSlice(arena); - var threaded: Io.Threaded = .init(gpa, .{ .environ = init.environ, .argv0 = .init(init.args), @@ -65,6 +57,17 @@ pub fn main(init: process.Init.Minimal) !void { defer threaded.deinit(); const io = threaded.ioBasic(); + // ...but we'll back our arena by `std.heap.page_allocator` for efficiency. + var single_threaded_arena: std.heap.ArenaAllocator = .init(std.heap.page_allocator); + defer single_threaded_arena.deinit(); + var thread_safe_arena: std.heap.ThreadSafeAllocator = .{ + .child_allocator = single_threaded_arena.allocator(), + .io = io, + }; + const arena = thread_safe_arena.allocator(); + + const args = try init.args.toSlice(arena); + // skip my own exe name var arg_idx: usize = 1; diff --git a/src/diff.zig b/src/diff.zig index 3821dd9c5..335bb73de 100644 --- a/src/diff.zig +++ b/src/diff.zig @@ -6,11 +6,8 @@ const offsets = @import("offsets.zig"); const tracy = @import("tracy"); const DiffMatchPatch = @import("diffz"); -const dmp: DiffMatchPatch = .{ - .diff_timeout = .fromMilliseconds(250), -}; - pub fn edits( + io: std.Io, allocator: std.mem.Allocator, before: []const u8, after: []const u8, @@ -19,7 +16,13 @@ pub fn edits( const tracy_zone = tracy.trace(@src()); defer tracy_zone.end(); - var diffs = try dmp.diff(allocator, before, after, true); + const dmp: DiffMatchPatch = .initDefault(io, allocator); + var diffs = try dmp.diff( + before, + after, + true, + .{ .duration = .{ .clock = .awake, .raw = .fromMilliseconds(250) } }, + ); defer DiffMatchPatch.deinitDiffList(allocator, &diffs); var edit_count: usize = 0; diff --git a/src/features/completions.zig b/src/features/completions.zig index 484d0a3bb..2c7ede451 100644 --- a/src/features/completions.zig +++ b/src/features/completions.zig @@ -121,7 +121,7 @@ fn typeToCompletion(builder: *Builder, ty: Analyser.Type) Analyser.Error!void { builder.arena, &builder.completions, builder.analyser.ip, - payload.index orelse try builder.analyser.ip.getUnknown(builder.analyser.gpa, payload.type), + payload.index orelse try builder.analyser.ip.getUnknown(payload.type), ), .either => |either_entries| { for (either_entries) |entry| { diff --git a/tests/analysis_check.zig b/tests/analysis_check.zig index 445c49fe9..0fe4a3925 100644 --- a/tests/analysis_check.zig +++ b/tests/analysis_check.zig @@ -88,7 +88,7 @@ pub fn main(init: std.process.Init) Error!void { } } - var ip: InternPool = try .init(gpa); + var ip: InternPool = try .init(io, gpa); defer ip.deinit(gpa); var diagnostics_collection: zls.DiagnosticsCollection = .{ diff --git a/tests/utility/diff.zig b/tests/utility/diff.zig index d2aa172c8..fa6145fea 100644 --- a/tests/utility/diff.zig +++ b/tests/utility/diff.zig @@ -8,14 +8,16 @@ fn gen(alloc: std.mem.Allocator, rand: std.Random) ![]const u8 { } test "diff - random" { - const allocator = std.testing.allocator; var rand: std.Random.DefaultPrng = .init(std.testing.random_seed); - try testDiff(allocator, rand.random(), .@"utf-8"); - try testDiff(allocator, rand.random(), .@"utf-16"); - try testDiff(allocator, rand.random(), .@"utf-32"); + try testDiff(rand.random(), .@"utf-8"); + try testDiff(rand.random(), .@"utf-16"); + try testDiff(rand.random(), .@"utf-32"); } -fn testDiff(allocator: std.mem.Allocator, rand: std.Random, encoding: zls.offsets.Encoding) !void { +fn testDiff(rand: std.Random, encoding: zls.offsets.Encoding) !void { + const io = std.testing.io; + const allocator = std.testing.allocator; + var buffer: [256]u8 = undefined; rand.bytes(&buffer); for (&buffer) |*c| c.* = '0' + c.* % 32; @@ -24,7 +26,7 @@ fn testDiff(allocator: std.mem.Allocator, rand: std.Random, encoding: zls.offset const before = buffer[0..split_index]; const after = buffer[split_index..]; - var edits = try zls.diff.edits(allocator, before, after, encoding); + var edits = try zls.diff.edits(io, allocator, before, after, encoding); defer { for (edits.items) |edit| allocator.free(edit.newText); edits.deinit(allocator);