authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-04-08 16:02:19-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-04-10 17:39:45+02:00
logc3a862522bbb59ee23a53e0562c402283db59b9c
treeb14399fc672d911c11f6e9f14fb911f818b67d67
parent0606af509f9a7f5e6bc458940aa9529d73232fc4

std: remove managed array hash map variants

And deprecate all the API names except for: * `std.array_hash_map.Auto` * `std.array_hash_map.String` * `std.array_hash_map.Custom`

26 files changed, 271 insertions(+), 725 deletions(-)

lib/std/Build.zig+12-12
......@@ -86,10 +86,10 @@ libc_runtimes_dir: ?[]const u8 = null,
8686
8787dep_prefix: []const u8 = "",
8888
89modules: std.StringArrayHashMap(*Module),
89modules: std.array_hash_map.String(*Module),
9090
91named_writefiles: std.StringArrayHashMap(*Step.WriteFile),
92named_lazy_paths: std.StringArrayHashMap(LazyPath),
91named_writefiles: std.array_hash_map.String(*Step.WriteFile),
92named_lazy_paths: std.array_hash_map.String(LazyPath),
9393/// The hash of this instance's package. `""` means that this is the root package.
9494pkg_hash: []const u8,
9595/// A mapping from dependency names to package hashes.
......@@ -312,9 +312,9 @@ pub fn create(
312312 },
313313 .install_path = undefined,
314314 .args = null,
315 .modules = .init(arena),
316 .named_writefiles = .init(arena),
317 .named_lazy_paths = .init(arena),
315 .modules = .empty,
316 .named_writefiles = .empty,
317 .named_lazy_paths = .empty,
318318 .pkg_hash = "",
319319 .available_deps = available_deps,
320320 .release_mode = .off,
......@@ -405,9 +405,9 @@ fn createChildOnly(
405405 .enable_wine = parent.enable_wine,
406406 .libc_runtimes_dir = parent.libc_runtimes_dir,
407407 .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),
408 .modules = .init(allocator),
409 .named_writefiles = .init(allocator),
410 .named_lazy_paths = .init(allocator),
408 .modules = .empty,
409 .named_writefiles = .empty,
410 .named_lazy_paths = .empty,
411411 .pkg_hash = pkg_hash,
412412 .available_deps = pkg_deps,
413413 .release_mode = parent.release_mode,
......@@ -908,7 +908,7 @@ pub const AssemblyOptions = struct {
908908/// `createModule` can be used instead to create a private module.
909909pub fn addModule(b: *Build, name: []const u8, options: Module.CreateOptions) *Module {
910910 const module = Module.create(b, options);
911 b.modules.put(b.dupe(name), module) catch @panic("OOM");
911 b.modules.put(b.graph.arena, b.dupe(name), module) catch @panic("OOM");
912912 return module;
913913}
914914
......@@ -1056,12 +1056,12 @@ pub fn addWriteFile(b: *Build, file_path: []const u8, data: []const u8) *Step.Wr
10561056
10571057pub fn addNamedWriteFiles(b: *Build, name: []const u8) *Step.WriteFile {
10581058 const wf = Step.WriteFile.create(b);
1059 b.named_writefiles.put(b.dupe(name), wf) catch @panic("OOM");
1059 b.named_writefiles.put(b.graph.arena, b.dupe(name), wf) catch @panic("OOM");
10601060 return wf;
10611061}
10621062
10631063pub fn addNamedLazyPath(b: *Build, name: []const u8, lp: LazyPath) void {
1064 b.named_lazy_paths.put(b.dupe(name), lp.dupe(b)) catch @panic("OOM");
1064 b.named_lazy_paths.put(b.graph.arena, b.dupe(name), lp.dupe(b)) catch @panic("OOM");
10651065}
10661066
10671067/// Creates a step for mutating files inside a temporary directory created lazily
lib/std/Build/Step/CheckObject.zig+3-3
......@@ -1814,16 +1814,16 @@ const ElfDumper = struct {
18141814 files.putAssumeCapacityNoClobber(object.off - @sizeOf(elf.ar_hdr), object.name);
18151815 }
18161816
1817 var symbols = std.AutoArrayHashMap(usize, std.array_list.Managed([]const u8)).init(ctx.gpa);
1817 var symbols: std.array_hash_map.Auto(usize, std.array_list.Managed([]const u8)) = .empty;
18181818 defer {
18191819 for (symbols.values()) |*value| {
18201820 value.deinit();
18211821 }
1822 symbols.deinit();
1822 symbols.deinit(ctx.gpa);
18231823 }
18241824
18251825 for (ctx.symtab.items) |entry| {
1826 const gop = try symbols.getOrPut(@intCast(entry.off));
1826 const gop = try symbols.getOrPut(ctx.gpa, @intCast(entry.off));
18271827 if (!gop.found_existing) {
18281828 gop.value_ptr.* = std.array_list.Managed([]const u8).init(ctx.gpa);
18291829 }
lib/std/Build/Step/ConfigHeader.zig+34-32
......@@ -38,7 +38,7 @@ pub const Value = union(enum) {
3838};
3939
4040step: Step,
41values: std.StringArrayHashMap(Value),
41values: std.array_hash_map.String(Value),
4242/// This directory contains the generated file under the name `include_path`.
4343generated_dir: std.Build.GeneratedFile,
4444
......@@ -95,7 +95,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
9595 .first_ret_addr = options.first_ret_addr orelse @returnAddress(),
9696 }),
9797 .style = options.style,
98 .values = .init(owner.allocator),
98 .values = .empty,
9999
100100 .max_bytes = options.max_bytes,
101101 .include_path = include_path,
......@@ -110,7 +110,8 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
110110}
111111
112112pub fn addIdent(config_header: *ConfigHeader, name: []const u8, value: []const u8) void {
113 config_header.values.put(name, .{ .ident = value }) catch @panic("OOM");
113 const arena = config_header.step.owner.allocator;
114 config_header.values.put(arena, name, .{ .ident = value }) catch @panic("OOM");
114115}
115116
116117pub fn addValue(config_header: *ConfigHeader, name: []const u8, comptime T: type, value: T) void {
......@@ -131,43 +132,44 @@ pub fn getOutputFile(ch: *ConfigHeader) std.Build.LazyPath {
131132}
132133
133134fn addValueInner(config_header: *ConfigHeader, name: []const u8, comptime T: type, value: T) !void {
135 const arena = config_header.step.owner.allocator;
134136 switch (@typeInfo(T)) {
135137 .null => {
136 try config_header.values.put(name, .undef);
138 try config_header.values.put(arena, name, .undef);
137139 },
138140 .void => {
139 try config_header.values.put(name, .defined);
141 try config_header.values.put(arena, name, .defined);
140142 },
141143 .bool => {
142 try config_header.values.put(name, .{ .boolean = value });
144 try config_header.values.put(arena, name, .{ .boolean = value });
143145 },
144146 .int => {
145 try config_header.values.put(name, .{ .int = value });
147 try config_header.values.put(arena, name, .{ .int = value });
146148 },
147149 .comptime_int => {
148 try config_header.values.put(name, .{ .int = value });
150 try config_header.values.put(arena, name, .{ .int = value });
149151 },
150152 .@"enum", .enum_literal => {
151 try config_header.values.put(name, .{ .ident = @tagName(value) });
153 try config_header.values.put(arena, name, .{ .ident = @tagName(value) });
152154 },
153155 .optional => {
154156 if (value) |x| {
155157 return addValueInner(config_header, name, @TypeOf(x), x);
156158 } else {
157 try config_header.values.put(name, .undef);
159 try config_header.values.put(arena, name, .undef);
158160 }
159161 },
160162 .pointer => |ptr| {
161163 switch (@typeInfo(ptr.child)) {
162164 .array => |array| {
163165 if (ptr.size == .one and array.child == u8) {
164 try config_header.values.put(name, .{ .string = value });
166 try config_header.values.put(arena, name, .{ .string = value });
165167 return;
166168 }
167169 },
168170 .int => {
169171 if (ptr.size == .slice and ptr.child == u8) {
170 try config_header.values.put(name, .{ .string = value });
172 try config_header.values.put(arena, name, .{ .string = value });
171173 return;
172174 }
173175 },
......@@ -218,8 +220,8 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
218220 });
219221 };
220222 switch (config_header.style) {
221 .autoconf_undef => try render_autoconf_undef(step, contents, bw, config_header.values, src_path),
222 .autoconf_at => try render_autoconf_at(step, contents, &aw, config_header.values, src_path),
223 .autoconf_undef => try render_autoconf_undef(step, contents, bw, &config_header.values, src_path),
224 .autoconf_at => try render_autoconf_at(step, contents, &aw, &config_header.values, src_path),
223225 else => unreachable,
224226 }
225227 },
......@@ -282,7 +284,7 @@ fn render_autoconf_undef(
282284 step: *Step,
283285 contents: []const u8,
284286 bw: *Writer,
285 values: std.StringArrayHashMap(Value),
287 values: *const std.array_hash_map.String(Value),
286288 src_path: []const u8,
287289) !void {
288290 const build = step.owner;
......@@ -334,7 +336,7 @@ fn render_autoconf_at(
334336 step: *Step,
335337 contents: []const u8,
336338 aw: *Writer.Allocating,
337 values: std.StringArrayHashMap(Value),
339 values: *const std.array_hash_map.String(Value),
338340 src_path: []const u8,
339341) !void {
340342 const build = step.owner;
......@@ -373,7 +375,7 @@ fn render_autoconf_at(
373375 if (!last_line) try bw.writeByte('\n');
374376 }
375377
376 for (values.unmanaged.entries.slice().items(.key), used) |name, u| {
378 for (values.entries.slice().items(.key), used) |name, u| {
377379 if (!u) {
378380 try step.addError("{s}: error: config header value unused: '{s}'", .{ src_path, name });
379381 any_errors = true;
......@@ -387,14 +389,14 @@ fn render_cmake(
387389 step: *Step,
388390 contents: []const u8,
389391 bw: *Writer,
390 values: std.StringArrayHashMap(Value),
392 values: std.array_hash_map.String(Value),
391393 src_path: []const u8,
392394) !void {
393395 const build = step.owner;
394396 const allocator = build.allocator;
395397
396 var values_copy = try values.clone();
397 defer values_copy.deinit();
398 var values_copy = try values.clone(allocator);
399 defer values_copy.deinit(allocator);
398400
399401 var any_errors = false;
400402 var line_index: u32 = 0;
......@@ -523,7 +525,7 @@ fn render_cmake(
523525fn render_blank(
524526 gpa: std.mem.Allocator,
525527 bw: *Writer,
526 defines: std.StringArrayHashMap(Value),
528 defines: std.array_hash_map.String(Value),
527529 include_path: []const u8,
528530 include_guard_override: ?[]const u8,
529531) !void {
......@@ -555,7 +557,7 @@ fn render_blank(
555557 , .{include_guard_name});
556558}
557559
558fn render_nasm(bw: *Writer, defines: std.StringArrayHashMap(Value)) !void {
560fn render_nasm(bw: *Writer, defines: std.array_hash_map.String(Value)) !void {
559561 for (defines.keys(), defines.values()) |name, value| try renderValueNasm(bw, name, value);
560562}
561563
......@@ -586,7 +588,7 @@ fn renderValueNasm(bw: *Writer, name: []const u8, value: Value) !void {
586588fn expand_variables_autoconf_at(
587589 bw: *Writer,
588590 contents: []const u8,
589 values: std.StringArrayHashMap(Value),
591 values: *const std.array_hash_map.String(Value),
590592 used: []bool,
591593) !void {
592594 const valid_varname_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
......@@ -612,7 +614,7 @@ fn expand_variables_autoconf_at(
612614 try bw.writeAll(key);
613615 return error.MissingValue;
614616 };
615 const value = values.unmanaged.entries.slice().items(.value)[index];
617 const value = values.entries.slice().items(.value)[index];
616618 used[index] = true;
617619 try bw.writeAll(contents[source_offset..curr]);
618620 switch (value) {
......@@ -633,7 +635,7 @@ fn expand_variables_autoconf_at(
633635fn expand_variables_cmake(
634636 allocator: Allocator,
635637 contents: []const u8,
636 values: std.StringArrayHashMap(Value),
638 values: std.array_hash_map.String(Value),
637639) ![]const u8 {
638640 var result: std.array_list.Managed(u8) = .init(allocator);
639641 errdefer result.deinit();
......@@ -765,7 +767,7 @@ fn testReplaceVariablesAutoconfAt(
765767 allocator: Allocator,
766768 contents: []const u8,
767769 expected: []const u8,
768 values: std.StringArrayHashMap(Value),
770 values: std.array_hash_map.String(Value),
769771) !void {
770772 var aw: Writer.Allocating = .init(allocator);
771773 defer aw.deinit();
......@@ -784,7 +786,7 @@ fn testReplaceVariablesCMake(
784786 allocator: Allocator,
785787 contents: []const u8,
786788 expected: []const u8,
787 values: std.StringArrayHashMap(Value),
789 values: std.array_hash_map.String(Value),
788790) !void {
789791 const actual = try expand_variables_cmake(allocator, contents, values);
790792 defer allocator.free(actual);
......@@ -794,7 +796,7 @@ fn testReplaceVariablesCMake(
794796
795797test "expand_variables_autoconf_at simple cases" {
796798 const allocator = std.testing.allocator;
797 var values: std.StringArrayHashMap(Value) = .init(allocator);
799 var values: std.array_hash_map.String(Value) = .init(allocator);
798800 defer values.deinit();
799801
800802 // empty strings are preserved
......@@ -890,7 +892,7 @@ test "expand_variables_autoconf_at simple cases" {
890892
891893test "expand_variables_autoconf_at edge cases" {
892894 const allocator = std.testing.allocator;
893 var values: std.StringArrayHashMap(Value) = .init(allocator);
895 var values: std.array_hash_map.String(Value) = .init(allocator);
894896 defer values.deinit();
895897
896898 // @-vars resolved only when they wrap valid characters, otherwise considered literals
......@@ -906,7 +908,7 @@ test "expand_variables_autoconf_at edge cases" {
906908
907909test "expand_variables_cmake simple cases" {
908910 const allocator = std.testing.allocator;
909 var values: std.StringArrayHashMap(Value) = .init(allocator);
911 var values: std.array_hash_map.String(Value) = .init(allocator);
910912 defer values.deinit();
911913
912914 try values.putNoClobber("undef", .undef);
......@@ -994,7 +996,7 @@ test "expand_variables_cmake simple cases" {
994996
995997test "expand_variables_cmake edge cases" {
996998 const allocator = std.testing.allocator;
997 var values: std.StringArrayHashMap(Value) = .init(allocator);
999 var values: std.array_hash_map.String(Value) = .init(allocator);
9981000 defer values.deinit();
9991001
10001002 // special symbols
......@@ -1055,7 +1057,7 @@ test "expand_variables_cmake edge cases" {
10551057
10561058test "expand_variables_cmake escaped characters" {
10571059 const allocator = std.testing.allocator;
1058 var values: std.StringArrayHashMap(Value) = .init(allocator);
1060 var values: std.array_hash_map.String(Value) = .init(allocator);
10591061 defer values.deinit();
10601062
10611063 try values.putNoClobber("string", Value{ .string = "text" });
lib/std/array_hash_map.zig+96-555
......@@ -12,27 +12,15 @@ const hash_map = @This();
1212/// An `ArrayHashMap` with default hash and equal functions.
1313///
1414/// See `AutoContext` for a description of the hash and equal implementations.
15pub fn AutoArrayHashMap(comptime K: type, comptime V: type) type {
15pub fn Auto(comptime K: type, comptime V: type) type {
1616 return ArrayHashMap(K, V, AutoContext(K), !autoEqlIsCheap(K));
1717}
1818
19/// An `ArrayHashMapUnmanaged` with default hash and equal functions.
20///
21/// See `AutoContext` for a description of the hash and equal implementations.
22pub fn AutoArrayHashMapUnmanaged(comptime K: type, comptime V: type) type {
23 return ArrayHashMapUnmanaged(K, V, AutoContext(K), !autoEqlIsCheap(K));
24}
25
2619/// An `ArrayHashMap` with strings as keys.
27pub fn StringArrayHashMap(comptime V: type) type {
20pub fn String(comptime V: type) type {
2821 return ArrayHashMap([]const u8, V, StringContext, true);
2922}
3023
31/// An `ArrayHashMapUnmanaged` with strings as keys.
32pub fn StringArrayHashMapUnmanaged(comptime V: type) type {
33 return ArrayHashMapUnmanaged([]const u8, V, StringContext, true);
34}
35
3624pub const StringContext = struct {
3725 pub fn hash(self: @This(), s: []const u8) u32 {
3826 _ = self;
......@@ -53,454 +41,8 @@ pub fn hashString(s: []const u8) u32 {
5341 return @truncate(std.hash.Wyhash.hash(0, s));
5442}
5543
56/// Deprecated in favor of `ArrayHashMapWithAllocator` (no code changes needed)
57/// or `ArrayHashMapUnmanaged` (will need to update callsites to pass an
58/// allocator). After Zig 0.14.0 is released, `ArrayHashMapWithAllocator` will
59/// be removed and `ArrayHashMapUnmanaged` will be a deprecated alias. After
60/// Zig 0.15.0 is released, the deprecated alias `ArrayHashMapUnmanaged` will
61/// be removed.
62pub const ArrayHashMap = ArrayHashMapWithAllocator;
63
64/// A hash table of keys and values, each stored sequentially.
65///
66/// Insertion order is preserved. In general, this data structure supports the same
67/// operations as `std.ArrayList`.
68///
69/// Deletion operations:
70/// * `swapRemove` - O(1)
71/// * `orderedRemove` - O(N)
72///
73/// Modifying the hash map while iterating is allowed, however, one must understand
74/// the (well defined) behavior when mixing insertions and deletions with iteration.
75///
76/// See `ArrayHashMapUnmanaged` for a variant of this data structure that accepts an
77/// `Allocator` as a parameter when needed rather than storing it.
78pub fn ArrayHashMapWithAllocator(
79 comptime K: type,
80 comptime V: type,
81 /// A namespace that provides these two functions:
82 /// * `pub fn hash(self, K) u32`
83 /// * `pub fn eql(self, K, K, usize) bool`
84 ///
85 /// The final `usize` in the `eql` function represents the index of the key
86 /// that's already inside the map.
87 comptime Context: type,
88 /// When `false`, this data structure is biased towards cheap `eql`
89 /// functions and avoids storing each key's hash in the table. Setting
90 /// `store_hash` to `true` incurs more memory cost but limits `eql` to
91 /// being called only once per insertion/deletion (provided there are no
92 /// hash collisions).
93 comptime store_hash: bool,
94) type {
95 return struct {
96 unmanaged: Unmanaged,
97 allocator: Allocator,
98 ctx: Context,
99
100 /// The ArrayHashMapUnmanaged type using the same settings as this managed map.
101 pub const Unmanaged = ArrayHashMapUnmanaged(K, V, Context, store_hash);
102
103 /// Pointers to a key and value in the backing store of this map.
104 /// Modifying the key is allowed only if it does not change the hash.
105 /// Modifying the value is allowed.
106 /// Entry pointers become invalid whenever this ArrayHashMap is modified,
107 /// unless `ensureTotalCapacity`/`ensureUnusedCapacity` was previously used.
108 pub const Entry = Unmanaged.Entry;
109
110 /// A KV pair which has been copied out of the backing store
111 pub const KV = Unmanaged.KV;
112
113 /// The Data type used for the MultiArrayList backing this map
114 pub const Data = Unmanaged.Data;
115 /// The MultiArrayList type backing this map
116 pub const DataList = Unmanaged.DataList;
117
118 /// The stored hash type, either u32 or void.
119 pub const Hash = Unmanaged.Hash;
120
121 /// getOrPut variants return this structure, with pointers
122 /// to the backing store and a flag to indicate whether an
123 /// existing entry was found.
124 /// Modifying the key is allowed only if it does not change the hash.
125 /// Modifying the value is allowed.
126 /// Entry pointers become invalid whenever this ArrayHashMap is modified,
127 /// unless `ensureTotalCapacity`/`ensureUnusedCapacity` was previously used.
128 pub const GetOrPutResult = Unmanaged.GetOrPutResult;
129
130 /// An Iterator over Entry pointers.
131 pub const Iterator = Unmanaged.Iterator;
132
133 const Self = @This();
134
135 /// Create an ArrayHashMap instance which will use a specified allocator.
136 pub fn init(allocator: Allocator) Self {
137 if (@sizeOf(Context) != 0)
138 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call initContext instead.");
139 return initContext(allocator, undefined);
140 }
141 pub fn initContext(allocator: Allocator, ctx: Context) Self {
142 return .{
143 .unmanaged = .empty,
144 .allocator = allocator,
145 .ctx = ctx,
146 };
147 }
148
149 /// Frees the backing allocation and leaves the map in an undefined state.
150 /// Note that this does not free keys or values. You must take care of that
151 /// before calling this function, if it is needed.
152 pub fn deinit(self: *Self) void {
153 self.unmanaged.deinit(self.allocator);
154 self.* = undefined;
155 }
156
157 /// Puts the hash map into a state where any method call that would
158 /// cause an existing key or value pointer to become invalidated will
159 /// instead trigger an assertion.
160 ///
161 /// An additional call to `lockPointers` in such state also triggers an
162 /// assertion.
163 ///
164 /// `unlockPointers` returns the hash map to the previous state.
165 pub fn lockPointers(self: *Self) void {
166 self.unmanaged.lockPointers();
167 }
168
169 /// Undoes a call to `lockPointers`.
170 pub fn unlockPointers(self: *Self) void {
171 self.unmanaged.unlockPointers();
172 }
173
174 /// Clears the map but retains the backing allocation for future use.
175 pub fn clearRetainingCapacity(self: *Self) void {
176 return self.unmanaged.clearRetainingCapacity();
177 }
178
179 /// Clears the map and releases the backing allocation
180 pub fn clearAndFree(self: *Self) void {
181 return self.unmanaged.clearAndFree(self.allocator);
182 }
183
184 /// Returns the number of KV pairs stored in this map.
185 pub fn count(self: Self) usize {
186 return self.unmanaged.count();
187 }
188
189 /// Returns the backing array of keys in this map. Modifying the map may
190 /// invalidate this array. Modifying this array in a way that changes
191 /// key hashes or key equality puts the map into an unusable state until
192 /// `reIndex` is called.
193 pub fn keys(self: Self) []K {
194 return self.unmanaged.keys();
195 }
196 /// Returns the backing array of values in this map. Modifying the map
197 /// may invalidate this array. It is permitted to modify the values in
198 /// this array.
199 pub fn values(self: Self) []V {
200 return self.unmanaged.values();
201 }
202
203 /// Returns an iterator over the pairs in this map.
204 /// Modifying the map may invalidate this iterator.
205 pub fn iterator(self: *const Self) Iterator {
206 return self.unmanaged.iterator();
207 }
208
209 /// If key exists this function cannot fail.
210 /// If there is an existing item with `key`, then the result
211 /// `Entry` pointer points to it, and found_existing is true.
212 /// Otherwise, puts a new item with undefined value, and
213 /// the `Entry` pointer points to it. Caller should then initialize
214 /// the value (but not the key).
215 pub fn getOrPut(self: *Self, key: K) !GetOrPutResult {
216 return self.unmanaged.getOrPutContext(self.allocator, key, self.ctx);
217 }
218 pub fn getOrPutAdapted(self: *Self, key: anytype, ctx: anytype) !GetOrPutResult {
219 return self.unmanaged.getOrPutContextAdapted(self.allocator, key, ctx, self.ctx);
220 }
221
222 /// If there is an existing item with `key`, then the result
223 /// `Entry` pointer points to it, and found_existing is true.
224 /// Otherwise, puts a new item with undefined value, and
225 /// the `Entry` pointer points to it. Caller should then initialize
226 /// the value (but not the key).
227 /// If a new entry needs to be stored, this function asserts there
228 /// is enough capacity to store it.
229 pub fn getOrPutAssumeCapacity(self: *Self, key: K) GetOrPutResult {
230 return self.unmanaged.getOrPutAssumeCapacityContext(key, self.ctx);
231 }
232 pub fn getOrPutAssumeCapacityAdapted(self: *Self, key: anytype, ctx: anytype) GetOrPutResult {
233 return self.unmanaged.getOrPutAssumeCapacityAdapted(key, ctx);
234 }
235 pub fn getOrPutValue(self: *Self, key: K, value: V) !GetOrPutResult {
236 return self.unmanaged.getOrPutValueContext(self.allocator, key, value, self.ctx);
237 }
238
239 /// Increases capacity, guaranteeing that insertions up until the
240 /// `expected_count` will not cause an allocation, and therefore cannot fail.
241 pub fn ensureTotalCapacity(self: *Self, new_capacity: usize) !void {
242 return self.unmanaged.ensureTotalCapacityContext(self.allocator, new_capacity, self.ctx);
243 }
244
245 /// Increases capacity, guaranteeing that insertions up until
246 /// `additional_count` **more** items will not cause an allocation, and
247 /// therefore cannot fail.
248 pub fn ensureUnusedCapacity(self: *Self, additional_count: usize) !void {
249 return self.unmanaged.ensureUnusedCapacityContext(self.allocator, additional_count, self.ctx);
250 }
251
252 /// Returns the number of total elements which may be present before it is
253 /// no longer guaranteed that no allocations will be performed.
254 pub fn capacity(self: Self) usize {
255 return self.unmanaged.capacity();
256 }
257
258 /// Clobbers any existing data. To detect if a put would clobber
259 /// existing data, see `getOrPut`.
260 pub fn put(self: *Self, key: K, value: V) !void {
261 return self.unmanaged.putContext(self.allocator, key, value, self.ctx);
262 }
263
264 /// Inserts a key-value pair into the hash map, asserting that no previous
265 /// entry with the same key is already present
266 pub fn putNoClobber(self: *Self, key: K, value: V) !void {
267 return self.unmanaged.putNoClobberContext(self.allocator, key, value, self.ctx);
268 }
269
270 /// Asserts there is enough capacity to store the new key-value pair.
271 /// Clobbers any existing data. To detect if a put would clobber
272 /// existing data, see `getOrPutAssumeCapacity`.
273 pub fn putAssumeCapacity(self: *Self, key: K, value: V) void {
274 return self.unmanaged.putAssumeCapacityContext(key, value, self.ctx);
275 }
276
277 /// Asserts there is enough capacity to store the new key-value pair.
278 /// Asserts that it does not clobber any existing data.
279 /// To detect if a put would clobber existing data, see `getOrPutAssumeCapacity`.
280 pub fn putAssumeCapacityNoClobber(self: *Self, key: K, value: V) void {
281 return self.unmanaged.putAssumeCapacityNoClobberContext(key, value, self.ctx);
282 }
283
284 /// Inserts a new `Entry` into the hash map, returning the previous one, if any.
285 pub fn fetchPut(self: *Self, key: K, value: V) !?KV {
286 return self.unmanaged.fetchPutContext(self.allocator, key, value, self.ctx);
287 }
288
289 /// Inserts a new `Entry` into the hash map, returning the previous one, if any.
290 /// If insertion happuns, asserts there is enough capacity without allocating.
291 pub fn fetchPutAssumeCapacity(self: *Self, key: K, value: V) ?KV {
292 return self.unmanaged.fetchPutAssumeCapacityContext(key, value, self.ctx);
293 }
294
295 /// Finds pointers to the key and value storage associated with a key.
296 pub fn getEntry(self: Self, key: K) ?Entry {
297 return self.unmanaged.getEntryContext(key, self.ctx);
298 }
299 pub fn getEntryAdapted(self: Self, key: anytype, ctx: anytype) ?Entry {
300 return self.unmanaged.getEntryAdapted(key, ctx);
301 }
302
303 /// Finds the index in the `entries` array where a key is stored
304 pub fn getIndex(self: Self, key: K) ?usize {
305 return self.unmanaged.getIndexContext(key, self.ctx);
306 }
307 pub fn getIndexAdapted(self: Self, key: anytype, ctx: anytype) ?usize {
308 return self.unmanaged.getIndexAdapted(key, ctx);
309 }
310
311 /// Find the value associated with a key
312 pub fn get(self: Self, key: K) ?V {
313 return self.unmanaged.getContext(key, self.ctx);
314 }
315 pub fn getAdapted(self: Self, key: anytype, ctx: anytype) ?V {
316 return self.unmanaged.getAdapted(key, ctx);
317 }
318
319 /// Find a pointer to the value associated with a key
320 pub fn getPtr(self: Self, key: K) ?*V {
321 return self.unmanaged.getPtrContext(key, self.ctx);
322 }
323 pub fn getPtrAdapted(self: Self, key: anytype, ctx: anytype) ?*V {
324 return self.unmanaged.getPtrAdapted(key, ctx);
325 }
326
327 /// Find the actual key associated with an adapted key
328 pub fn getKey(self: Self, key: K) ?K {
329 return self.unmanaged.getKeyContext(key, self.ctx);
330 }
331 pub fn getKeyAdapted(self: Self, key: anytype, ctx: anytype) ?K {
332 return self.unmanaged.getKeyAdapted(key, ctx);
333 }
334
335 /// Find a pointer to the actual key associated with an adapted key
336 pub fn getKeyPtr(self: Self, key: K) ?*K {
337 return self.unmanaged.getKeyPtrContext(key, self.ctx);
338 }
339 pub fn getKeyPtrAdapted(self: Self, key: anytype, ctx: anytype) ?*K {
340 return self.unmanaged.getKeyPtrAdapted(key, ctx);
341 }
342
343 /// Check whether a key is stored in the map
344 pub fn contains(self: Self, key: K) bool {
345 return self.unmanaged.containsContext(key, self.ctx);
346 }
347 pub fn containsAdapted(self: Self, key: anytype, ctx: anytype) bool {
348 return self.unmanaged.containsAdapted(key, ctx);
349 }
350
351 /// If there is an `Entry` with a matching key, it is deleted from
352 /// the hash map, and then returned from this function. The entry is
353 /// removed from the underlying array by swapping it with the last
354 /// element.
355 pub fn fetchSwapRemove(self: *Self, key: K) ?KV {
356 return self.unmanaged.fetchSwapRemoveContext(key, self.ctx);
357 }
358 pub fn fetchSwapRemoveAdapted(self: *Self, key: anytype, ctx: anytype) ?KV {
359 return self.unmanaged.fetchSwapRemoveContextAdapted(key, ctx, self.ctx);
360 }
361
362 /// If there is an `Entry` with a matching key, it is deleted from
363 /// the hash map, and then returned from this function. The entry is
364 /// removed from the underlying array by shifting all elements forward
365 /// thereby maintaining the current ordering.
366 pub fn fetchOrderedRemove(self: *Self, key: K) ?KV {
367 return self.unmanaged.fetchOrderedRemoveContext(key, self.ctx);
368 }
369 pub fn fetchOrderedRemoveAdapted(self: *Self, key: anytype, ctx: anytype) ?KV {
370 return self.unmanaged.fetchOrderedRemoveContextAdapted(key, ctx, self.ctx);
371 }
372
373 /// If there is an `Entry` with a matching key, it is deleted from
374 /// the hash map. The entry is removed from the underlying array
375 /// by swapping it with the last element. Returns true if an entry
376 /// was removed, false otherwise.
377 pub fn swapRemove(self: *Self, key: K) bool {
378 return self.unmanaged.swapRemoveContext(key, self.ctx);
379 }
380 pub fn swapRemoveAdapted(self: *Self, key: anytype, ctx: anytype) bool {
381 return self.unmanaged.swapRemoveContextAdapted(key, ctx, self.ctx);
382 }
383
384 /// If there is an `Entry` with a matching key, it is deleted from
385 /// the hash map. The entry is removed from the underlying array
386 /// by shifting all elements forward, thereby maintaining the
387 /// current ordering. Returns true if an entry was removed, false otherwise.
388 pub fn orderedRemove(self: *Self, key: K) bool {
389 return self.unmanaged.orderedRemoveContext(key, self.ctx);
390 }
391 pub fn orderedRemoveAdapted(self: *Self, key: anytype, ctx: anytype) bool {
392 return self.unmanaged.orderedRemoveContextAdapted(key, ctx, self.ctx);
393 }
394
395 /// Deletes the item at the specified index in `entries` from
396 /// the hash map. The entry is removed from the underlying array
397 /// by swapping it with the last element.
398 pub fn swapRemoveAt(self: *Self, index: usize) void {
399 self.unmanaged.swapRemoveAtContext(index, self.ctx);
400 }
401
402 /// Deletes the item at the specified index in `entries` from
403 /// the hash map. The entry is removed from the underlying array
404 /// by shifting all elements forward, thereby maintaining the
405 /// current ordering.
406 pub fn orderedRemoveAt(self: *Self, index: usize) void {
407 self.unmanaged.orderedRemoveAtContext(index, self.ctx);
408 }
409
410 /// Create a copy of the hash map which can be modified separately.
411 /// The copy uses the same context and allocator as this instance.
412 pub fn clone(self: Self) !Self {
413 var other = try self.unmanaged.cloneContext(self.allocator, self.ctx);
414 return other.promoteContext(self.allocator, self.ctx);
415 }
416 /// Create a copy of the hash map which can be modified separately.
417 /// The copy uses the same context as this instance, but the specified
418 /// allocator.
419 pub fn cloneWithAllocator(self: Self, allocator: Allocator) !Self {
420 var other = try self.unmanaged.cloneContext(allocator, self.ctx);
421 return other.promoteContext(allocator, self.ctx);
422 }
423 /// Create a copy of the hash map which can be modified separately.
424 /// The copy uses the same allocator as this instance, but the
425 /// specified context.
426 pub fn cloneWithContext(self: Self, ctx: anytype) !ArrayHashMap(K, V, @TypeOf(ctx), store_hash) {
427 var other = try self.unmanaged.cloneContext(self.allocator, ctx);
428 return other.promoteContext(self.allocator, ctx);
429 }
430 /// Create a copy of the hash map which can be modified separately.
431 /// The copy uses the specified allocator and context.
432 pub fn cloneWithAllocatorAndContext(self: Self, allocator: Allocator, ctx: anytype) !ArrayHashMap(K, V, @TypeOf(ctx), store_hash) {
433 var other = try self.unmanaged.cloneContext(allocator, ctx);
434 return other.promoteContext(allocator, ctx);
435 }
436
437 /// Set the map to an empty state, making deinitialization a no-op, and
438 /// returning a copy of the original.
439 pub fn move(self: *Self) Self {
440 self.unmanaged.pointer_stability.assertUnlocked();
441 const result = self.*;
442 self.unmanaged = .empty;
443 return result;
444 }
445
446 /// Recomputes stored hashes and rebuilds the key indexes. If the
447 /// underlying keys have been modified directly, call this method to
448 /// recompute the denormalized metadata necessary for the operation of
449 /// the methods of this map that lookup entries by key.
450 ///
451 /// One use case for this is directly calling `entries.resize()` to grow
452 /// the underlying storage, and then setting the `keys` and `values`
453 /// directly without going through the methods of this map.
454 ///
455 /// The time complexity of this operation is O(n).
456 pub fn reIndex(self: *Self) !void {
457 return self.unmanaged.reIndexContext(self.allocator, self.ctx);
458 }
459
460 /// Sorts the entries and then rebuilds the index.
461 /// `sort_ctx` must have this method:
462 /// `fn lessThan(ctx: @TypeOf(ctx), a_index: usize, b_index: usize) bool`
463 /// Uses a stable sorting algorithm.
464 pub fn sort(self: *Self, sort_ctx: anytype) void {
465 return self.unmanaged.sortContext(sort_ctx, self.ctx);
466 }
467
468 /// Sorts the entries and then rebuilds the index.
469 /// `sort_ctx` must have this method:
470 /// `fn lessThan(ctx: @TypeOf(ctx), a_index: usize, b_index: usize) bool`
471 /// Uses an unstable sorting algorithm.
472 pub fn sortUnstable(self: *Self, sort_ctx: anytype) void {
473 return self.unmanaged.sortUnstableContext(sort_ctx, self.ctx);
474 }
475
476 /// Shrinks the underlying `Entry` array to `new_len` elements and
477 /// discards any associated index entries. Keeps capacity the same.
478 ///
479 /// Asserts the discarded entries remain initialized and capable of
480 /// performing hash and equality checks. Any deinitialization of
481 /// discarded entries must take place *after* calling this function.
482 pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void {
483 return self.unmanaged.shrinkRetainingCapacityContext(new_len, self.ctx);
484 }
485
486 /// Shrinks the underlying `Entry` array to `new_len` elements and
487 /// discards any associated index entries. Reduces allocated capacity.
488 ///
489 /// Asserts the discarded entries remain initialized and capable of
490 /// performing hash and equality checks. It is a bug to call this
491 /// function if the discarded entries require deinitialization. For
492 /// that use case, `shrinkRetainingCapacity` can be used instead.
493 pub fn shrinkAndFree(self: *Self, new_len: usize) void {
494 return self.unmanaged.shrinkAndFreeContext(self.allocator, new_len, self.ctx);
495 }
496
497 /// Removes the last inserted `Entry` in the hash map and returns it if count is nonzero.
498 /// Otherwise returns null.
499 pub fn pop(self: *Self) ?KV {
500 return self.unmanaged.popContext(self.ctx);
501 }
502 };
503}
44/// Deprecated; use `Custom`.
45pub const ArrayHashMap = Custom;
50446
50547/// A hash table of keys and values, each stored sequentially.
50648///
......@@ -522,11 +64,11 @@ pub fn ArrayHashMapWithAllocator(
52264///
52365/// This type is designed to have low overhead for small numbers of entries. When
52466/// `store_hash` is `false` and the number of entries in the map is less than 9,
525/// the overhead cost of using `ArrayHashMapUnmanaged` rather than `std.ArrayList` is
67/// the overhead cost of using `ArrayHashMap` rather than `std.ArrayList` is
52668/// only a single pointer-sized integer.
52769///
52870/// Default initialization of this struct is deprecated; use `.empty` instead.
529pub fn ArrayHashMapUnmanaged(
71pub fn Custom(
53072 comptime K: type,
53173 comptime V: type,
53274 /// A namespace that provides these two functions:
......@@ -605,9 +147,6 @@ pub fn ArrayHashMapUnmanaged(
605147 index: usize,
606148 };
607149
608 /// The ArrayHashMap type using the same settings as this managed map.
609 pub const Managed = ArrayHashMap(K, V, Context, store_hash);
610
611150 /// Some functions require a context only if hashes are not stored.
612151 /// To keep the api simple, this type is only used internally.
613152 const ByIndexContext = if (store_hash) void else Context;
......@@ -626,21 +165,6 @@ pub fn ArrayHashMapUnmanaged(
626165
627166 const Oom = Allocator.Error;
628167
629 /// Convert from an unmanaged map to a managed map. After calling this,
630 /// the promoted map should no longer be used.
631 pub fn promote(self: Self, gpa: Allocator) Managed {
632 if (@sizeOf(Context) != 0)
633 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call promoteContext instead.");
634 return self.promoteContext(gpa, undefined);
635 }
636 pub fn promoteContext(self: Self, gpa: Allocator, ctx: Context) Managed {
637 return .{
638 .unmanaged = self,
639 .allocator = gpa,
640 .ctx = ctx,
641 };
642 }
643
644168 pub fn init(gpa: Allocator, key_list: []const K, value_list: []const V) Oom!Self {
645169 var self: Self = .{};
646170 errdefer self.deinit(gpa);
......@@ -2189,35 +1713,37 @@ const IndexHeader = struct {
21891713};
21901714
21911715test "basic hash map usage" {
2192 var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);
2193 defer map.deinit();
1716 const gpa = testing.allocator;
21941717
2195 try testing.expect((try map.fetchPut(1, 11)) == null);
2196 try testing.expect((try map.fetchPut(2, 22)) == null);
2197 try testing.expect((try map.fetchPut(3, 33)) == null);
2198 try testing.expect((try map.fetchPut(4, 44)) == null);
1718 var map: Auto(i32, i32) = .empty;
1719 defer map.deinit(gpa);
1720
1721 try testing.expect((try map.fetchPut(gpa, 1, 11)) == null);
1722 try testing.expect((try map.fetchPut(gpa, 2, 22)) == null);
1723 try testing.expect((try map.fetchPut(gpa, 3, 33)) == null);
1724 try testing.expect((try map.fetchPut(gpa, 4, 44)) == null);
21991725
2200 try map.putNoClobber(5, 55);
2201 try testing.expect((try map.fetchPut(5, 66)).?.value == 55);
2202 try testing.expect((try map.fetchPut(5, 55)).?.value == 66);
1726 try map.putNoClobber(gpa, 5, 55);
1727 try testing.expect((try map.fetchPut(gpa, 5, 66)).?.value == 55);
1728 try testing.expect((try map.fetchPut(gpa, 5, 55)).?.value == 66);
22031729
2204 const gop1 = try map.getOrPut(5);
1730 const gop1 = try map.getOrPut(gpa, 5);
22051731 try testing.expect(gop1.found_existing == true);
22061732 try testing.expect(gop1.value_ptr.* == 55);
22071733 try testing.expect(gop1.index == 4);
22081734 gop1.value_ptr.* = 77;
22091735 try testing.expect(map.getEntry(5).?.value_ptr.* == 77);
22101736
2211 const gop2 = try map.getOrPut(99);
1737 const gop2 = try map.getOrPut(gpa, 99);
22121738 try testing.expect(gop2.found_existing == false);
22131739 try testing.expect(gop2.index == 5);
22141740 gop2.value_ptr.* = 42;
22151741 try testing.expect(map.getEntry(99).?.value_ptr.* == 42);
22161742
2217 const gop3 = try map.getOrPutValue(5, 5);
1743 const gop3 = try map.getOrPutValue(gpa, 5, 5);
22181744 try testing.expect(gop3.value_ptr.* == 77);
22191745
2220 const gop4 = try map.getOrPutValue(100, 41);
1746 const gop4 = try map.getOrPutValue(gpa, 100, 41);
22211747 try testing.expect(gop4.value_ptr.* == 41);
22221748
22231749 try testing.expect(map.contains(2));
......@@ -2234,7 +1760,7 @@ test "basic hash map usage" {
22341760
22351761 // Since we've used `swapRemove` above, the index of this entry should remain unchanged.
22361762 try testing.expect(map.getIndex(100).? == 1);
2237 const gop5 = try map.getOrPut(5);
1763 const gop5 = try map.getOrPut(gpa, 5);
22381764 try testing.expect(gop5.found_existing == true);
22391765 try testing.expect(gop5.value_ptr.* == 77);
22401766 try testing.expect(gop5.index == 4);
......@@ -2247,7 +1773,7 @@ test "basic hash map usage" {
22471773 try testing.expect(map.orderedRemove(100) == false);
22481774 try testing.expect(map.getEntry(100) == null);
22491775 try testing.expect(map.get(100) == null);
2250 const gop6 = try map.getOrPut(5);
1776 const gop6 = try map.getOrPut(gpa, 5);
22511777 try testing.expect(gop6.found_existing == true);
22521778 try testing.expect(gop6.value_ptr.* == 77);
22531779 try testing.expect(gop6.index == 3);
......@@ -2256,15 +1782,17 @@ test "basic hash map usage" {
22561782}
22571783
22581784test "iterator hash map" {
2259 var reset_map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);
2260 defer reset_map.deinit();
1785 const gpa = testing.allocator;
1786
1787 var reset_map: Auto(i32, i32) = .empty;
1788 defer reset_map.deinit(gpa);
22611789
22621790 // test ensureTotalCapacity with a 0 parameter
2263 try reset_map.ensureTotalCapacity(0);
1791 try reset_map.ensureTotalCapacity(gpa, 0);
22641792
2265 try reset_map.putNoClobber(0, 11);
2266 try reset_map.putNoClobber(1, 22);
2267 try reset_map.putNoClobber(2, 33);
1793 try reset_map.putNoClobber(gpa, 0, 11);
1794 try reset_map.putNoClobber(gpa, 1, 22);
1795 try reset_map.putNoClobber(gpa, 2, 33);
22681796
22691797 const keys = [_]i32{
22701798 0, 2, 1,
......@@ -2312,10 +1840,12 @@ test "iterator hash map" {
23121840}
23131841
23141842test "ensure capacity" {
2315 var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);
2316 defer map.deinit();
1843 const gpa = testing.allocator;
23171844
2318 try map.ensureTotalCapacity(20);
1845 var map: Auto(i32, i32) = .empty;
1846 defer map.deinit(gpa);
1847
1848 try map.ensureTotalCapacity(gpa, 20);
23191849 const initial_capacity = map.capacity();
23201850 try testing.expect(initial_capacity >= 20);
23211851 var i: i32 = 0;
......@@ -2329,23 +1859,25 @@ test "ensure capacity" {
23291859test "ensure capacity leak" {
23301860 try testing.checkAllAllocationFailures(std.testing.allocator, struct {
23311861 pub fn f(allocator: Allocator) !void {
2332 var map = AutoArrayHashMap(i32, i32).init(allocator);
2333 defer map.deinit();
1862 var map: Auto(i32, i32) = .empty;
1863 defer map.deinit(allocator);
23341864
23351865 var i: i32 = 0;
23361866 // put more than `linear_scan_max` in so index_header gets allocated.
2337 while (i <= 20) : (i += 1) try map.put(i, i);
1867 while (i <= 20) : (i += 1) try map.put(allocator, i, i);
23381868 }
23391869 }.f, .{});
23401870}
23411871
23421872test "big map" {
2343 var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);
2344 defer map.deinit();
1873 const gpa = testing.allocator;
1874
1875 var map: Auto(i32, i32) = .empty;
1876 defer map.deinit(gpa);
23451877
23461878 var i: i32 = 0;
23471879 while (i < 8) : (i += 1) {
2348 try map.put(i, i + 10);
1880 try map.put(gpa, i, i + 10);
23491881 }
23501882
23511883 i = 0;
......@@ -2358,7 +1890,7 @@ test "big map" {
23581890
23591891 i = 4;
23601892 while (i < 12) : (i += 1) {
2361 try map.put(i, i + 12);
1893 try map.put(gpa, i, i + 12);
23621894 }
23631895
23641896 i = 0;
......@@ -2393,17 +1925,19 @@ test "big map" {
23931925}
23941926
23951927test "clone" {
2396 var original = AutoArrayHashMap(i32, i32).init(std.testing.allocator);
2397 defer original.deinit();
1928 const gpa = testing.allocator;
1929
1930 var original: Auto(i32, i32) = .empty;
1931 defer original.deinit(gpa);
23981932
23991933 // put more than `linear_scan_max` so we can test that the index header is properly cloned
24001934 var i: u8 = 0;
24011935 while (i < 10) : (i += 1) {
2402 try original.putNoClobber(i, i * 10);
1936 try original.putNoClobber(gpa, i, i * 10);
24031937 }
24041938
2405 var copy = try original.clone();
2406 defer copy.deinit();
1939 var copy = try original.clone(gpa);
1940 defer copy.deinit(gpa);
24071941
24081942 i = 0;
24091943 while (i < 10) : (i += 1) {
......@@ -2419,16 +1953,18 @@ test "clone" {
24191953}
24201954
24211955test "shrink" {
2422 var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);
2423 defer map.deinit();
1956 const gpa = testing.allocator;
1957
1958 var map: Auto(i32, i32) = .empty;
1959 defer map.deinit(gpa);
24241960
24251961 // This test is more interesting if we insert enough entries to allocate the index header.
24261962 const num_entries = 200;
24271963 var i: i32 = 0;
24281964 while (i < num_entries) : (i += 1)
2429 try testing.expect((try map.fetchPut(i, i * 10)) == null);
1965 try testing.expect((try map.fetchPut(gpa, i, i * 10)) == null);
24301966
2431 try testing.expect(map.unmanaged.index_header != null);
1967 try testing.expect(map.index_header != null);
24321968 try testing.expect(map.count() == num_entries);
24331969
24341970 // Test `shrinkRetainingCapacity`.
......@@ -2437,7 +1973,7 @@ test "shrink" {
24371973 try testing.expect(map.capacity() >= num_entries);
24381974 i = 0;
24391975 while (i < num_entries) : (i += 1) {
2440 const gop = try map.getOrPut(i);
1976 const gop = try map.getOrPut(gpa, i);
24411977 if (i < 17) {
24421978 try testing.expect(gop.found_existing == true);
24431979 try testing.expect(gop.value_ptr.* == i * 10);
......@@ -2445,12 +1981,12 @@ test "shrink" {
24451981 }
24461982
24471983 // Test `shrinkAndFree`.
2448 map.shrinkAndFree(15);
1984 map.shrinkAndFree(gpa, 15);
24491985 try testing.expect(map.count() == 15);
24501986 try testing.expect(map.capacity() == 15);
24511987 i = 0;
24521988 while (i < num_entries) : (i += 1) {
2453 const gop = try map.getOrPut(i);
1989 const gop = try map.getOrPut(gpa, i);
24541990 if (i < 15) {
24551991 try testing.expect(gop.found_existing == true);
24561992 try testing.expect(gop.value_ptr.* == i * 10);
......@@ -2459,15 +1995,17 @@ test "shrink" {
24591995}
24601996
24611997test "pop()" {
2462 var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);
2463 defer map.deinit();
1998 const gpa = testing.allocator;
1999
2000 var map: Auto(i32, i32) = .empty;
2001 defer map.deinit(gpa);
24642002
24652003 // Insert just enough entries so that the map expands. Afterwards,
24662004 // pop all entries out of the map.
24672005
24682006 var i: i32 = 0;
24692007 while (i < 9) : (i += 1) {
2470 try testing.expect((try map.fetchPut(i, i)) == null);
2008 try testing.expect((try map.fetchPut(gpa, i, i)) == null);
24712009 }
24722010
24732011 while (map.pop()) |pop| {
......@@ -2479,31 +2017,33 @@ test "pop()" {
24792017}
24802018
24812019test "reIndex" {
2482 var map = ArrayHashMap(i32, i32, AutoContext(i32), true).init(std.testing.allocator);
2483 defer map.deinit();
2020 const gpa = testing.allocator;
2021
2022 var map: Custom(i32, i32, AutoContext(i32), true) = .empty;
2023 defer map.deinit(gpa);
24842024
24852025 // Populate via the API.
24862026 const num_indexed_entries = 200;
24872027 var i: i32 = 0;
24882028 while (i < num_indexed_entries) : (i += 1)
2489 try testing.expect((try map.fetchPut(i, i * 10)) == null);
2029 try testing.expect((try map.fetchPut(gpa, i, i * 10)) == null);
24902030
24912031 // Make sure we allocated an index header.
2492 try testing.expect(map.unmanaged.index_header != null);
2032 try testing.expect(map.index_header != null);
24932033
24942034 // Now write to the arrays directly.
24952035 const num_unindexed_entries = 20;
2496 try map.unmanaged.entries.resize(std.testing.allocator, num_indexed_entries + num_unindexed_entries);
2036 try map.entries.resize(std.testing.allocator, num_indexed_entries + num_unindexed_entries);
24972037 for (map.keys()[num_indexed_entries..], map.values()[num_indexed_entries..], num_indexed_entries..) |*key, *value, j| {
24982038 key.* = @intCast(j);
24992039 value.* = @intCast(j * 10);
25002040 }
25012041
25022042 // After reindexing, we should see everything.
2503 try map.reIndex();
2043 try map.reIndex(gpa);
25042044 i = 0;
25052045 while (i < num_indexed_entries + num_unindexed_entries) : (i += 1) {
2506 const gop = try map.getOrPut(i);
2046 const gop = try map.getOrPut(gpa, i);
25072047 try testing.expect(gop.found_existing == true);
25082048 try testing.expect(gop.value_ptr.* == i * 10);
25092049 try testing.expect(gop.index == i);
......@@ -2511,23 +2051,20 @@ test "reIndex" {
25112051}
25122052
25132053test "auto store_hash" {
2514 const HasCheapEql = AutoArrayHashMap(i32, i32);
2515 const HasExpensiveEql = AutoArrayHashMap([32]i32, i32);
2054 const HasCheapEql = Auto(i32, i32);
2055 const HasExpensiveEql = Auto([32]i32, i32);
25162056 try testing.expect(@FieldType(HasCheapEql.Data, "hash") == void);
25172057 try testing.expect(@FieldType(HasExpensiveEql.Data, "hash") != void);
2518
2519 const HasCheapEqlUn = AutoArrayHashMapUnmanaged(i32, i32);
2520 const HasExpensiveEqlUn = AutoArrayHashMapUnmanaged([32]i32, i32);
2521 try testing.expect(@FieldType(HasCheapEqlUn.Data, "hash") == void);
2522 try testing.expect(@FieldType(HasExpensiveEqlUn.Data, "hash") != void);
25232058}
25242059
25252060test "sort" {
2526 var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);
2527 defer map.deinit();
2061 const gpa = testing.allocator;
2062
2063 var map: Auto(i32, i32) = .empty;
2064 defer map.deinit(gpa);
25282065
25292066 for ([_]i32{ 8, 3, 12, 10, 2, 4, 9, 5, 6, 13, 14, 15, 16, 1, 11, 17, 7 }) |x| {
2530 try map.put(x, x * 3);
2067 try map.put(gpa, x, x * 3);
25312068 }
25322069
25332070 const C = struct {
......@@ -2549,15 +2086,17 @@ test "sort" {
25492086}
25502087
25512088test "0 sized key" {
2552 var map = AutoArrayHashMap(u0, i32).init(std.testing.allocator);
2553 defer map.deinit();
2089 const gpa = testing.allocator;
2090
2091 var map: Auto(u0, i32) = .empty;
2092 defer map.deinit(gpa);
25542093
25552094 try testing.expectEqual(map.get(0), null);
25562095
2557 try map.put(0, 5);
2096 try map.put(gpa, 0, 5);
25582097 try testing.expectEqual(map.get(0), 5);
25592098
2560 try map.put(0, 10);
2099 try map.put(gpa, 0, 10);
25612100 try testing.expectEqual(map.get(0), 10);
25622101
25632102 try testing.expectEqual(map.swapRemove(0), true);
......@@ -2565,12 +2104,14 @@ test "0 sized key" {
25652104}
25662105
25672106test "0 sized key and 0 sized value" {
2568 var map = AutoArrayHashMap(u0, u0).init(std.testing.allocator);
2569 defer map.deinit();
2107 const gpa = testing.allocator;
2108
2109 var map: Auto(u0, u0) = .empty;
2110 defer map.deinit(gpa);
25702111
25712112 try testing.expectEqual(map.get(0), null);
25722113
2573 try map.put(0, 0);
2114 try map.put(gpa, 0, 0);
25742115 try testing.expectEqual(map.get(0), 0);
25752116
25762117 try testing.expectEqual(map.swapRemove(0), true);
......@@ -2580,7 +2121,7 @@ test "0 sized key and 0 sized value" {
25802121test "setKey storehash true" {
25812122 const gpa = std.testing.allocator;
25822123
2583 var map: ArrayHashMapUnmanaged(i32, i32, AutoContext(i32), true) = .empty;
2124 var map: ArrayHashMap(i32, i32, AutoContext(i32), true) = .empty;
25842125 defer map.deinit(gpa);
25852126
25862127 try map.put(gpa, 12, 34);
......@@ -2596,7 +2137,7 @@ test "setKey storehash true" {
25962137test "setKey storehash false" {
25972138 const gpa = std.testing.allocator;
25982139
2599 var map: ArrayHashMapUnmanaged(i32, i32, AutoContext(i32), false) = .empty;
2140 var map: ArrayHashMap(i32, i32, AutoContext(i32), false) = .empty;
26002141 defer map.deinit(gpa);
26012142
26022143 try map.put(gpa, 12, 34);
......@@ -2691,7 +2232,7 @@ pub fn getAutoHashStratFn(comptime K: type, comptime Context: type, comptime str
26912232test "orderedRemoveAtMany" {
26922233 const gpa = testing.allocator;
26932234
2694 var map: AutoArrayHashMapUnmanaged(usize, void) = .empty;
2235 var map: Auto(usize, void) = .empty;
26952236 defer map.deinit(gpa);
26962237
26972238 for (0..10) |n| {
lib/std/json/Stringify.zig+3-3
......@@ -770,9 +770,9 @@ fn testBasicWriteStream(w: *Stringify) !void {
770770}
771771
772772fn getJsonObject(allocator: std.mem.Allocator) !std.json.Value {
773 var v: std.json.Value = .{ .object = std.json.ObjectMap.init(allocator) };
774 try v.object.put("one", std.json.Value{ .integer = @as(i64, @intCast(1)) });
775 try v.object.put("two", std.json.Value{ .float = 2.0 });
773 var v: std.json.Value = .{ .object = .empty };
774 try v.object.put(allocator, "one", std.json.Value{ .integer = @as(i64, @intCast(1)) });
775 try v.object.put(allocator, "two", std.json.Value{ .float = 2.0 });
776776 return v;
777777}
778778
lib/std/json/dynamic.zig+4-4
......@@ -1,7 +1,7 @@
11const std = @import("std");
22const debug = std.debug;
33const ArenaAllocator = std.heap.ArenaAllocator;
4const StringArrayHashMap = std.StringArrayHashMap;
4const StringArrayHashMap = std.array_hash_map.String;
55const Allocator = std.mem.Allocator;
66const json = std.json;
77
......@@ -103,10 +103,10 @@ pub const Value = union(enum) {
103103
104104 .object_begin => {
105105 switch (try source.nextAllocMax(allocator, .alloc_always, options.max_value_len.?)) {
106 .object_end => return try handleCompleteValue(&stack, allocator, source, Value{ .object = ObjectMap.init(allocator) }, options) orelse continue,
106 .object_end => return try handleCompleteValue(&stack, allocator, source, Value{ .object = .empty }, options) orelse continue,
107107 .allocated_string => |key| {
108108 try stack.appendSlice(&[_]Value{
109 Value{ .object = ObjectMap.init(allocator) },
109 Value{ .object = .empty },
110110 Value{ .string = key },
111111 });
112112 },
......@@ -145,7 +145,7 @@ fn handleCompleteValue(stack: *Array, allocator: Allocator, source: anytype, val
145145 // stack: [..., .object]
146146 var object = &stack.items[stack.items.len - 1].object;
147147
148 const gop = try object.getOrPut(key);
148 const gop = try object.getOrPut(allocator, key);
149149 if (gop.found_existing) {
150150 switch (options.duplicate_field_behavior) {
151151 .use_first => {},
lib/std/json/dynamic_test.zig+4-3
......@@ -220,14 +220,15 @@ test "Value with duplicate fields" {
220220}
221221
222222test "Value.jsonStringify" {
223 const gpa = testing.allocator;
223224 var vals = [_]Value{
224225 .{ .integer = 1 },
225226 .{ .integer = 2 },
226227 .{ .number_string = "3" },
227228 };
228 var obj = ObjectMap.init(testing.allocator);
229 defer obj.deinit();
230 try obj.putNoClobber("a", .{ .string = "b" });
229 var obj: ObjectMap = .empty;
230 defer obj.deinit(gpa);
231 try obj.putNoClobber(gpa, "a", .{ .string = "b" });
231232 const array = [_]Value{
232233 .null,
233234 .{ .bool = true },
lib/std/std.zig+7-6
......@@ -1,7 +1,3 @@
1pub const ArrayHashMap = array_hash_map.ArrayHashMap;
2pub const ArrayHashMapUnmanaged = array_hash_map.ArrayHashMapUnmanaged;
3pub const AutoArrayHashMap = array_hash_map.AutoArrayHashMap;
4pub const AutoArrayHashMapUnmanaged = array_hash_map.AutoArrayHashMapUnmanaged;
51pub const AutoHashMap = hash_map.AutoHashMap;
62pub const AutoHashMapUnmanaged = hash_map.AutoHashMapUnmanaged;
73pub const BitStack = @import("BitStack.zig");
......@@ -31,14 +27,19 @@ pub const SinglyLinkedList = @import("SinglyLinkedList.zig");
3127pub const StaticBitSet = bit_set.StaticBitSet;
3228pub const StringHashMap = hash_map.StringHashMap;
3329pub const StringHashMapUnmanaged = hash_map.StringHashMapUnmanaged;
34pub const StringArrayHashMap = array_hash_map.StringArrayHashMap;
35pub const StringArrayHashMapUnmanaged = array_hash_map.StringArrayHashMapUnmanaged;
3630pub const Target = @import("Target.zig");
3731pub const Thread = @import("Thread.zig");
3832pub const Treap = @import("treap.zig").Treap;
3933pub const Tz = tz.Tz;
4034pub const Uri = @import("Uri.zig");
4135
36/// Deprecated; use `array_hash_map.Custom`.
37pub const ArrayHashMapUnmanaged = array_hash_map.Custom;
38/// Deprecated; use `array_hash_map.Auto`.
39pub const AutoArrayHashMapUnmanaged = array_hash_map.Auto;
40/// Deprecated; use `array_hash_map.String`.
41pub const StringArrayHashMapUnmanaged = array_hash_map.String;
42
4243/// A contiguous, growable list of items in memory. This is a wrapper around a
4344/// slice of `T` values.
4445///
lib/std/zig/AstGen.zig+3-3
......@@ -1779,8 +1779,8 @@ fn structInitExpr(
17791779 var sfba = std.heap.stackFallback(256, astgen.arena);
17801780 const sfba_allocator = sfba.get();
17811781
1782 var duplicate_names = std.AutoArrayHashMap(Zir.NullTerminatedString, ArrayList(Ast.TokenIndex)).init(sfba_allocator);
1783 try duplicate_names.ensureTotalCapacity(@intCast(struct_init.ast.fields.len));
1782 var duplicate_names: std.array_hash_map.Auto(Zir.NullTerminatedString, ArrayList(Ast.TokenIndex)) = .empty;
1783 try duplicate_names.ensureTotalCapacity(sfba_allocator, @intCast(struct_init.ast.fields.len));
17841784
17851785 // When there aren't errors, use this to avoid a second iteration.
17861786 var any_duplicate = false;
......@@ -1789,7 +1789,7 @@ fn structInitExpr(
17891789 const name_token = tree.firstToken(field) - 2;
17901790 const name_index = try astgen.identAsString(name_token);
17911791
1792 const gop = try duplicate_names.getOrPut(name_index);
1792 const gop = try duplicate_names.getOrPut(sfba_allocator, name_index);
17931793
17941794 if (gop.found_existing) {
17951795 try gop.value_ptr.append(sfba_allocator, name_token);
src/InternPool.zig+3-3
......@@ -10552,7 +10552,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo
1055210552 count: usize = 0,
1055310553 bytes: usize = 0,
1055410554 };
10555 var counts = std.AutoArrayHashMap(Tag, TagStats).init(arena);
10555 var counts: std.array_hash_map.Auto(Tag, TagStats) = .empty;
1055610556 for (ip.locals) |*local| {
1055710557 // Early check for length 0, because `view()` is invalid if capacity is 0
1055810558 if (local.mutate.items.len == 0) continue;
......@@ -10563,7 +10563,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo
1056310563 items.items(.tag)[0..local.mutate.items.len],
1056410564 items.items(.data)[0..local.mutate.items.len],
1056510565 ) |tag, data| {
10566 const gop = try counts.getOrPut(tag);
10566 const gop = try counts.getOrPut(arena, tag);
1056710567 if (!gop.found_existing) gop.value_ptr.* = .{};
1056810568 gop.value_ptr.count += 1;
1056910569 gop.value_ptr.bytes += 1 + 4 + @as(usize, switch (tag) {
......@@ -10799,7 +10799,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo
1079910799 }
1080010800 }
1080110801 const SortContext = struct {
10802 map: *std.AutoArrayHashMap(Tag, TagStats),
10802 map: *std.array_hash_map.Auto(Tag, TagStats),
1080310803 pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {
1080410804 const values = ctx.map.values();
1080510805 return values[a_index].bytes > values[b_index].bytes;
src/libs/glibc.zig+3-3
......@@ -795,7 +795,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
795795 //
796796 // If we don't handle this, we end up writing the default `lgammal` symbol for version 2.33
797797 // twice, which causes a "duplicate symbol" assembler error.
798 var versions_written = std.AutoArrayHashMap(Version, void).init(arena);
798 var versions_written: std.array_hash_map.Auto(Version, void) = .empty;
799799
800800 var inc_reader: Io.Reader = .fixed(metadata.inclusions);
801801
......@@ -859,7 +859,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
859859 }
860860
861861 versions_written.clearRetainingCapacity();
862 try versions_written.ensureTotalCapacity(versions_len);
862 try versions_written.ensureTotalCapacity(arena, versions_len);
863863
864864 {
865865 var ver_buf_i: u8 = 0;
......@@ -1035,7 +1035,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
10351035 }
10361036
10371037 versions_written.clearRetainingCapacity();
1038 try versions_written.ensureTotalCapacity(versions_len);
1038 try versions_written.ensureTotalCapacity(arena, versions_len);
10391039
10401040 {
10411041 var ver_buf_i: u8 = 0;
src/libs/mingw/implib.zig+3-3
......@@ -36,14 +36,14 @@ pub fn writeCoffArchive(
3636 var long_names: StringTable = .{};
3737 defer long_names.deinit(allocator);
3838
39 var symbol_to_member_index = std.StringArrayHashMap(usize).init(allocator);
40 defer symbol_to_member_index.deinit();
39 var symbol_to_member_index: std.array_hash_map.String(usize) = .empty;
40 defer symbol_to_member_index.deinit(allocator);
4141 var string_table_len: usize = 0;
4242 var num_symbols: usize = 0;
4343
4444 for (members.list.items, 0..) |member, i| {
4545 for (member.symbol_names_for_import_lib) |symbol_name| {
46 const gop_result = try symbol_to_member_index.getOrPut(symbol_name);
46 const gop_result = try symbol_to_member_index.getOrPut(allocator, symbol_name);
4747 // When building the symbol map, ignore duplicate symbol names.
4848 // This can happen in cases like (using .def file syntax):
4949 // _foo
src/libs/musl.zig+6-6
......@@ -90,10 +90,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
9090 // Even a .s file can substitute for a .c file.
9191 const target = comp.getTarget();
9292 const arch_name = std.zig.target.muslArchName(target.cpu.arch, target.abi);
93 var source_table = std.StringArrayHashMap(Ext).init(comp.gpa);
94 defer source_table.deinit();
93 var source_table: std.array_hash_map.String(Ext) = .empty;
94 defer source_table.deinit(gpa);
9595
96 try source_table.ensureTotalCapacity(compat_time32_files.len + src_files.len);
96 try source_table.ensureTotalCapacity(gpa, compat_time32_files.len + src_files.len);
9797
9898 for (src_files) |src_file| {
9999 try addSrcFile(arena, &source_table, src_file);
......@@ -107,10 +107,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
107107 }
108108 }
109109
110 var c_source_files = std.array_list.Managed(Compilation.CSourceFile).init(comp.gpa);
110 var c_source_files = std.array_list.Managed(Compilation.CSourceFile).init(gpa);
111111 defer c_source_files.deinit();
112112
113 var override_path = std.array_list.Managed(u8).init(comp.gpa);
113 var override_path = std.array_list.Managed(u8).init(gpa);
114114 defer override_path.deinit();
115115
116116 const s = path.sep_str;
......@@ -349,7 +349,7 @@ const Ext = enum {
349349 o3,
350350};
351351
352fn addSrcFile(arena: Allocator, source_table: *std.StringArrayHashMap(Ext), file_path: []const u8) !void {
352fn addSrcFile(arena: Allocator, source_table: *std.array_hash_map.String(Ext), file_path: []const u8) !void {
353353 const ext: Ext = ext: {
354354 if (mem.endsWith(u8, file_path, ".c")) {
355355 if (mem.startsWith(u8, file_path, "musl/src/string/") or
src/link/Elf.zig+8-8
......@@ -881,10 +881,10 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
881881 self.rela_plt.clearRetainingCapacity();
882882
883883 if (self.zigObjectPtr()) |zo| {
884 var undefs: std.AutoArrayHashMap(SymbolResolver.Index, std.array_list.Managed(Ref)) = .init(gpa);
884 var undefs: std.array_hash_map.Auto(SymbolResolver.Index, std.array_list.Managed(Ref)) = .empty;
885885 defer {
886886 for (undefs.values()) |*refs| refs.deinit();
887 undefs.deinit();
887 undefs.deinit(gpa);
888888 }
889889
890890 var has_reloc_errors = false;
......@@ -1332,10 +1332,10 @@ fn scanRelocs(self: *Elf) !void {
13321332 const gpa = self.base.comp.gpa;
13331333 const shared_objects = self.shared_objects.values();
13341334
1335 var undefs: std.AutoArrayHashMap(SymbolResolver.Index, std.array_list.Managed(Ref)) = .init(gpa);
1335 var undefs: std.array_hash_map.Auto(SymbolResolver.Index, std.array_list.Managed(Ref)) = .empty;
13361336 defer {
13371337 for (undefs.values()) |*refs| refs.deinit();
1338 undefs.deinit();
1338 undefs.deinit(gpa);
13391339 }
13401340
13411341 var has_reloc_errors = false;
......@@ -1748,12 +1748,12 @@ pub fn deleteExport(
17481748fn checkDuplicates(self: *Elf) !void {
17491749 const gpa = self.base.comp.gpa;
17501750
1751 var dupes = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(File.Index)).init(gpa);
1751 var dupes: std.array_hash_map.Auto(SymbolResolver.Index, std.ArrayList(File.Index)) = .empty;
17521752 defer {
17531753 for (dupes.values()) |*list| {
17541754 list.deinit(gpa);
17551755 }
1756 dupes.deinit();
1756 dupes.deinit(gpa);
17571757 }
17581758
17591759 if (self.zigObjectPtr()) |zig_object| {
......@@ -2992,10 +2992,10 @@ fn allocateSpecialPhdrs(self: *Elf) void {
29922992fn writeAtoms(self: *Elf) !void {
29932993 const gpa = self.base.comp.gpa;
29942994
2995 var undefs: std.AutoArrayHashMap(SymbolResolver.Index, std.array_list.Managed(Ref)) = .init(gpa);
2995 var undefs: std.array_hash_map.Auto(SymbolResolver.Index, std.array_list.Managed(Ref)) = .empty;
29962996 defer {
29972997 for (undefs.values()) |*refs| refs.deinit();
2998 undefs.deinit();
2998 undefs.deinit(gpa);
29992999 }
30003000
30013001 var buffer: std.Io.Writer.Allocating = .init(gpa);
src/link/Elf/Atom.zig+1-1
......@@ -605,7 +605,7 @@ fn reportUndefined(
605605 .object => |x| x.symbols_resolver.items[rel.r_sym() - x.first_global.?],
606606 inline else => |x| x.symbols_resolver.items[rel.r_sym()],
607607 };
608 const gop = try undefs.getOrPut(idx);
608 const gop = try undefs.getOrPut(gpa, idx);
609609 if (!gop.found_existing) {
610610 gop.value_ptr.* = std.array_list.Managed(Elf.Ref).init(gpa);
611611 }
src/link/Elf/Object.zig+4-2
......@@ -753,6 +753,8 @@ pub fn markImportsExports(self: *Object, elf_file: *Elf) void {
753753}
754754
755755pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {
756 const gpa = elf_file.base.comp.gpa;
757
756758 const first_global = self.first_global orelse return;
757759 for (0..self.globals().len) |i| {
758760 const esym_idx = first_global + i;
......@@ -772,11 +774,11 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutO
772774 if (!atom_ptr.alive) continue;
773775 }
774776
775 const gop = try dupes.getOrPut(self.symbols_resolver.items[i]);
777 const gop = try dupes.getOrPut(gpa, self.symbols_resolver.items[i]);
776778 if (!gop.found_existing) {
777779 gop.value_ptr.* = .empty;
778780 }
779 try gop.value_ptr.append(elf_file.base.comp.gpa, self.index);
781 try gop.value_ptr.append(gpa, self.index);
780782 }
781783}
782784
src/link/Elf/ZigObject.zig+3-1
......@@ -710,6 +710,8 @@ pub fn markImportsExports(self: *ZigObject, elf_file: *Elf) void {
710710}
711711
712712pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {
713 const gpa = elf_file.base.comp.gpa;
714
713715 for (self.global_symbols.items, 0..) |index, i| {
714716 const esym = self.symtab.items(.elf_sym)[index];
715717 const shndx = self.symtab.items(.shndx)[index];
......@@ -727,7 +729,7 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O
727729 if (!atom_ptr.alive) continue;
728730 }
729731
730 const gop = try dupes.getOrPut(self.symbols_resolver.items[i]);
732 const gop = try dupes.getOrPut(gpa, self.symbols_resolver.items[i]);
731733 if (!gop.found_existing) {
732734 gop.value_ptr.* = .empty;
733735 }
src/link/MachO/InternalObject.zig+6-6
......@@ -164,8 +164,8 @@ pub fn resolveBoundarySymbols(self: *InternalObject, macho_file: *MachO) !void {
164164 defer tracy.end();
165165
166166 const gpa = macho_file.base.comp.gpa;
167 var boundary_symbols = std.StringArrayHashMap(MachO.Ref).init(gpa);
168 defer boundary_symbols.deinit();
167 var boundary_symbols: std.array_hash_map.String(MachO.Ref) = .empty;
168 defer boundary_symbols.deinit(gpa);
169169
170170 for (macho_file.objects.items) |index| {
171171 const object = macho_file.getFile(index).?.object;
......@@ -180,7 +180,7 @@ pub fn resolveBoundarySymbols(self: *InternalObject, macho_file: *MachO) !void {
180180 mem.startsWith(u8, name, "section$start$") or
181181 mem.startsWith(u8, name, "section$end$"))
182182 {
183 const gop = try boundary_symbols.getOrPut(name);
183 const gop = try boundary_symbols.getOrPut(gpa, name);
184184 if (!gop.found_existing) {
185185 gop.value_ptr.* = .{ .index = @intCast(i), .file = index };
186186 }
......@@ -344,8 +344,8 @@ pub fn resolveObjcMsgSendSymbols(self: *InternalObject, macho_file: *MachO) !voi
344344
345345 const gpa = macho_file.base.comp.gpa;
346346
347 var objc_msgsend_syms = std.StringArrayHashMap(MachO.Ref).init(gpa);
348 defer objc_msgsend_syms.deinit();
347 var objc_msgsend_syms: std.array_hash_map.String(MachO.Ref) = .empty;
348 defer objc_msgsend_syms.deinit(gpa);
349349
350350 for (macho_file.objects.items) |index| {
351351 const object = macho_file.getFile(index).?.object;
......@@ -360,7 +360,7 @@ pub fn resolveObjcMsgSendSymbols(self: *InternalObject, macho_file: *MachO) !voi
360360
361361 const name = sym.getName(macho_file);
362362 if (mem.startsWith(u8, name, "_objc_msgSend$")) {
363 const gop = try objc_msgsend_syms.getOrPut(name);
363 const gop = try objc_msgsend_syms.getOrPut(gpa, name);
364364 if (!gop.found_existing) {
365365 gop.value_ptr.* = .{ .index = @intCast(i), .file = index };
366366 }
src/link/MachO/Object.zig+5-5
......@@ -1292,8 +1292,8 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target.
12921292
12931293 const Superposition = struct { atom: Atom.Index, size: u64, cu: ?UnwindInfo.Record.Index = null, fde: ?Fde.Index = null };
12941294
1295 var superposition = std.AutoArrayHashMap(u64, Superposition).init(allocator);
1296 defer superposition.deinit();
1295 var superposition: std.array_hash_map.Auto(u64, Superposition) = .empty;
1296 defer superposition.deinit(allocator);
12971297
12981298 const slice = self.symtab.slice();
12991299 for (slice.items(.nlist), slice.items(.atom), slice.items(.size)) |nlist, atom, size| {
......@@ -1301,7 +1301,7 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target.
13011301 if (nlist.n_type.bits.type != .sect) continue;
13021302 const sect = self.sections.items(.header)[nlist.n_sect - 1];
13031303 if (sect.isCode() and sect.size > 0) {
1304 try superposition.ensureUnusedCapacity(1);
1304 try superposition.ensureUnusedCapacity(allocator, 1);
13051305 const gop = superposition.getOrPutAssumeCapacity(nlist.n_value);
13061306 if (gop.found_existing) {
13071307 assert(gop.value_ptr.atom == atom and gop.value_ptr.size == size);
......@@ -1315,7 +1315,7 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target.
13151315 const atom = rec.getAtom(macho_file);
13161316 const addr = atom.getInputAddress(macho_file) + rec.atom_offset;
13171317
1318 try superposition.ensureUnusedCapacity(1);
1318 try superposition.ensureUnusedCapacity(allocator, 1);
13191319 const gop = superposition.getOrPutAssumeCapacity(addr);
13201320 if (!gop.found_existing) {
13211321 gop.value_ptr.* = .{ .atom = rec.atom, .size = rec.length };
......@@ -1331,7 +1331,7 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target.
13311331 const atom = fde.getAtom(macho_file);
13321332 const addr = atom.getInputAddress(macho_file) + fde.atom_offset;
13331333
1334 try superposition.ensureUnusedCapacity(1);
1334 try superposition.ensureUnusedCapacity(allocator, 1);
13351335 const gop = superposition.getOrPutAssumeCapacity(addr);
13361336 if (!gop.found_existing) {
13371337 gop.value_ptr.* = .{ .atom = fde.atom, .size = fde.pc_range };
src/link/MachO/UnwindInfo.zig+4-4
......@@ -173,18 +173,18 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
173173 }
174174 };
175175
176 var common_encodings_counts = std.ArrayHashMap(
176 var common_encodings_counts: std.array_hash_map.Custom(
177177 Encoding,
178178 CommonEncWithCount,
179179 Context,
180180 false,
181 ).init(gpa);
182 defer common_encodings_counts.deinit();
181 ) = .empty;
182 defer common_encodings_counts.deinit(gpa);
183183
184184 for (info.records.items) |ref| {
185185 const rec = ref.getUnwindRecord(macho_file);
186186 if (rec.enc.isDwarf(macho_file)) continue;
187 const gop = try common_encodings_counts.getOrPut(rec.enc);
187 const gop = try common_encodings_counts.getOrPut(gpa, rec.enc);
188188 if (!gop.found_existing) {
189189 gop.value_ptr.* = .{
190190 .enc = rec.enc,
src/link/SpirV/lower_invocation_globals.zig+28-27
......@@ -67,17 +67,17 @@ const ModuleInfo = struct {
6767 parser: *BinaryModule.Parser,
6868 binary: BinaryModule,
6969 ) BinaryModule.ParseError!ModuleInfo {
70 var entry_points = std.AutoArrayHashMap(ResultId, void).init(arena);
71 var functions = std.AutoArrayHashMap(ResultId, Fn).init(arena);
70 var entry_points: std.array_hash_map.Auto(ResultId, void) = .empty;
71 var functions: std.array_hash_map.Auto(ResultId, Fn) = .empty;
7272 var fn_types = std.AutoHashMap(ResultId, struct {
7373 return_type: ResultId,
7474 param_types: []const ResultId,
7575 }).init(arena);
76 var calls = std.AutoArrayHashMap(ResultId, void).init(arena);
76 var calls: std.array_hash_map.Auto(ResultId, void) = .empty;
7777 var callee_store = std.array_list.Managed(ResultId).init(arena);
78 var function_invocation_globals = std.AutoArrayHashMap(ResultId, void).init(arena);
78 var function_invocation_globals: std.array_hash_map.Auto(ResultId, void) = .empty;
7979 var result_id_offsets = std.array_list.Managed(u16).init(arena);
80 var invocation_globals = std.AutoArrayHashMap(ResultId, InvocationGlobal).init(arena);
80 var invocation_globals: std.array_hash_map.Auto(ResultId, InvocationGlobal) = .empty;
8181
8282 var maybe_current_function: ?ResultId = null;
8383 var fn_ty_id: ResultId = undefined;
......@@ -90,7 +90,7 @@ const ModuleInfo = struct {
9090 switch (inst.opcode) {
9191 .OpEntryPoint => {
9292 const entry_point: ResultId = @enumFromInt(inst.operands[1]);
93 const entry = try entry_points.getOrPut(entry_point);
93 const entry = try entry_points.getOrPut(arena, entry_point);
9494 if (entry.found_existing) {
9595 log.err("Entry point type {f} has duplicate definition", .{entry_point});
9696 return error.DuplicateId;
......@@ -126,7 +126,7 @@ const ModuleInfo = struct {
126126 else
127127 .none;
128128
129 try invocation_globals.put(result_id, .{
129 try invocation_globals.put(arena, result_id, .{
130130 .dependencies = .{},
131131 .ty = global_type,
132132 .initializer = initializer,
......@@ -145,14 +145,14 @@ const ModuleInfo = struct {
145145 },
146146 .OpFunctionCall => {
147147 const callee: ResultId = @enumFromInt(inst.operands[2]);
148 try calls.put(callee, {});
148 try calls.put(arena, callee, {});
149149 },
150150 .OpFunctionEnd => {
151151 const current_function = maybe_current_function orelse {
152152 log.err("encountered OpFunctionEnd without corresponding OpFunction", .{});
153153 return error.InvalidPhysicalFormat;
154154 };
155 const entry = try functions.getOrPut(current_function);
155 const entry = try functions.getOrPut(arena, current_function);
156156 if (entry.found_existing) {
157157 log.err("Function {f} has duplicate definition", .{current_function});
158158 return error.DuplicateId;
......@@ -170,7 +170,7 @@ const ModuleInfo = struct {
170170 .first_callee = first_callee,
171171 .return_type = fn_type.return_type,
172172 .param_types = fn_type.param_types,
173 .invocation_globals = try function_invocation_globals.unmanaged.clone(arena),
173 .invocation_globals = try function_invocation_globals.clone(arena),
174174 };
175175 maybe_current_function = null;
176176 calls.clearRetainingCapacity();
......@@ -181,7 +181,7 @@ const ModuleInfo = struct {
181181 for (result_id_offsets.items) |off| {
182182 const result_id: ResultId = @enumFromInt(inst.operands[off]);
183183 if (invocation_globals.contains(result_id)) {
184 try function_invocation_globals.put(result_id, {});
184 try function_invocation_globals.put(arena, result_id, {});
185185 }
186186 }
187187 }
......@@ -191,11 +191,11 @@ const ModuleInfo = struct {
191191 return error.InvalidPhysicalFormat;
192192 }
193193
194 return ModuleInfo{
195 .functions = functions.unmanaged,
196 .entry_points = entry_points.unmanaged,
194 return .{
195 .functions = functions,
196 .entry_points = entry_points,
197197 .callee_store = callee_store.items,
198 .invocation_globals = invocation_globals.unmanaged,
198 .invocation_globals = invocation_globals,
199199 };
200200 }
201201
......@@ -583,7 +583,8 @@ const ModuleBuilder = struct {
583583 }
584584
585585 fn emitNewEntryPoints(self: *ModuleBuilder, info: ModuleInfo) !void {
586 var all_function_invocation_globals = std.AutoArrayHashMap(ResultId, void).init(self.arena);
586 const arena = self.arena;
587 var all_function_invocation_globals: std.array_hash_map.Auto(ResultId, void) = .empty;
587588
588589 for (info.entry_points.keys(), 0..) |func, entry_point_index| {
589590 const fn_info = info.functions.get(func).?;
......@@ -593,7 +594,7 @@ const ModuleBuilder = struct {
593594 .param_types = fn_info.param_types,
594595 }).?;
595596
596 try self.section.emit(self.arena, .OpFunction, .{
597 try self.section.emit(arena, .OpFunction, .{
597598 .id_result_type = fn_info.return_type,
598599 .id_result = ep_id,
599600 .function_control = .{}, // TODO: Copy the attributes from the original function maybe?
......@@ -604,13 +605,13 @@ const ModuleBuilder = struct {
604605 const params_id_base: u32 = @intFromEnum(self.allocIds(@intCast(fn_info.param_types.len)));
605606 for (fn_info.param_types, 0..) |param_type, i| {
606607 const id: ResultId = @enumFromInt(params_id_base + @as(u32, @intCast(i)));
607 try self.section.emit(self.arena, .OpFunctionParameter, .{
608 try self.section.emit(arena, .OpFunctionParameter, .{
608609 .id_result_type = param_type,
609610 .id_result = id,
610611 });
611612 }
612613
613 try self.section.emit(self.arena, .OpLabel, .{
614 try self.section.emit(arena, .OpLabel, .{
614615 .id_result = self.allocId(),
615616 });
616617
......@@ -619,10 +620,10 @@ const ModuleBuilder = struct {
619620 // Just quickly construct that set here.
620621 all_function_invocation_globals.clearRetainingCapacity();
621622 for (fn_info.invocation_globals.keys()) |global| {
622 try all_function_invocation_globals.put(global, {});
623 try all_function_invocation_globals.put(arena, global, {});
623624 const global_info = info.invocation_globals.get(global).?;
624625 for (global_info.dependencies.keys()) |dependency| {
625 try all_function_invocation_globals.put(dependency, {});
626 try all_function_invocation_globals.put(arena, dependency, {});
626627 }
627628 }
628629
......@@ -632,7 +633,7 @@ const ModuleBuilder = struct {
632633 const global_info = info.invocation_globals.get(global).?;
633634
634635 const id: ResultId = @enumFromInt(global_id_base + @as(u32, @intCast(i)));
635 try self.section.emit(self.arena, .OpVariable, .{
636 try self.section.emit(arena, .OpVariable, .{
636637 .id_result_type = global_info.ty,
637638 .id_result = id,
638639 .storage_class = .function,
......@@ -649,7 +650,7 @@ const ModuleBuilder = struct {
649650 assert(initializer_info.param_types.len == 0);
650651
651652 try self.callWithGlobalsAndLinearParams(
652 all_function_invocation_globals,
653 &all_function_invocation_globals,
653654 global_info.initializer,
654655 initializer_info,
655656 global_id_base,
......@@ -659,21 +660,21 @@ const ModuleBuilder = struct {
659660
660661 // Call the main kernel entry
661662 try self.callWithGlobalsAndLinearParams(
662 all_function_invocation_globals,
663 &all_function_invocation_globals,
663664 func,
664665 fn_info,
665666 global_id_base,
666667 params_id_base,
667668 );
668669
669 try self.section.emit(self.arena, .OpReturn, {});
670 try self.section.emit(self.arena, .OpFunctionEnd, {});
670 try self.section.emit(arena, .OpReturn, {});
671 try self.section.emit(arena, .OpFunctionEnd, {});
671672 }
672673 }
673674
674675 fn callWithGlobalsAndLinearParams(
675676 self: *ModuleBuilder,
676 all_globals: std.AutoArrayHashMap(ResultId, void),
677 all_globals: *const std.array_hash_map.Auto(ResultId, void),
677678 func: ResultId,
678679 callee_info: ModuleInfo.Fn,
679680 global_id_base: u32,
src/link/Wasm.zig+3-3
......@@ -3088,11 +3088,11 @@ fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void {
30883088 // In this case we must force link all embedded object files within the archive
30893089 // We loop over all symbols, and then group them by offset as the offset
30903090 // notates where the object file starts.
3091 var offsets = std.AutoArrayHashMap(u32, void).init(gpa);
3092 defer offsets.deinit();
3091 var offsets: std.array_hash_map.Auto(u32, void) = .empty;
3092 defer offsets.deinit(gpa);
30933093 for (archive.toc.values()) |symbol_offsets| {
30943094 for (symbol_offsets.items) |sym_offset| {
3095 try offsets.put(sym_offset, {});
3095 try offsets.put(gpa, sym_offset, {});
30963096 }
30973097 }
30983098
tools/gen_spirv_spec.zig+11-11
......@@ -44,7 +44,7 @@ const StringPairContext = struct {
4444 }
4545};
4646
47const OperandKindMap = std.ArrayHashMap(StringPair, OperandKind, StringPairContext, true);
47const OperandKindMap = std.array_hash_map.Custom(StringPair, OperandKind, StringPairContext, true);
4848
4949/// Khronos made it so that these names are not defined explicitly, so
5050/// we need to hardcode it (like they did).
......@@ -295,9 +295,9 @@ fn render(
295295 );
296296
297297 // Merge the operand kinds from all extensions together.
298 var all_operand_kinds = OperandKindMap.init(arena);
298 var all_operand_kinds: OperandKindMap = .empty;
299299 for (registry.operand_kinds) |kind| {
300 try all_operand_kinds.putNoClobber(.{ "core", kind.kind }, kind);
300 try all_operand_kinds.putNoClobber(arena, .{ "core", kind.kind }, kind);
301301 }
302302 for (extensions) |ext| {
303303 // Note: extensions may define the same operand kind, with different
......@@ -305,11 +305,11 @@ fn render(
305305 // using the name of the extension. This is similar to what
306306 // the official headers do.
307307
308 try all_operand_kinds.ensureUnusedCapacity(ext.spec.operand_kinds.len);
308 try all_operand_kinds.ensureUnusedCapacity(arena, ext.spec.operand_kinds.len);
309309 for (ext.spec.operand_kinds) |kind| {
310310 var new_kind = kind;
311311 new_kind.kind = try std.mem.join(arena, ".", &.{ ext.name, kind.kind });
312 try all_operand_kinds.putNoClobber(.{ ext.name, kind.kind }, new_kind);
312 try all_operand_kinds.putNoClobber(arena, .{ ext.name, kind.kind }, new_kind);
313313 }
314314 }
315315
......@@ -411,11 +411,11 @@ fn renderInstructionsCase(
411411}
412412
413413fn renderClass(arena: Allocator, writer: *std.Io.Writer, instructions: []const Instruction) !void {
414 var class_map = std.StringArrayHashMap(void).init(arena);
414 var class_map: std.array_hash_map.String(void) = .empty;
415415
416416 for (instructions) |inst| {
417417 if (std.mem.eql(u8, inst.class.?, "@exclude")) continue;
418 try class_map.put(inst.class.?, {});
418 try class_map.put(arena, inst.class.?, {});
419419 }
420420
421421 try writer.writeAll("pub const Class = enum {\n");
......@@ -538,8 +538,8 @@ fn renderOpcodes(
538538 instructions: []const Instruction,
539539 extended_structs: ExtendedStructSet,
540540) !void {
541 var inst_map = std.AutoArrayHashMap(u32, usize).init(arena);
542 try inst_map.ensureTotalCapacity(instructions.len);
541 var inst_map: std.array_hash_map.Auto(u32, usize) = .empty;
542 try inst_map.ensureTotalCapacity(arena, instructions.len);
543543
544544 var aliases = std.array_list.Managed(struct { inst: usize, alias: usize }).init(arena);
545545 try aliases.ensureTotalCapacity(instructions.len);
......@@ -653,8 +653,8 @@ fn renderValueEnum(
653653) !void {
654654 const enumerants = enumeration.enumerants orelse return error.InvalidRegistry;
655655
656 var enum_map = std.AutoArrayHashMap(u32, usize).init(arena);
657 try enum_map.ensureTotalCapacity(enumerants.len);
656 var enum_map: std.array_hash_map.Auto(u32, usize) = .empty;
657 try enum_map.ensureTotalCapacity(arena, enumerants.len);
658658
659659 var aliases = std.array_list.Managed(struct { enumerant: usize, alias: usize }).init(arena);
660660 try aliases.ensureTotalCapacity(enumerants.len);
tools/gen_stubs.zig+10-14
......@@ -274,8 +274,8 @@ const MultiSym = struct {
274274
275275const Parse = struct {
276276 arena: mem.Allocator,
277 sym_table: *std.StringArrayHashMap(MultiSym),
278 sections: *std.StringArrayHashMap(void),
277 sym_table: *std.array_hash_map.String(MultiSym),
278 sections: *std.array_hash_map.String(void),
279279 elf_bytes: []align(@alignOf(elf.Elf64_Ehdr)) u8,
280280 header: elf.Header,
281281 arch: Arch,
......@@ -289,13 +289,11 @@ pub fn main(init: std.process.Init) !void {
289289
290290 var build_all_dir = try Io.Dir.cwd().openDir(io, build_all_path, .{});
291291
292 var sym_table = std.StringArrayHashMap(MultiSym).init(arena);
293 var sections = std.StringArrayHashMap(void).init(arena);
292 var sym_table: std.array_hash_map.String(MultiSym) = .empty;
293 var sections: std.array_hash_map.String(void) = .empty;
294294
295295 for (arches) |arch| {
296 const libc_so_path = try std.fmt.allocPrint(arena, "{s}/lib/libc.so", .{
297 @tagName(arch),
298 });
296 const libc_so_path = try std.fmt.allocPrint(arena, "{t}/lib/libc.so", .{arch});
299297
300298 // Read the ELF header.
301299 const elf_bytes = build_all_dir.readFileAllocOptions(
......@@ -306,9 +304,7 @@ pub fn main(init: std.process.Init) !void {
306304 .of(elf.Elf64_Ehdr),
307305 null,
308306 ) catch |err| {
309 std.debug.panic("unable to read '{s}/{s}': {s}", .{
310 build_all_path, libc_so_path, @errorName(err),
311 });
307 std.debug.panic("unable to read '{s}/{s}': {t}", .{ build_all_path, libc_so_path, err });
312308 };
313309 var stream: std.Io.Reader = .fixed(elf_bytes);
314310 const header = try elf.Header.read(&stream);
......@@ -359,8 +355,8 @@ pub fn main(init: std.process.Init) !void {
359355
360356 // Sort the symbols for deterministic output and cleaner vcs diffs.
361357 const SymTableSort = struct {
362 sections: *const std.StringArrayHashMap(void),
363 sym_table: *const std.StringArrayHashMap(MultiSym),
358 sections: *const std.array_hash_map.String(void),
359 sym_table: *const std.array_hash_map.String(MultiSym),
364360
365361 /// Sort first by section name, then by symbol name
366362 pub fn lessThan(ctx: @This(), index_a: usize, index_b: usize) bool {
......@@ -580,7 +576,7 @@ fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: std.builtin.End
580576 if (mem.eql(u8, sh_name, ".dynsym")) {
581577 dynsym_index = @as(u16, @intCast(i));
582578 }
583 const gop = try parse.sections.getOrPut(sh_name);
579 const gop = try parse.sections.getOrPut(arena, sh_name);
584580 section_index_map[i] = @as(u16, @intCast(gop.index));
585581 }
586582 if (dynsym_index == 0) @panic("did not find the .dynsym section");
......@@ -653,7 +649,7 @@ fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: std.builtin.End
653649 },
654650 }
655651
656 const gop = try parse.sym_table.getOrPut(name);
652 const gop = try parse.sym_table.getOrPut(arena, name);
657653 if (gop.found_existing) {
658654 if (gop.value_ptr.section != section_index_map[this_section]) {
659655 const sh_name = mem.sliceTo(shstrtab[s(shdrs[this_section].sh_name)..], 0);
tools/process_headers.zig+4-4
......@@ -130,7 +130,7 @@ const Contents = struct {
130130};
131131
132132const HashToContents = std.StringHashMap(Contents);
133const TargetToHash = std.StringArrayHashMap([]const u8);
133const TargetToHash = std.array_hash_map.String([]const u8);
134134const PathTable = std.StringHashMap(*TargetToHash);
135135
136136const LibCVendor = enum {
......@@ -317,7 +317,7 @@ pub fn main(init: std.process.Init) !void {
317317 const path_gop = try path_table.getOrPut(rel_path);
318318 const target_to_hash = if (path_gop.found_existing) path_gop.value_ptr.* else blk: {
319319 const ptr = try arena.create(TargetToHash);
320 ptr.* = TargetToHash.init(arena);
320 ptr.* = .empty;
321321 path_gop.value_ptr.* = ptr;
322322 break :blk ptr;
323323 };
......@@ -327,14 +327,14 @@ pub fn main(init: std.process.Init) !void {
327327 // such cases, we manually patch the affected header after processing, so it's fine that
328328 // only one header wins here.
329329 if (libc_target.dest != null) {
330 const hash_gop = try target_to_hash.getOrPut(dest_target);
330 const hash_gop = try target_to_hash.getOrPut(arena, dest_target);
331331 if (hash_gop.found_existing) std.debug.print("overwrote: {s} {s} {s}\n", .{
332332 libc_dir,
333333 rel_path,
334334 dest_target,
335335 }) else hash_gop.value_ptr.* = hash;
336336 } else {
337 try target_to_hash.putNoClobber(dest_target, hash);
337 try target_to_hash.putNoClobber(arena, dest_target, hash);
338338 }
339339 },
340340 else => std.debug.print("warning: weird file: {s}\n", .{full_path}),
tools/update-linux-headers.zig+3-3
......@@ -138,7 +138,7 @@ const Contents = struct {
138138};
139139
140140const HashToContents = std.StringHashMap(Contents);
141const TargetToHash = std.ArrayHashMap(DestTarget, []const u8, DestTarget.HashContext, true);
141const TargetToHash = std.array_hash_map.Custom(DestTarget, []const u8, DestTarget.HashContext, true);
142142const PathTable = std.StringHashMap(*TargetToHash);
143143
144144pub fn main(init: std.process.Init) !void {
......@@ -239,11 +239,11 @@ pub fn main(init: std.process.Init) !void {
239239 const path_gop = try path_table.getOrPut(rel_path);
240240 const target_to_hash = if (path_gop.found_existing) path_gop.value_ptr.* else blk: {
241241 const ptr = try arena.create(TargetToHash);
242 ptr.* = TargetToHash.init(arena);
242 ptr.* = .empty;
243243 path_gop.value_ptr.* = ptr;
244244 break :blk ptr;
245245 };
246 try target_to_hash.putNoClobber(dest_target, hash);
246 try target_to_hash.putNoClobber(arena, dest_target, hash);
247247 },
248248 else => std.debug.print("warning: weird file: {s}\n", .{full_path}),
249249 }