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,...@@ -86,10 +86,10 @@ libc_runtimes_dir: ?[]const u8 = null,
8686
87dep_prefix: []const u8 = "",87dep_prefix: []const u8 = "",
8888
89modules: std.StringArrayHashMap(*Module),89modules: std.array_hash_map.String(*Module),
9090
91named_writefiles: std.StringArrayHashMap(*Step.WriteFile),91named_writefiles: std.array_hash_map.String(*Step.WriteFile),
92named_lazy_paths: std.StringArrayHashMap(LazyPath),92named_lazy_paths: std.array_hash_map.String(LazyPath),
93/// The hash of this instance's package. `""` means that this is the root package.93/// The hash of this instance's package. `""` means that this is the root package.
94pkg_hash: []const u8,94pkg_hash: []const u8,
95/// A mapping from dependency names to package hashes.95/// A mapping from dependency names to package hashes.
...@@ -312,9 +312,9 @@ pub fn create(...@@ -312,9 +312,9 @@ pub fn create(
312 },312 },
313 .install_path = undefined,313 .install_path = undefined,
314 .args = null,314 .args = null,
315 .modules = .init(arena),315 .modules = .empty,
316 .named_writefiles = .init(arena),316 .named_writefiles = .empty,
317 .named_lazy_paths = .init(arena),317 .named_lazy_paths = .empty,
318 .pkg_hash = "",318 .pkg_hash = "",
319 .available_deps = available_deps,319 .available_deps = available_deps,
320 .release_mode = .off,320 .release_mode = .off,
...@@ -405,9 +405,9 @@ fn createChildOnly(...@@ -405,9 +405,9 @@ fn createChildOnly(
405 .enable_wine = parent.enable_wine,405 .enable_wine = parent.enable_wine,
406 .libc_runtimes_dir = parent.libc_runtimes_dir,406 .libc_runtimes_dir = parent.libc_runtimes_dir,
407 .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),407 .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),
408 .modules = .init(allocator),408 .modules = .empty,
409 .named_writefiles = .init(allocator),409 .named_writefiles = .empty,
410 .named_lazy_paths = .init(allocator),410 .named_lazy_paths = .empty,
411 .pkg_hash = pkg_hash,411 .pkg_hash = pkg_hash,
412 .available_deps = pkg_deps,412 .available_deps = pkg_deps,
413 .release_mode = parent.release_mode,413 .release_mode = parent.release_mode,
...@@ -908,7 +908,7 @@ pub const AssemblyOptions = struct {...@@ -908,7 +908,7 @@ pub const AssemblyOptions = struct {
908/// `createModule` can be used instead to create a private module.908/// `createModule` can be used instead to create a private module.
909pub fn addModule(b: *Build, name: []const u8, options: Module.CreateOptions) *Module {909pub fn addModule(b: *Build, name: []const u8, options: Module.CreateOptions) *Module {
910 const module = Module.create(b, options);910 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");
912 return module;912 return module;
913}913}
914914
...@@ -1056,12 +1056,12 @@ pub fn addWriteFile(b: *Build, file_path: []const u8, data: []const u8) *Step.Wr...@@ -1056,12 +1056,12 @@ pub fn addWriteFile(b: *Build, file_path: []const u8, data: []const u8) *Step.Wr
10561056
1057pub fn addNamedWriteFiles(b: *Build, name: []const u8) *Step.WriteFile {1057pub fn addNamedWriteFiles(b: *Build, name: []const u8) *Step.WriteFile {
1058 const wf = Step.WriteFile.create(b);1058 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");
1060 return wf;1060 return wf;
1061}1061}
10621062
1063pub fn addNamedLazyPath(b: *Build, name: []const u8, lp: LazyPath) void {1063pub 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");
1065}1065}
10661066
1067/// Creates a step for mutating files inside a temporary directory created lazily1067/// 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 {...@@ -1814,16 +1814,16 @@ const ElfDumper = struct {
1814 files.putAssumeCapacityNoClobber(object.off - @sizeOf(elf.ar_hdr), object.name);1814 files.putAssumeCapacityNoClobber(object.off - @sizeOf(elf.ar_hdr), object.name);
1815 }1815 }
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;
1818 defer {1818 defer {
1819 for (symbols.values()) |*value| {1819 for (symbols.values()) |*value| {
1820 value.deinit();1820 value.deinit();
1821 }1821 }
1822 symbols.deinit();1822 symbols.deinit(ctx.gpa);
1823 }1823 }
18241824
1825 for (ctx.symtab.items) |entry| {1825 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));
1827 if (!gop.found_existing) {1827 if (!gop.found_existing) {
1828 gop.value_ptr.* = std.array_list.Managed([]const u8).init(ctx.gpa);1828 gop.value_ptr.* = std.array_list.Managed([]const u8).init(ctx.gpa);
1829 }1829 }
lib/std/Build/Step/ConfigHeader.zig+34-32
...@@ -38,7 +38,7 @@ pub const Value = union(enum) {...@@ -38,7 +38,7 @@ pub const Value = union(enum) {
38};38};
3939
40step: Step,40step: Step,
41values: std.StringArrayHashMap(Value),41values: std.array_hash_map.String(Value),
42/// This directory contains the generated file under the name `include_path`.42/// This directory contains the generated file under the name `include_path`.
43generated_dir: std.Build.GeneratedFile,43generated_dir: std.Build.GeneratedFile,
4444
...@@ -95,7 +95,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {...@@ -95,7 +95,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
95 .first_ret_addr = options.first_ret_addr orelse @returnAddress(),95 .first_ret_addr = options.first_ret_addr orelse @returnAddress(),
96 }),96 }),
97 .style = options.style,97 .style = options.style,
98 .values = .init(owner.allocator),98 .values = .empty,
9999
100 .max_bytes = options.max_bytes,100 .max_bytes = options.max_bytes,
101 .include_path = include_path,101 .include_path = include_path,
...@@ -110,7 +110,8 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {...@@ -110,7 +110,8 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
110}110}
111111
112pub fn addIdent(config_header: *ConfigHeader, name: []const u8, value: []const u8) void {112pub 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");
114}115}
115116
116pub fn addValue(config_header: *ConfigHeader, name: []const u8, comptime T: type, value: T) void {117pub 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 {...@@ -131,43 +132,44 @@ pub fn getOutputFile(ch: *ConfigHeader) std.Build.LazyPath {
131}132}
132133
133fn addValueInner(config_header: *ConfigHeader, name: []const u8, comptime T: type, value: T) !void {134fn addValueInner(config_header: *ConfigHeader, name: []const u8, comptime T: type, value: T) !void {
135 const arena = config_header.step.owner.allocator;
134 switch (@typeInfo(T)) {136 switch (@typeInfo(T)) {
135 .null => {137 .null => {
136 try config_header.values.put(name, .undef);138 try config_header.values.put(arena, name, .undef);
137 },139 },
138 .void => {140 .void => {
139 try config_header.values.put(name, .defined);141 try config_header.values.put(arena, name, .defined);
140 },142 },
141 .bool => {143 .bool => {
142 try config_header.values.put(name, .{ .boolean = value });144 try config_header.values.put(arena, name, .{ .boolean = value });
143 },145 },
144 .int => {146 .int => {
145 try config_header.values.put(name, .{ .int = value });147 try config_header.values.put(arena, name, .{ .int = value });
146 },148 },
147 .comptime_int => {149 .comptime_int => {
148 try config_header.values.put(name, .{ .int = value });150 try config_header.values.put(arena, name, .{ .int = value });
149 },151 },
150 .@"enum", .enum_literal => {152 .@"enum", .enum_literal => {
151 try config_header.values.put(name, .{ .ident = @tagName(value) });153 try config_header.values.put(arena, name, .{ .ident = @tagName(value) });
152 },154 },
153 .optional => {155 .optional => {
154 if (value) |x| {156 if (value) |x| {
155 return addValueInner(config_header, name, @TypeOf(x), x);157 return addValueInner(config_header, name, @TypeOf(x), x);
156 } else {158 } else {
157 try config_header.values.put(name, .undef);159 try config_header.values.put(arena, name, .undef);
158 }160 }
159 },161 },
160 .pointer => |ptr| {162 .pointer => |ptr| {
161 switch (@typeInfo(ptr.child)) {163 switch (@typeInfo(ptr.child)) {
162 .array => |array| {164 .array => |array| {
163 if (ptr.size == .one and array.child == u8) {165 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 });
165 return;167 return;
166 }168 }
167 },169 },
168 .int => {170 .int => {
169 if (ptr.size == .slice and ptr.child == u8) {171 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 });
171 return;173 return;
172 }174 }
173 },175 },
...@@ -218,8 +220,8 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -218,8 +220,8 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
218 });220 });
219 };221 };
220 switch (config_header.style) {222 switch (config_header.style) {
221 .autoconf_undef => try render_autoconf_undef(step, contents, bw, config_header.values, src_path),223 .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),224 .autoconf_at => try render_autoconf_at(step, contents, &aw, &config_header.values, src_path),
223 else => unreachable,225 else => unreachable,
224 }226 }
225 },227 },
...@@ -282,7 +284,7 @@ fn render_autoconf_undef(...@@ -282,7 +284,7 @@ fn render_autoconf_undef(
282 step: *Step,284 step: *Step,
283 contents: []const u8,285 contents: []const u8,
284 bw: *Writer,286 bw: *Writer,
285 values: std.StringArrayHashMap(Value),287 values: *const std.array_hash_map.String(Value),
286 src_path: []const u8,288 src_path: []const u8,
287) !void {289) !void {
288 const build = step.owner;290 const build = step.owner;
...@@ -334,7 +336,7 @@ fn render_autoconf_at(...@@ -334,7 +336,7 @@ fn render_autoconf_at(
334 step: *Step,336 step: *Step,
335 contents: []const u8,337 contents: []const u8,
336 aw: *Writer.Allocating,338 aw: *Writer.Allocating,
337 values: std.StringArrayHashMap(Value),339 values: *const std.array_hash_map.String(Value),
338 src_path: []const u8,340 src_path: []const u8,
339) !void {341) !void {
340 const build = step.owner;342 const build = step.owner;
...@@ -373,7 +375,7 @@ fn render_autoconf_at(...@@ -373,7 +375,7 @@ fn render_autoconf_at(
373 if (!last_line) try bw.writeByte('\n');375 if (!last_line) try bw.writeByte('\n');
374 }376 }
375377
376 for (values.unmanaged.entries.slice().items(.key), used) |name, u| {378 for (values.entries.slice().items(.key), used) |name, u| {
377 if (!u) {379 if (!u) {
378 try step.addError("{s}: error: config header value unused: '{s}'", .{ src_path, name });380 try step.addError("{s}: error: config header value unused: '{s}'", .{ src_path, name });
379 any_errors = true;381 any_errors = true;
...@@ -387,14 +389,14 @@ fn render_cmake(...@@ -387,14 +389,14 @@ fn render_cmake(
387 step: *Step,389 step: *Step,
388 contents: []const u8,390 contents: []const u8,
389 bw: *Writer,391 bw: *Writer,
390 values: std.StringArrayHashMap(Value),392 values: std.array_hash_map.String(Value),
391 src_path: []const u8,393 src_path: []const u8,
392) !void {394) !void {
393 const build = step.owner;395 const build = step.owner;
394 const allocator = build.allocator;396 const allocator = build.allocator;
395397
396 var values_copy = try values.clone();398 var values_copy = try values.clone(allocator);
397 defer values_copy.deinit();399 defer values_copy.deinit(allocator);
398400
399 var any_errors = false;401 var any_errors = false;
400 var line_index: u32 = 0;402 var line_index: u32 = 0;
...@@ -523,7 +525,7 @@ fn render_cmake(...@@ -523,7 +525,7 @@ fn render_cmake(
523fn render_blank(525fn render_blank(
524 gpa: std.mem.Allocator,526 gpa: std.mem.Allocator,
525 bw: *Writer,527 bw: *Writer,
526 defines: std.StringArrayHashMap(Value),528 defines: std.array_hash_map.String(Value),
527 include_path: []const u8,529 include_path: []const u8,
528 include_guard_override: ?[]const u8,530 include_guard_override: ?[]const u8,
529) !void {531) !void {
...@@ -555,7 +557,7 @@ fn render_blank(...@@ -555,7 +557,7 @@ fn render_blank(
555 , .{include_guard_name});557 , .{include_guard_name});
556}558}
557559
558fn render_nasm(bw: *Writer, defines: std.StringArrayHashMap(Value)) !void {560fn render_nasm(bw: *Writer, defines: std.array_hash_map.String(Value)) !void {
559 for (defines.keys(), defines.values()) |name, value| try renderValueNasm(bw, name, value);561 for (defines.keys(), defines.values()) |name, value| try renderValueNasm(bw, name, value);
560}562}
561563
...@@ -586,7 +588,7 @@ fn renderValueNasm(bw: *Writer, name: []const u8, value: Value) !void {...@@ -586,7 +588,7 @@ fn renderValueNasm(bw: *Writer, name: []const u8, value: Value) !void {
586fn expand_variables_autoconf_at(588fn expand_variables_autoconf_at(
587 bw: *Writer,589 bw: *Writer,
588 contents: []const u8,590 contents: []const u8,
589 values: std.StringArrayHashMap(Value),591 values: *const std.array_hash_map.String(Value),
590 used: []bool,592 used: []bool,
591) !void {593) !void {
592 const valid_varname_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";594 const valid_varname_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
...@@ -612,7 +614,7 @@ fn expand_variables_autoconf_at(...@@ -612,7 +614,7 @@ fn expand_variables_autoconf_at(
612 try bw.writeAll(key);614 try bw.writeAll(key);
613 return error.MissingValue;615 return error.MissingValue;
614 };616 };
615 const value = values.unmanaged.entries.slice().items(.value)[index];617 const value = values.entries.slice().items(.value)[index];
616 used[index] = true;618 used[index] = true;
617 try bw.writeAll(contents[source_offset..curr]);619 try bw.writeAll(contents[source_offset..curr]);
618 switch (value) {620 switch (value) {
...@@ -633,7 +635,7 @@ fn expand_variables_autoconf_at(...@@ -633,7 +635,7 @@ fn expand_variables_autoconf_at(
633fn expand_variables_cmake(635fn expand_variables_cmake(
634 allocator: Allocator,636 allocator: Allocator,
635 contents: []const u8,637 contents: []const u8,
636 values: std.StringArrayHashMap(Value),638 values: std.array_hash_map.String(Value),
637) ![]const u8 {639) ![]const u8 {
638 var result: std.array_list.Managed(u8) = .init(allocator);640 var result: std.array_list.Managed(u8) = .init(allocator);
639 errdefer result.deinit();641 errdefer result.deinit();
...@@ -765,7 +767,7 @@ fn testReplaceVariablesAutoconfAt(...@@ -765,7 +767,7 @@ fn testReplaceVariablesAutoconfAt(
765 allocator: Allocator,767 allocator: Allocator,
766 contents: []const u8,768 contents: []const u8,
767 expected: []const u8,769 expected: []const u8,
768 values: std.StringArrayHashMap(Value),770 values: std.array_hash_map.String(Value),
769) !void {771) !void {
770 var aw: Writer.Allocating = .init(allocator);772 var aw: Writer.Allocating = .init(allocator);
771 defer aw.deinit();773 defer aw.deinit();
...@@ -784,7 +786,7 @@ fn testReplaceVariablesCMake(...@@ -784,7 +786,7 @@ fn testReplaceVariablesCMake(
784 allocator: Allocator,786 allocator: Allocator,
785 contents: []const u8,787 contents: []const u8,
786 expected: []const u8,788 expected: []const u8,
787 values: std.StringArrayHashMap(Value),789 values: std.array_hash_map.String(Value),
788) !void {790) !void {
789 const actual = try expand_variables_cmake(allocator, contents, values);791 const actual = try expand_variables_cmake(allocator, contents, values);
790 defer allocator.free(actual);792 defer allocator.free(actual);
...@@ -794,7 +796,7 @@ fn testReplaceVariablesCMake(...@@ -794,7 +796,7 @@ fn testReplaceVariablesCMake(
794796
795test "expand_variables_autoconf_at simple cases" {797test "expand_variables_autoconf_at simple cases" {
796 const allocator = std.testing.allocator;798 const allocator = std.testing.allocator;
797 var values: std.StringArrayHashMap(Value) = .init(allocator);799 var values: std.array_hash_map.String(Value) = .init(allocator);
798 defer values.deinit();800 defer values.deinit();
799801
800 // empty strings are preserved802 // empty strings are preserved
...@@ -890,7 +892,7 @@ test "expand_variables_autoconf_at simple cases" {...@@ -890,7 +892,7 @@ test "expand_variables_autoconf_at simple cases" {
890892
891test "expand_variables_autoconf_at edge cases" {893test "expand_variables_autoconf_at edge cases" {
892 const allocator = std.testing.allocator;894 const allocator = std.testing.allocator;
893 var values: std.StringArrayHashMap(Value) = .init(allocator);895 var values: std.array_hash_map.String(Value) = .init(allocator);
894 defer values.deinit();896 defer values.deinit();
895897
896 // @-vars resolved only when they wrap valid characters, otherwise considered literals898 // @-vars resolved only when they wrap valid characters, otherwise considered literals
...@@ -906,7 +908,7 @@ test "expand_variables_autoconf_at edge cases" {...@@ -906,7 +908,7 @@ test "expand_variables_autoconf_at edge cases" {
906908
907test "expand_variables_cmake simple cases" {909test "expand_variables_cmake simple cases" {
908 const allocator = std.testing.allocator;910 const allocator = std.testing.allocator;
909 var values: std.StringArrayHashMap(Value) = .init(allocator);911 var values: std.array_hash_map.String(Value) = .init(allocator);
910 defer values.deinit();912 defer values.deinit();
911913
912 try values.putNoClobber("undef", .undef);914 try values.putNoClobber("undef", .undef);
...@@ -994,7 +996,7 @@ test "expand_variables_cmake simple cases" {...@@ -994,7 +996,7 @@ test "expand_variables_cmake simple cases" {
994996
995test "expand_variables_cmake edge cases" {997test "expand_variables_cmake edge cases" {
996 const allocator = std.testing.allocator;998 const allocator = std.testing.allocator;
997 var values: std.StringArrayHashMap(Value) = .init(allocator);999 var values: std.array_hash_map.String(Value) = .init(allocator);
998 defer values.deinit();1000 defer values.deinit();
9991001
1000 // special symbols1002 // special symbols
...@@ -1055,7 +1057,7 @@ test "expand_variables_cmake edge cases" {...@@ -1055,7 +1057,7 @@ test "expand_variables_cmake edge cases" {
10551057
1056test "expand_variables_cmake escaped characters" {1058test "expand_variables_cmake escaped characters" {
1057 const allocator = std.testing.allocator;1059 const allocator = std.testing.allocator;
1058 var values: std.StringArrayHashMap(Value) = .init(allocator);1060 var values: std.array_hash_map.String(Value) = .init(allocator);
1059 defer values.deinit();1061 defer values.deinit();
10601062
1061 try values.putNoClobber("string", Value{ .string = "text" });1063 try values.putNoClobber("string", Value{ .string = "text" });
lib/std/array_hash_map.zig+96-555
...@@ -12,27 +12,15 @@ const hash_map = @This();...@@ -12,27 +12,15 @@ const hash_map = @This();
12/// An `ArrayHashMap` with default hash and equal functions.12/// An `ArrayHashMap` with default hash and equal functions.
13///13///
14/// See `AutoContext` for a description of the hash and equal implementations.14/// 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 {
16 return ArrayHashMap(K, V, AutoContext(K), !autoEqlIsCheap(K));16 return ArrayHashMap(K, V, AutoContext(K), !autoEqlIsCheap(K));
17}17}
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
26/// An `ArrayHashMap` with strings as keys.19/// An `ArrayHashMap` with strings as keys.
27pub fn StringArrayHashMap(comptime V: type) type {20pub fn String(comptime V: type) type {
28 return ArrayHashMap([]const u8, V, StringContext, true);21 return ArrayHashMap([]const u8, V, StringContext, true);
29}22}
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
36pub const StringContext = struct {24pub const StringContext = struct {
37 pub fn hash(self: @This(), s: []const u8) u32 {25 pub fn hash(self: @This(), s: []const u8) u32 {
38 _ = self;26 _ = self;
...@@ -53,454 +41,8 @@ pub fn hashString(s: []const u8) u32 {...@@ -53,454 +41,8 @@ pub fn hashString(s: []const u8) u32 {
53 return @truncate(std.hash.Wyhash.hash(0, s));41 return @truncate(std.hash.Wyhash.hash(0, s));
54}42}
5543
56/// Deprecated in favor of `ArrayHashMapWithAllocator` (no code changes needed)44/// Deprecated; use `Custom`.
57/// or `ArrayHashMapUnmanaged` (will need to update callsites to pass an45pub const ArrayHashMap = Custom;
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}
50446
505/// A hash table of keys and values, each stored sequentially.47/// A hash table of keys and values, each stored sequentially.
506///48///
...@@ -522,11 +64,11 @@ pub fn ArrayHashMapWithAllocator(...@@ -522,11 +64,11 @@ pub fn ArrayHashMapWithAllocator(
522///64///
523/// This type is designed to have low overhead for small numbers of entries. When65/// This type is designed to have low overhead for small numbers of entries. When
524/// `store_hash` is `false` and the number of entries in the map is less than 9,66/// `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` is67/// the overhead cost of using `ArrayHashMap` rather than `std.ArrayList` is
526/// only a single pointer-sized integer.68/// only a single pointer-sized integer.
527///69///
528/// Default initialization of this struct is deprecated; use `.empty` instead.70/// Default initialization of this struct is deprecated; use `.empty` instead.
529pub fn ArrayHashMapUnmanaged(71pub fn Custom(
530 comptime K: type,72 comptime K: type,
531 comptime V: type,73 comptime V: type,
532 /// A namespace that provides these two functions:74 /// A namespace that provides these two functions:
...@@ -605,9 +147,6 @@ pub fn ArrayHashMapUnmanaged(...@@ -605,9 +147,6 @@ pub fn ArrayHashMapUnmanaged(
605 index: usize,147 index: usize,
606 };148 };
607149
608 /// The ArrayHashMap type using the same settings as this managed map.
609 pub const Managed = ArrayHashMap(K, V, Context, store_hash);
610
611 /// Some functions require a context only if hashes are not stored.150 /// Some functions require a context only if hashes are not stored.
612 /// To keep the api simple, this type is only used internally.151 /// To keep the api simple, this type is only used internally.
613 const ByIndexContext = if (store_hash) void else Context;152 const ByIndexContext = if (store_hash) void else Context;
...@@ -626,21 +165,6 @@ pub fn ArrayHashMapUnmanaged(...@@ -626,21 +165,6 @@ pub fn ArrayHashMapUnmanaged(
626165
627 const Oom = Allocator.Error;166 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
644 pub fn init(gpa: Allocator, key_list: []const K, value_list: []const V) Oom!Self {168 pub fn init(gpa: Allocator, key_list: []const K, value_list: []const V) Oom!Self {
645 var self: Self = .{};169 var self: Self = .{};
646 errdefer self.deinit(gpa);170 errdefer self.deinit(gpa);
...@@ -2189,35 +1713,37 @@ const IndexHeader = struct {...@@ -2189,35 +1713,37 @@ const IndexHeader = struct {
2189};1713};
21901714
2191test "basic hash map usage" {1715test "basic hash map usage" {
2192 var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);1716 const gpa = testing.allocator;
2193 defer map.deinit();
21941717
2195 try testing.expect((try map.fetchPut(1, 11)) == null);1718 var map: Auto(i32, i32) = .empty;
2196 try testing.expect((try map.fetchPut(2, 22)) == null);1719 defer map.deinit(gpa);
2197 try testing.expect((try map.fetchPut(3, 33)) == null);1720
2198 try testing.expect((try map.fetchPut(4, 44)) == null);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);1726 try map.putNoClobber(gpa, 5, 55);
2201 try testing.expect((try map.fetchPut(5, 66)).?.value == 55);1727 try testing.expect((try map.fetchPut(gpa, 5, 66)).?.value == 55);
2202 try testing.expect((try map.fetchPut(5, 55)).?.value == 66);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);
2205 try testing.expect(gop1.found_existing == true);1731 try testing.expect(gop1.found_existing == true);
2206 try testing.expect(gop1.value_ptr.* == 55);1732 try testing.expect(gop1.value_ptr.* == 55);
2207 try testing.expect(gop1.index == 4);1733 try testing.expect(gop1.index == 4);
2208 gop1.value_ptr.* = 77;1734 gop1.value_ptr.* = 77;
2209 try testing.expect(map.getEntry(5).?.value_ptr.* == 77);1735 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);
2212 try testing.expect(gop2.found_existing == false);1738 try testing.expect(gop2.found_existing == false);
2213 try testing.expect(gop2.index == 5);1739 try testing.expect(gop2.index == 5);
2214 gop2.value_ptr.* = 42;1740 gop2.value_ptr.* = 42;
2215 try testing.expect(map.getEntry(99).?.value_ptr.* == 42);1741 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);
2218 try testing.expect(gop3.value_ptr.* == 77);1744 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);
2221 try testing.expect(gop4.value_ptr.* == 41);1747 try testing.expect(gop4.value_ptr.* == 41);
22221748
2223 try testing.expect(map.contains(2));1749 try testing.expect(map.contains(2));
...@@ -2234,7 +1760,7 @@ test "basic hash map usage" {...@@ -2234,7 +1760,7 @@ test "basic hash map usage" {
22341760
2235 // Since we've used `swapRemove` above, the index of this entry should remain unchanged.1761 // Since we've used `swapRemove` above, the index of this entry should remain unchanged.
2236 try testing.expect(map.getIndex(100).? == 1);1762 try testing.expect(map.getIndex(100).? == 1);
2237 const gop5 = try map.getOrPut(5);1763 const gop5 = try map.getOrPut(gpa, 5);
2238 try testing.expect(gop5.found_existing == true);1764 try testing.expect(gop5.found_existing == true);
2239 try testing.expect(gop5.value_ptr.* == 77);1765 try testing.expect(gop5.value_ptr.* == 77);
2240 try testing.expect(gop5.index == 4);1766 try testing.expect(gop5.index == 4);
...@@ -2247,7 +1773,7 @@ test "basic hash map usage" {...@@ -2247,7 +1773,7 @@ test "basic hash map usage" {
2247 try testing.expect(map.orderedRemove(100) == false);1773 try testing.expect(map.orderedRemove(100) == false);
2248 try testing.expect(map.getEntry(100) == null);1774 try testing.expect(map.getEntry(100) == null);
2249 try testing.expect(map.get(100) == null);1775 try testing.expect(map.get(100) == null);
2250 const gop6 = try map.getOrPut(5);1776 const gop6 = try map.getOrPut(gpa, 5);
2251 try testing.expect(gop6.found_existing == true);1777 try testing.expect(gop6.found_existing == true);
2252 try testing.expect(gop6.value_ptr.* == 77);1778 try testing.expect(gop6.value_ptr.* == 77);
2253 try testing.expect(gop6.index == 3);1779 try testing.expect(gop6.index == 3);
...@@ -2256,15 +1782,17 @@ test "basic hash map usage" {...@@ -2256,15 +1782,17 @@ test "basic hash map usage" {
2256}1782}
22571783
2258test "iterator hash map" {1784test "iterator hash map" {
2259 var reset_map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);1785 const gpa = testing.allocator;
2260 defer reset_map.deinit();1786
1787 var reset_map: Auto(i32, i32) = .empty;
1788 defer reset_map.deinit(gpa);
22611789
2262 // test ensureTotalCapacity with a 0 parameter1790 // 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);1793 try reset_map.putNoClobber(gpa, 0, 11);
2266 try reset_map.putNoClobber(1, 22);1794 try reset_map.putNoClobber(gpa, 1, 22);
2267 try reset_map.putNoClobber(2, 33);1795 try reset_map.putNoClobber(gpa, 2, 33);
22681796
2269 const keys = [_]i32{1797 const keys = [_]i32{
2270 0, 2, 1,1798 0, 2, 1,
...@@ -2312,10 +1840,12 @@ test "iterator hash map" {...@@ -2312,10 +1840,12 @@ test "iterator hash map" {
2312}1840}
23131841
2314test "ensure capacity" {1842test "ensure capacity" {
2315 var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);1843 const gpa = testing.allocator;
2316 defer map.deinit();
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);
2319 const initial_capacity = map.capacity();1849 const initial_capacity = map.capacity();
2320 try testing.expect(initial_capacity >= 20);1850 try testing.expect(initial_capacity >= 20);
2321 var i: i32 = 0;1851 var i: i32 = 0;
...@@ -2329,23 +1859,25 @@ test "ensure capacity" {...@@ -2329,23 +1859,25 @@ test "ensure capacity" {
2329test "ensure capacity leak" {1859test "ensure capacity leak" {
2330 try testing.checkAllAllocationFailures(std.testing.allocator, struct {1860 try testing.checkAllAllocationFailures(std.testing.allocator, struct {
2331 pub fn f(allocator: Allocator) !void {1861 pub fn f(allocator: Allocator) !void {
2332 var map = AutoArrayHashMap(i32, i32).init(allocator);1862 var map: Auto(i32, i32) = .empty;
2333 defer map.deinit();1863 defer map.deinit(allocator);
23341864
2335 var i: i32 = 0;1865 var i: i32 = 0;
2336 // put more than `linear_scan_max` in so index_header gets allocated.1866 // 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);
2338 }1868 }
2339 }.f, .{});1869 }.f, .{});
2340}1870}
23411871
2342test "big map" {1872test "big map" {
2343 var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);1873 const gpa = testing.allocator;
2344 defer map.deinit();1874
1875 var map: Auto(i32, i32) = .empty;
1876 defer map.deinit(gpa);
23451877
2346 var i: i32 = 0;1878 var i: i32 = 0;
2347 while (i < 8) : (i += 1) {1879 while (i < 8) : (i += 1) {
2348 try map.put(i, i + 10);1880 try map.put(gpa, i, i + 10);
2349 }1881 }
23501882
2351 i = 0;1883 i = 0;
...@@ -2358,7 +1890,7 @@ test "big map" {...@@ -2358,7 +1890,7 @@ test "big map" {
23581890
2359 i = 4;1891 i = 4;
2360 while (i < 12) : (i += 1) {1892 while (i < 12) : (i += 1) {
2361 try map.put(i, i + 12);1893 try map.put(gpa, i, i + 12);
2362 }1894 }
23631895
2364 i = 0;1896 i = 0;
...@@ -2393,17 +1925,19 @@ test "big map" {...@@ -2393,17 +1925,19 @@ test "big map" {
2393}1925}
23941926
2395test "clone" {1927test "clone" {
2396 var original = AutoArrayHashMap(i32, i32).init(std.testing.allocator);1928 const gpa = testing.allocator;
2397 defer original.deinit();1929
1930 var original: Auto(i32, i32) = .empty;
1931 defer original.deinit(gpa);
23981932
2399 // put more than `linear_scan_max` so we can test that the index header is properly cloned1933 // put more than `linear_scan_max` so we can test that the index header is properly cloned
2400 var i: u8 = 0;1934 var i: u8 = 0;
2401 while (i < 10) : (i += 1) {1935 while (i < 10) : (i += 1) {
2402 try original.putNoClobber(i, i * 10);1936 try original.putNoClobber(gpa, i, i * 10);
2403 }1937 }
24041938
2405 var copy = try original.clone();1939 var copy = try original.clone(gpa);
2406 defer copy.deinit();1940 defer copy.deinit(gpa);
24071941
2408 i = 0;1942 i = 0;
2409 while (i < 10) : (i += 1) {1943 while (i < 10) : (i += 1) {
...@@ -2419,16 +1953,18 @@ test "clone" {...@@ -2419,16 +1953,18 @@ test "clone" {
2419}1953}
24201954
2421test "shrink" {1955test "shrink" {
2422 var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);1956 const gpa = testing.allocator;
2423 defer map.deinit();1957
1958 var map: Auto(i32, i32) = .empty;
1959 defer map.deinit(gpa);
24241960
2425 // This test is more interesting if we insert enough entries to allocate the index header.1961 // This test is more interesting if we insert enough entries to allocate the index header.
2426 const num_entries = 200;1962 const num_entries = 200;
2427 var i: i32 = 0;1963 var i: i32 = 0;
2428 while (i < num_entries) : (i += 1)1964 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);
2432 try testing.expect(map.count() == num_entries);1968 try testing.expect(map.count() == num_entries);
24331969
2434 // Test `shrinkRetainingCapacity`.1970 // Test `shrinkRetainingCapacity`.
...@@ -2437,7 +1973,7 @@ test "shrink" {...@@ -2437,7 +1973,7 @@ test "shrink" {
2437 try testing.expect(map.capacity() >= num_entries);1973 try testing.expect(map.capacity() >= num_entries);
2438 i = 0;1974 i = 0;
2439 while (i < num_entries) : (i += 1) {1975 while (i < num_entries) : (i += 1) {
2440 const gop = try map.getOrPut(i);1976 const gop = try map.getOrPut(gpa, i);
2441 if (i < 17) {1977 if (i < 17) {
2442 try testing.expect(gop.found_existing == true);1978 try testing.expect(gop.found_existing == true);
2443 try testing.expect(gop.value_ptr.* == i * 10);1979 try testing.expect(gop.value_ptr.* == i * 10);
...@@ -2445,12 +1981,12 @@ test "shrink" {...@@ -2445,12 +1981,12 @@ test "shrink" {
2445 }1981 }
24461982
2447 // Test `shrinkAndFree`.1983 // Test `shrinkAndFree`.
2448 map.shrinkAndFree(15);1984 map.shrinkAndFree(gpa, 15);
2449 try testing.expect(map.count() == 15);1985 try testing.expect(map.count() == 15);
2450 try testing.expect(map.capacity() == 15);1986 try testing.expect(map.capacity() == 15);
2451 i = 0;1987 i = 0;
2452 while (i < num_entries) : (i += 1) {1988 while (i < num_entries) : (i += 1) {
2453 const gop = try map.getOrPut(i);1989 const gop = try map.getOrPut(gpa, i);
2454 if (i < 15) {1990 if (i < 15) {
2455 try testing.expect(gop.found_existing == true);1991 try testing.expect(gop.found_existing == true);
2456 try testing.expect(gop.value_ptr.* == i * 10);1992 try testing.expect(gop.value_ptr.* == i * 10);
...@@ -2459,15 +1995,17 @@ test "shrink" {...@@ -2459,15 +1995,17 @@ test "shrink" {
2459}1995}
24601996
2461test "pop()" {1997test "pop()" {
2462 var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);1998 const gpa = testing.allocator;
2463 defer map.deinit();1999
2000 var map: Auto(i32, i32) = .empty;
2001 defer map.deinit(gpa);
24642002
2465 // Insert just enough entries so that the map expands. Afterwards,2003 // Insert just enough entries so that the map expands. Afterwards,
2466 // pop all entries out of the map.2004 // pop all entries out of the map.
24672005
2468 var i: i32 = 0;2006 var i: i32 = 0;
2469 while (i < 9) : (i += 1) {2007 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);
2471 }2009 }
24722010
2473 while (map.pop()) |pop| {2011 while (map.pop()) |pop| {
...@@ -2479,31 +2017,33 @@ test "pop()" {...@@ -2479,31 +2017,33 @@ test "pop()" {
2479}2017}
24802018
2481test "reIndex" {2019test "reIndex" {
2482 var map = ArrayHashMap(i32, i32, AutoContext(i32), true).init(std.testing.allocator);2020 const gpa = testing.allocator;
2483 defer map.deinit();2021
2022 var map: Custom(i32, i32, AutoContext(i32), true) = .empty;
2023 defer map.deinit(gpa);
24842024
2485 // Populate via the API.2025 // Populate via the API.
2486 const num_indexed_entries = 200;2026 const num_indexed_entries = 200;
2487 var i: i32 = 0;2027 var i: i32 = 0;
2488 while (i < num_indexed_entries) : (i += 1)2028 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
2491 // Make sure we allocated an index header.2031 // 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
2494 // Now write to the arrays directly.2034 // Now write to the arrays directly.
2495 const num_unindexed_entries = 20;2035 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);
2497 for (map.keys()[num_indexed_entries..], map.values()[num_indexed_entries..], num_indexed_entries..) |*key, *value, j| {2037 for (map.keys()[num_indexed_entries..], map.values()[num_indexed_entries..], num_indexed_entries..) |*key, *value, j| {
2498 key.* = @intCast(j);2038 key.* = @intCast(j);
2499 value.* = @intCast(j * 10);2039 value.* = @intCast(j * 10);
2500 }2040 }
25012041
2502 // After reindexing, we should see everything.2042 // After reindexing, we should see everything.
2503 try map.reIndex();2043 try map.reIndex(gpa);
2504 i = 0;2044 i = 0;
2505 while (i < num_indexed_entries + num_unindexed_entries) : (i += 1) {2045 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);
2507 try testing.expect(gop.found_existing == true);2047 try testing.expect(gop.found_existing == true);
2508 try testing.expect(gop.value_ptr.* == i * 10);2048 try testing.expect(gop.value_ptr.* == i * 10);
2509 try testing.expect(gop.index == i);2049 try testing.expect(gop.index == i);
...@@ -2511,23 +2051,20 @@ test "reIndex" {...@@ -2511,23 +2051,20 @@ test "reIndex" {
2511}2051}
25122052
2513test "auto store_hash" {2053test "auto store_hash" {
2514 const HasCheapEql = AutoArrayHashMap(i32, i32);2054 const HasCheapEql = Auto(i32, i32);
2515 const HasExpensiveEql = AutoArrayHashMap([32]i32, i32);2055 const HasExpensiveEql = Auto([32]i32, i32);
2516 try testing.expect(@FieldType(HasCheapEql.Data, "hash") == void);2056 try testing.expect(@FieldType(HasCheapEql.Data, "hash") == void);
2517 try testing.expect(@FieldType(HasExpensiveEql.Data, "hash") != void);2057 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);
2523}2058}
25242059
2525test "sort" {2060test "sort" {
2526 var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);2061 const gpa = testing.allocator;
2527 defer map.deinit();2062
2063 var map: Auto(i32, i32) = .empty;
2064 defer map.deinit(gpa);
25282065
2529 for ([_]i32{ 8, 3, 12, 10, 2, 4, 9, 5, 6, 13, 14, 15, 16, 1, 11, 17, 7 }) |x| {2066 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);
2531 }2068 }
25322069
2533 const C = struct {2070 const C = struct {
...@@ -2549,15 +2086,17 @@ test "sort" {...@@ -2549,15 +2086,17 @@ test "sort" {
2549}2086}
25502087
2551test "0 sized key" {2088test "0 sized key" {
2552 var map = AutoArrayHashMap(u0, i32).init(std.testing.allocator);2089 const gpa = testing.allocator;
2553 defer map.deinit();2090
2091 var map: Auto(u0, i32) = .empty;
2092 defer map.deinit(gpa);
25542093
2555 try testing.expectEqual(map.get(0), null);2094 try testing.expectEqual(map.get(0), null);
25562095
2557 try map.put(0, 5);2096 try map.put(gpa, 0, 5);
2558 try testing.expectEqual(map.get(0), 5);2097 try testing.expectEqual(map.get(0), 5);
25592098
2560 try map.put(0, 10);2099 try map.put(gpa, 0, 10);
2561 try testing.expectEqual(map.get(0), 10);2100 try testing.expectEqual(map.get(0), 10);
25622101
2563 try testing.expectEqual(map.swapRemove(0), true);2102 try testing.expectEqual(map.swapRemove(0), true);
...@@ -2565,12 +2104,14 @@ test "0 sized key" {...@@ -2565,12 +2104,14 @@ test "0 sized key" {
2565}2104}
25662105
2567test "0 sized key and 0 sized value" {2106test "0 sized key and 0 sized value" {
2568 var map = AutoArrayHashMap(u0, u0).init(std.testing.allocator);2107 const gpa = testing.allocator;
2569 defer map.deinit();2108
2109 var map: Auto(u0, u0) = .empty;
2110 defer map.deinit(gpa);
25702111
2571 try testing.expectEqual(map.get(0), null);2112 try testing.expectEqual(map.get(0), null);
25722113
2573 try map.put(0, 0);2114 try map.put(gpa, 0, 0);
2574 try testing.expectEqual(map.get(0), 0);2115 try testing.expectEqual(map.get(0), 0);
25752116
2576 try testing.expectEqual(map.swapRemove(0), true);2117 try testing.expectEqual(map.swapRemove(0), true);
...@@ -2580,7 +2121,7 @@ test "0 sized key and 0 sized value" {...@@ -2580,7 +2121,7 @@ test "0 sized key and 0 sized value" {
2580test "setKey storehash true" {2121test "setKey storehash true" {
2581 const gpa = std.testing.allocator;2122 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;
2584 defer map.deinit(gpa);2125 defer map.deinit(gpa);
25852126
2586 try map.put(gpa, 12, 34);2127 try map.put(gpa, 12, 34);
...@@ -2596,7 +2137,7 @@ test "setKey storehash true" {...@@ -2596,7 +2137,7 @@ test "setKey storehash true" {
2596test "setKey storehash false" {2137test "setKey storehash false" {
2597 const gpa = std.testing.allocator;2138 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;
2600 defer map.deinit(gpa);2141 defer map.deinit(gpa);
26012142
2602 try map.put(gpa, 12, 34);2143 try map.put(gpa, 12, 34);
...@@ -2691,7 +2232,7 @@ pub fn getAutoHashStratFn(comptime K: type, comptime Context: type, comptime str...@@ -2691,7 +2232,7 @@ pub fn getAutoHashStratFn(comptime K: type, comptime Context: type, comptime str
2691test "orderedRemoveAtMany" {2232test "orderedRemoveAtMany" {
2692 const gpa = testing.allocator;2233 const gpa = testing.allocator;
26932234
2694 var map: AutoArrayHashMapUnmanaged(usize, void) = .empty;2235 var map: Auto(usize, void) = .empty;
2695 defer map.deinit(gpa);2236 defer map.deinit(gpa);
26962237
2697 for (0..10) |n| {2238 for (0..10) |n| {
lib/std/json/Stringify.zig+3-3
...@@ -770,9 +770,9 @@ fn testBasicWriteStream(w: *Stringify) !void {...@@ -770,9 +770,9 @@ fn testBasicWriteStream(w: *Stringify) !void {
770}770}
771771
772fn getJsonObject(allocator: std.mem.Allocator) !std.json.Value {772fn getJsonObject(allocator: std.mem.Allocator) !std.json.Value {
773 var v: std.json.Value = .{ .object = std.json.ObjectMap.init(allocator) };773 var v: std.json.Value = .{ .object = .empty };
774 try v.object.put("one", std.json.Value{ .integer = @as(i64, @intCast(1)) });774 try v.object.put(allocator, "one", std.json.Value{ .integer = @as(i64, @intCast(1)) });
775 try v.object.put("two", std.json.Value{ .float = 2.0 });775 try v.object.put(allocator, "two", std.json.Value{ .float = 2.0 });
776 return v;776 return v;
777}777}
778778
lib/std/json/dynamic.zig+4-4
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1const std = @import("std");1const std = @import("std");
2const debug = std.debug;2const debug = std.debug;
3const ArenaAllocator = std.heap.ArenaAllocator;3const ArenaAllocator = std.heap.ArenaAllocator;
4const StringArrayHashMap = std.StringArrayHashMap;4const StringArrayHashMap = std.array_hash_map.String;
5const Allocator = std.mem.Allocator;5const Allocator = std.mem.Allocator;
6const json = std.json;6const json = std.json;
77
...@@ -103,10 +103,10 @@ pub const Value = union(enum) {...@@ -103,10 +103,10 @@ pub const Value = union(enum) {
103103
104 .object_begin => {104 .object_begin => {
105 switch (try source.nextAllocMax(allocator, .alloc_always, options.max_value_len.?)) {105 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,
107 .allocated_string => |key| {107 .allocated_string => |key| {
108 try stack.appendSlice(&[_]Value{108 try stack.appendSlice(&[_]Value{
109 Value{ .object = ObjectMap.init(allocator) },109 Value{ .object = .empty },
110 Value{ .string = key },110 Value{ .string = key },
111 });111 });
112 },112 },
...@@ -145,7 +145,7 @@ fn handleCompleteValue(stack: *Array, allocator: Allocator, source: anytype, val...@@ -145,7 +145,7 @@ fn handleCompleteValue(stack: *Array, allocator: Allocator, source: anytype, val
145 // stack: [..., .object]145 // stack: [..., .object]
146 var object = &stack.items[stack.items.len - 1].object;146 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);
149 if (gop.found_existing) {149 if (gop.found_existing) {
150 switch (options.duplicate_field_behavior) {150 switch (options.duplicate_field_behavior) {
151 .use_first => {},151 .use_first => {},
lib/std/json/dynamic_test.zig+4-3
...@@ -220,14 +220,15 @@ test "Value with duplicate fields" {...@@ -220,14 +220,15 @@ test "Value with duplicate fields" {
220}220}
221221
222test "Value.jsonStringify" {222test "Value.jsonStringify" {
223 const gpa = testing.allocator;
223 var vals = [_]Value{224 var vals = [_]Value{
224 .{ .integer = 1 },225 .{ .integer = 1 },
225 .{ .integer = 2 },226 .{ .integer = 2 },
226 .{ .number_string = "3" },227 .{ .number_string = "3" },
227 };228 };
228 var obj = ObjectMap.init(testing.allocator);229 var obj: ObjectMap = .empty;
229 defer obj.deinit();230 defer obj.deinit(gpa);
230 try obj.putNoClobber("a", .{ .string = "b" });231 try obj.putNoClobber(gpa, "a", .{ .string = "b" });
231 const array = [_]Value{232 const array = [_]Value{
232 .null,233 .null,
233 .{ .bool = true },234 .{ .bool = true },
lib/std/std.zig+7-6
...@@ -1,7 +1,3 @@...@@ -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;
5pub const AutoHashMap = hash_map.AutoHashMap;1pub const AutoHashMap = hash_map.AutoHashMap;
6pub const AutoHashMapUnmanaged = hash_map.AutoHashMapUnmanaged;2pub const AutoHashMapUnmanaged = hash_map.AutoHashMapUnmanaged;
7pub const BitStack = @import("BitStack.zig");3pub const BitStack = @import("BitStack.zig");
...@@ -31,14 +27,19 @@ pub const SinglyLinkedList = @import("SinglyLinkedList.zig");...@@ -31,14 +27,19 @@ pub const SinglyLinkedList = @import("SinglyLinkedList.zig");
31pub const StaticBitSet = bit_set.StaticBitSet;27pub const StaticBitSet = bit_set.StaticBitSet;
32pub const StringHashMap = hash_map.StringHashMap;28pub const StringHashMap = hash_map.StringHashMap;
33pub const StringHashMapUnmanaged = hash_map.StringHashMapUnmanaged;29pub const StringHashMapUnmanaged = hash_map.StringHashMapUnmanaged;
34pub const StringArrayHashMap = array_hash_map.StringArrayHashMap;
35pub const StringArrayHashMapUnmanaged = array_hash_map.StringArrayHashMapUnmanaged;
36pub const Target = @import("Target.zig");30pub const Target = @import("Target.zig");
37pub const Thread = @import("Thread.zig");31pub const Thread = @import("Thread.zig");
38pub const Treap = @import("treap.zig").Treap;32pub const Treap = @import("treap.zig").Treap;
39pub const Tz = tz.Tz;33pub const Tz = tz.Tz;
40pub const Uri = @import("Uri.zig");34pub 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
42/// A contiguous, growable list of items in memory. This is a wrapper around a43/// A contiguous, growable list of items in memory. This is a wrapper around a
43/// slice of `T` values.44/// slice of `T` values.
44///45///
lib/std/zig/AstGen.zig+3-3
...@@ -1779,8 +1779,8 @@ fn structInitExpr(...@@ -1779,8 +1779,8 @@ fn structInitExpr(
1779 var sfba = std.heap.stackFallback(256, astgen.arena);1779 var sfba = std.heap.stackFallback(256, astgen.arena);
1780 const sfba_allocator = sfba.get();1780 const sfba_allocator = sfba.get();
17811781
1782 var duplicate_names = std.AutoArrayHashMap(Zir.NullTerminatedString, ArrayList(Ast.TokenIndex)).init(sfba_allocator);1782 var duplicate_names: std.array_hash_map.Auto(Zir.NullTerminatedString, ArrayList(Ast.TokenIndex)) = .empty;
1783 try duplicate_names.ensureTotalCapacity(@intCast(struct_init.ast.fields.len));1783 try duplicate_names.ensureTotalCapacity(sfba_allocator, @intCast(struct_init.ast.fields.len));
17841784
1785 // When there aren't errors, use this to avoid a second iteration.1785 // When there aren't errors, use this to avoid a second iteration.
1786 var any_duplicate = false;1786 var any_duplicate = false;
...@@ -1789,7 +1789,7 @@ fn structInitExpr(...@@ -1789,7 +1789,7 @@ fn structInitExpr(
1789 const name_token = tree.firstToken(field) - 2;1789 const name_token = tree.firstToken(field) - 2;
1790 const name_index = try astgen.identAsString(name_token);1790 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
1794 if (gop.found_existing) {1794 if (gop.found_existing) {
1795 try gop.value_ptr.append(sfba_allocator, name_token);1795 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...@@ -10552,7 +10552,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo
10552 count: usize = 0,10552 count: usize = 0,
10553 bytes: usize = 0,10553 bytes: usize = 0,
10554 };10554 };
10555 var counts = std.AutoArrayHashMap(Tag, TagStats).init(arena);10555 var counts: std.array_hash_map.Auto(Tag, TagStats) = .empty;
10556 for (ip.locals) |*local| {10556 for (ip.locals) |*local| {
10557 // Early check for length 0, because `view()` is invalid if capacity is 010557 // Early check for length 0, because `view()` is invalid if capacity is 0
10558 if (local.mutate.items.len == 0) continue;10558 if (local.mutate.items.len == 0) continue;
...@@ -10563,7 +10563,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo...@@ -10563,7 +10563,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo
10563 items.items(.tag)[0..local.mutate.items.len],10563 items.items(.tag)[0..local.mutate.items.len],
10564 items.items(.data)[0..local.mutate.items.len],10564 items.items(.data)[0..local.mutate.items.len],
10565 ) |tag, data| {10565 ) |tag, data| {
10566 const gop = try counts.getOrPut(tag);10566 const gop = try counts.getOrPut(arena, tag);
10567 if (!gop.found_existing) gop.value_ptr.* = .{};10567 if (!gop.found_existing) gop.value_ptr.* = .{};
10568 gop.value_ptr.count += 1;10568 gop.value_ptr.count += 1;
10569 gop.value_ptr.bytes += 1 + 4 + @as(usize, switch (tag) {10569 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...@@ -10799,7 +10799,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo
10799 }10799 }
10800 }10800 }
10801 const SortContext = struct {10801 const SortContext = struct {
10802 map: *std.AutoArrayHashMap(Tag, TagStats),10802 map: *std.array_hash_map.Auto(Tag, TagStats),
10803 pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {10803 pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {
10804 const values = ctx.map.values();10804 const values = ctx.map.values();
10805 return values[a_index].bytes > values[b_index].bytes;10805 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...@@ -795,7 +795,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
795 //795 //
796 // If we don't handle this, we end up writing the default `lgammal` symbol for version 2.33796 // If we don't handle this, we end up writing the default `lgammal` symbol for version 2.33
797 // twice, which causes a "duplicate symbol" assembler error.797 // 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
800 var inc_reader: Io.Reader = .fixed(metadata.inclusions);800 var inc_reader: Io.Reader = .fixed(metadata.inclusions);
801801
...@@ -859,7 +859,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -859,7 +859,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
859 }859 }
860860
861 versions_written.clearRetainingCapacity();861 versions_written.clearRetainingCapacity();
862 try versions_written.ensureTotalCapacity(versions_len);862 try versions_written.ensureTotalCapacity(arena, versions_len);
863863
864 {864 {
865 var ver_buf_i: u8 = 0;865 var ver_buf_i: u8 = 0;
...@@ -1035,7 +1035,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -1035,7 +1035,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
1035 }1035 }
10361036
1037 versions_written.clearRetainingCapacity();1037 versions_written.clearRetainingCapacity();
1038 try versions_written.ensureTotalCapacity(versions_len);1038 try versions_written.ensureTotalCapacity(arena, versions_len);
10391039
1040 {1040 {
1041 var ver_buf_i: u8 = 0;1041 var ver_buf_i: u8 = 0;
src/libs/mingw/implib.zig+3-3
...@@ -36,14 +36,14 @@ pub fn writeCoffArchive(...@@ -36,14 +36,14 @@ pub fn writeCoffArchive(
36 var long_names: StringTable = .{};36 var long_names: StringTable = .{};
37 defer long_names.deinit(allocator);37 defer long_names.deinit(allocator);
3838
39 var symbol_to_member_index = std.StringArrayHashMap(usize).init(allocator);39 var symbol_to_member_index: std.array_hash_map.String(usize) = .empty;
40 defer symbol_to_member_index.deinit();40 defer symbol_to_member_index.deinit(allocator);
41 var string_table_len: usize = 0;41 var string_table_len: usize = 0;
42 var num_symbols: usize = 0;42 var num_symbols: usize = 0;
4343
44 for (members.list.items, 0..) |member, i| {44 for (members.list.items, 0..) |member, i| {
45 for (member.symbol_names_for_import_lib) |symbol_name| {45 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);
47 // When building the symbol map, ignore duplicate symbol names.47 // When building the symbol map, ignore duplicate symbol names.
48 // This can happen in cases like (using .def file syntax):48 // This can happen in cases like (using .def file syntax):
49 // _foo49 // _foo
src/libs/musl.zig+6-6
...@@ -90,10 +90,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro...@@ -90,10 +90,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
90 // Even a .s file can substitute for a .c file.90 // Even a .s file can substitute for a .c file.
91 const target = comp.getTarget();91 const target = comp.getTarget();
92 const arch_name = std.zig.target.muslArchName(target.cpu.arch, target.abi);92 const arch_name = std.zig.target.muslArchName(target.cpu.arch, target.abi);
93 var source_table = std.StringArrayHashMap(Ext).init(comp.gpa);93 var source_table: std.array_hash_map.String(Ext) = .empty;
94 defer source_table.deinit();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
98 for (src_files) |src_file| {98 for (src_files) |src_file| {
99 try addSrcFile(arena, &source_table, src_file);99 try addSrcFile(arena, &source_table, src_file);
...@@ -107,10 +107,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro...@@ -107,10 +107,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
107 }107 }
108 }108 }
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);
111 defer c_source_files.deinit();111 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);
114 defer override_path.deinit();114 defer override_path.deinit();
115115
116 const s = path.sep_str;116 const s = path.sep_str;
...@@ -349,7 +349,7 @@ const Ext = enum {...@@ -349,7 +349,7 @@ const Ext = enum {
349 o3,349 o3,
350};350};
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 {
353 const ext: Ext = ext: {353 const ext: Ext = ext: {
354 if (mem.endsWith(u8, file_path, ".c")) {354 if (mem.endsWith(u8, file_path, ".c")) {
355 if (mem.startsWith(u8, file_path, "musl/src/string/") or355 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 {...@@ -881,10 +881,10 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
881 self.rela_plt.clearRetainingCapacity();881 self.rela_plt.clearRetainingCapacity();
882882
883 if (self.zigObjectPtr()) |zo| {883 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;
885 defer {885 defer {
886 for (undefs.values()) |*refs| refs.deinit();886 for (undefs.values()) |*refs| refs.deinit();
887 undefs.deinit();887 undefs.deinit(gpa);
888 }888 }
889889
890 var has_reloc_errors = false;890 var has_reloc_errors = false;
...@@ -1332,10 +1332,10 @@ fn scanRelocs(self: *Elf) !void {...@@ -1332,10 +1332,10 @@ fn scanRelocs(self: *Elf) !void {
1332 const gpa = self.base.comp.gpa;1332 const gpa = self.base.comp.gpa;
1333 const shared_objects = self.shared_objects.values();1333 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;
1336 defer {1336 defer {
1337 for (undefs.values()) |*refs| refs.deinit();1337 for (undefs.values()) |*refs| refs.deinit();
1338 undefs.deinit();1338 undefs.deinit(gpa);
1339 }1339 }
13401340
1341 var has_reloc_errors = false;1341 var has_reloc_errors = false;
...@@ -1748,12 +1748,12 @@ pub fn deleteExport(...@@ -1748,12 +1748,12 @@ pub fn deleteExport(
1748fn checkDuplicates(self: *Elf) !void {1748fn checkDuplicates(self: *Elf) !void {
1749 const gpa = self.base.comp.gpa;1749 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;
1752 defer {1752 defer {
1753 for (dupes.values()) |*list| {1753 for (dupes.values()) |*list| {
1754 list.deinit(gpa);1754 list.deinit(gpa);
1755 }1755 }
1756 dupes.deinit();1756 dupes.deinit(gpa);
1757 }1757 }
17581758
1759 if (self.zigObjectPtr()) |zig_object| {1759 if (self.zigObjectPtr()) |zig_object| {
...@@ -2992,10 +2992,10 @@ fn allocateSpecialPhdrs(self: *Elf) void {...@@ -2992,10 +2992,10 @@ fn allocateSpecialPhdrs(self: *Elf) void {
2992fn writeAtoms(self: *Elf) !void {2992fn writeAtoms(self: *Elf) !void {
2993 const gpa = self.base.comp.gpa;2993 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;
2996 defer {2996 defer {
2997 for (undefs.values()) |*refs| refs.deinit();2997 for (undefs.values()) |*refs| refs.deinit();
2998 undefs.deinit();2998 undefs.deinit(gpa);
2999 }2999 }
30003000
3001 var buffer: std.Io.Writer.Allocating = .init(gpa);3001 var buffer: std.Io.Writer.Allocating = .init(gpa);
src/link/Elf/Atom.zig+1-1
...@@ -605,7 +605,7 @@ fn reportUndefined(...@@ -605,7 +605,7 @@ fn reportUndefined(
605 .object => |x| x.symbols_resolver.items[rel.r_sym() - x.first_global.?],605 .object => |x| x.symbols_resolver.items[rel.r_sym() - x.first_global.?],
606 inline else => |x| x.symbols_resolver.items[rel.r_sym()],606 inline else => |x| x.symbols_resolver.items[rel.r_sym()],
607 };607 };
608 const gop = try undefs.getOrPut(idx);608 const gop = try undefs.getOrPut(gpa, idx);
609 if (!gop.found_existing) {609 if (!gop.found_existing) {
610 gop.value_ptr.* = std.array_list.Managed(Elf.Ref).init(gpa);610 gop.value_ptr.* = std.array_list.Managed(Elf.Ref).init(gpa);
611 }611 }
src/link/Elf/Object.zig+4-2
...@@ -753,6 +753,8 @@ pub fn markImportsExports(self: *Object, elf_file: *Elf) void {...@@ -753,6 +753,8 @@ pub fn markImportsExports(self: *Object, elf_file: *Elf) void {
753}753}
754754
755pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {755pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {
756 const gpa = elf_file.base.comp.gpa;
757
756 const first_global = self.first_global orelse return;758 const first_global = self.first_global orelse return;
757 for (0..self.globals().len) |i| {759 for (0..self.globals().len) |i| {
758 const esym_idx = first_global + i;760 const esym_idx = first_global + i;
...@@ -772,11 +774,11 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutO...@@ -772,11 +774,11 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutO
772 if (!atom_ptr.alive) continue;774 if (!atom_ptr.alive) continue;
773 }775 }
774776
775 const gop = try dupes.getOrPut(self.symbols_resolver.items[i]);777 const gop = try dupes.getOrPut(gpa, self.symbols_resolver.items[i]);
776 if (!gop.found_existing) {778 if (!gop.found_existing) {
777 gop.value_ptr.* = .empty;779 gop.value_ptr.* = .empty;
778 }780 }
779 try gop.value_ptr.append(elf_file.base.comp.gpa, self.index);781 try gop.value_ptr.append(gpa, self.index);
780 }782 }
781}783}
782784
src/link/Elf/ZigObject.zig+3-1
...@@ -710,6 +710,8 @@ pub fn markImportsExports(self: *ZigObject, elf_file: *Elf) void {...@@ -710,6 +710,8 @@ pub fn markImportsExports(self: *ZigObject, elf_file: *Elf) void {
710}710}
711711
712pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {712pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void {
713 const gpa = elf_file.base.comp.gpa;
714
713 for (self.global_symbols.items, 0..) |index, i| {715 for (self.global_symbols.items, 0..) |index, i| {
714 const esym = self.symtab.items(.elf_sym)[index];716 const esym = self.symtab.items(.elf_sym)[index];
715 const shndx = self.symtab.items(.shndx)[index];717 const shndx = self.symtab.items(.shndx)[index];
...@@ -727,7 +729,7 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O...@@ -727,7 +729,7 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O
727 if (!atom_ptr.alive) continue;729 if (!atom_ptr.alive) continue;
728 }730 }
729731
730 const gop = try dupes.getOrPut(self.symbols_resolver.items[i]);732 const gop = try dupes.getOrPut(gpa, self.symbols_resolver.items[i]);
731 if (!gop.found_existing) {733 if (!gop.found_existing) {
732 gop.value_ptr.* = .empty;734 gop.value_ptr.* = .empty;
733 }735 }
src/link/MachO/InternalObject.zig+6-6
...@@ -164,8 +164,8 @@ pub fn resolveBoundarySymbols(self: *InternalObject, macho_file: *MachO) !void {...@@ -164,8 +164,8 @@ pub fn resolveBoundarySymbols(self: *InternalObject, macho_file: *MachO) !void {
164 defer tracy.end();164 defer tracy.end();
165165
166 const gpa = macho_file.base.comp.gpa;166 const gpa = macho_file.base.comp.gpa;
167 var boundary_symbols = std.StringArrayHashMap(MachO.Ref).init(gpa);167 var boundary_symbols: std.array_hash_map.String(MachO.Ref) = .empty;
168 defer boundary_symbols.deinit();168 defer boundary_symbols.deinit(gpa);
169169
170 for (macho_file.objects.items) |index| {170 for (macho_file.objects.items) |index| {
171 const object = macho_file.getFile(index).?.object;171 const object = macho_file.getFile(index).?.object;
...@@ -180,7 +180,7 @@ pub fn resolveBoundarySymbols(self: *InternalObject, macho_file: *MachO) !void {...@@ -180,7 +180,7 @@ pub fn resolveBoundarySymbols(self: *InternalObject, macho_file: *MachO) !void {
180 mem.startsWith(u8, name, "section$start$") or180 mem.startsWith(u8, name, "section$start$") or
181 mem.startsWith(u8, name, "section$end$"))181 mem.startsWith(u8, name, "section$end$"))
182 {182 {
183 const gop = try boundary_symbols.getOrPut(name);183 const gop = try boundary_symbols.getOrPut(gpa, name);
184 if (!gop.found_existing) {184 if (!gop.found_existing) {
185 gop.value_ptr.* = .{ .index = @intCast(i), .file = index };185 gop.value_ptr.* = .{ .index = @intCast(i), .file = index };
186 }186 }
...@@ -344,8 +344,8 @@ pub fn resolveObjcMsgSendSymbols(self: *InternalObject, macho_file: *MachO) !voi...@@ -344,8 +344,8 @@ pub fn resolveObjcMsgSendSymbols(self: *InternalObject, macho_file: *MachO) !voi
344344
345 const gpa = macho_file.base.comp.gpa;345 const gpa = macho_file.base.comp.gpa;
346346
347 var objc_msgsend_syms = std.StringArrayHashMap(MachO.Ref).init(gpa);347 var objc_msgsend_syms: std.array_hash_map.String(MachO.Ref) = .empty;
348 defer objc_msgsend_syms.deinit();348 defer objc_msgsend_syms.deinit(gpa);
349349
350 for (macho_file.objects.items) |index| {350 for (macho_file.objects.items) |index| {
351 const object = macho_file.getFile(index).?.object;351 const object = macho_file.getFile(index).?.object;
...@@ -360,7 +360,7 @@ pub fn resolveObjcMsgSendSymbols(self: *InternalObject, macho_file: *MachO) !voi...@@ -360,7 +360,7 @@ pub fn resolveObjcMsgSendSymbols(self: *InternalObject, macho_file: *MachO) !voi
360360
361 const name = sym.getName(macho_file);361 const name = sym.getName(macho_file);
362 if (mem.startsWith(u8, name, "_objc_msgSend$")) {362 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);
364 if (!gop.found_existing) {364 if (!gop.found_existing) {
365 gop.value_ptr.* = .{ .index = @intCast(i), .file = index };365 gop.value_ptr.* = .{ .index = @intCast(i), .file = index };
366 }366 }
src/link/MachO/Object.zig+5-5
...@@ -1292,8 +1292,8 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target....@@ -1292,8 +1292,8 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target.
12921292
1293 const Superposition = struct { atom: Atom.Index, size: u64, cu: ?UnwindInfo.Record.Index = null, fde: ?Fde.Index = null };1293 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);1295 var superposition: std.array_hash_map.Auto(u64, Superposition) = .empty;
1296 defer superposition.deinit();1296 defer superposition.deinit(allocator);
12971297
1298 const slice = self.symtab.slice();1298 const slice = self.symtab.slice();
1299 for (slice.items(.nlist), slice.items(.atom), slice.items(.size)) |nlist, atom, size| {1299 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....@@ -1301,7 +1301,7 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target.
1301 if (nlist.n_type.bits.type != .sect) continue;1301 if (nlist.n_type.bits.type != .sect) continue;
1302 const sect = self.sections.items(.header)[nlist.n_sect - 1];1302 const sect = self.sections.items(.header)[nlist.n_sect - 1];
1303 if (sect.isCode() and sect.size > 0) {1303 if (sect.isCode() and sect.size > 0) {
1304 try superposition.ensureUnusedCapacity(1);1304 try superposition.ensureUnusedCapacity(allocator, 1);
1305 const gop = superposition.getOrPutAssumeCapacity(nlist.n_value);1305 const gop = superposition.getOrPutAssumeCapacity(nlist.n_value);
1306 if (gop.found_existing) {1306 if (gop.found_existing) {
1307 assert(gop.value_ptr.atom == atom and gop.value_ptr.size == size);1307 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....@@ -1315,7 +1315,7 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target.
1315 const atom = rec.getAtom(macho_file);1315 const atom = rec.getAtom(macho_file);
1316 const addr = atom.getInputAddress(macho_file) + rec.atom_offset;1316 const addr = atom.getInputAddress(macho_file) + rec.atom_offset;
13171317
1318 try superposition.ensureUnusedCapacity(1);1318 try superposition.ensureUnusedCapacity(allocator, 1);
1319 const gop = superposition.getOrPutAssumeCapacity(addr);1319 const gop = superposition.getOrPutAssumeCapacity(addr);
1320 if (!gop.found_existing) {1320 if (!gop.found_existing) {
1321 gop.value_ptr.* = .{ .atom = rec.atom, .size = rec.length };1321 gop.value_ptr.* = .{ .atom = rec.atom, .size = rec.length };
...@@ -1331,7 +1331,7 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target....@@ -1331,7 +1331,7 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target.
1331 const atom = fde.getAtom(macho_file);1331 const atom = fde.getAtom(macho_file);
1332 const addr = atom.getInputAddress(macho_file) + fde.atom_offset;1332 const addr = atom.getInputAddress(macho_file) + fde.atom_offset;
13331333
1334 try superposition.ensureUnusedCapacity(1);1334 try superposition.ensureUnusedCapacity(allocator, 1);
1335 const gop = superposition.getOrPutAssumeCapacity(addr);1335 const gop = superposition.getOrPutAssumeCapacity(addr);
1336 if (!gop.found_existing) {1336 if (!gop.found_existing) {
1337 gop.value_ptr.* = .{ .atom = fde.atom, .size = fde.pc_range };1337 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 {...@@ -173,18 +173,18 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
173 }173 }
174 };174 };
175175
176 var common_encodings_counts = std.ArrayHashMap(176 var common_encodings_counts: std.array_hash_map.Custom(
177 Encoding,177 Encoding,
178 CommonEncWithCount,178 CommonEncWithCount,
179 Context,179 Context,
180 false,180 false,
181 ).init(gpa);181 ) = .empty;
182 defer common_encodings_counts.deinit();182 defer common_encodings_counts.deinit(gpa);
183183
184 for (info.records.items) |ref| {184 for (info.records.items) |ref| {
185 const rec = ref.getUnwindRecord(macho_file);185 const rec = ref.getUnwindRecord(macho_file);
186 if (rec.enc.isDwarf(macho_file)) continue;186 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);
188 if (!gop.found_existing) {188 if (!gop.found_existing) {
189 gop.value_ptr.* = .{189 gop.value_ptr.* = .{
190 .enc = rec.enc,190 .enc = rec.enc,
src/link/SpirV/lower_invocation_globals.zig+28-27
...@@ -67,17 +67,17 @@ const ModuleInfo = struct {...@@ -67,17 +67,17 @@ const ModuleInfo = struct {
67 parser: *BinaryModule.Parser,67 parser: *BinaryModule.Parser,
68 binary: BinaryModule,68 binary: BinaryModule,
69 ) BinaryModule.ParseError!ModuleInfo {69 ) BinaryModule.ParseError!ModuleInfo {
70 var entry_points = std.AutoArrayHashMap(ResultId, void).init(arena);70 var entry_points: std.array_hash_map.Auto(ResultId, void) = .empty;
71 var functions = std.AutoArrayHashMap(ResultId, Fn).init(arena);71 var functions: std.array_hash_map.Auto(ResultId, Fn) = .empty;
72 var fn_types = std.AutoHashMap(ResultId, struct {72 var fn_types = std.AutoHashMap(ResultId, struct {
73 return_type: ResultId,73 return_type: ResultId,
74 param_types: []const ResultId,74 param_types: []const ResultId,
75 }).init(arena);75 }).init(arena);
76 var calls = std.AutoArrayHashMap(ResultId, void).init(arena);76 var calls: std.array_hash_map.Auto(ResultId, void) = .empty;
77 var callee_store = std.array_list.Managed(ResultId).init(arena);77 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;
79 var result_id_offsets = std.array_list.Managed(u16).init(arena);79 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
82 var maybe_current_function: ?ResultId = null;82 var maybe_current_function: ?ResultId = null;
83 var fn_ty_id: ResultId = undefined;83 var fn_ty_id: ResultId = undefined;
...@@ -90,7 +90,7 @@ const ModuleInfo = struct {...@@ -90,7 +90,7 @@ const ModuleInfo = struct {
90 switch (inst.opcode) {90 switch (inst.opcode) {
91 .OpEntryPoint => {91 .OpEntryPoint => {
92 const entry_point: ResultId = @enumFromInt(inst.operands[1]);92 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);
94 if (entry.found_existing) {94 if (entry.found_existing) {
95 log.err("Entry point type {f} has duplicate definition", .{entry_point});95 log.err("Entry point type {f} has duplicate definition", .{entry_point});
96 return error.DuplicateId;96 return error.DuplicateId;
...@@ -126,7 +126,7 @@ const ModuleInfo = struct {...@@ -126,7 +126,7 @@ const ModuleInfo = struct {
126 else126 else
127 .none;127 .none;
128128
129 try invocation_globals.put(result_id, .{129 try invocation_globals.put(arena, result_id, .{
130 .dependencies = .{},130 .dependencies = .{},
131 .ty = global_type,131 .ty = global_type,
132 .initializer = initializer,132 .initializer = initializer,
...@@ -145,14 +145,14 @@ const ModuleInfo = struct {...@@ -145,14 +145,14 @@ const ModuleInfo = struct {
145 },145 },
146 .OpFunctionCall => {146 .OpFunctionCall => {
147 const callee: ResultId = @enumFromInt(inst.operands[2]);147 const callee: ResultId = @enumFromInt(inst.operands[2]);
148 try calls.put(callee, {});148 try calls.put(arena, callee, {});
149 },149 },
150 .OpFunctionEnd => {150 .OpFunctionEnd => {
151 const current_function = maybe_current_function orelse {151 const current_function = maybe_current_function orelse {
152 log.err("encountered OpFunctionEnd without corresponding OpFunction", .{});152 log.err("encountered OpFunctionEnd without corresponding OpFunction", .{});
153 return error.InvalidPhysicalFormat;153 return error.InvalidPhysicalFormat;
154 };154 };
155 const entry = try functions.getOrPut(current_function);155 const entry = try functions.getOrPut(arena, current_function);
156 if (entry.found_existing) {156 if (entry.found_existing) {
157 log.err("Function {f} has duplicate definition", .{current_function});157 log.err("Function {f} has duplicate definition", .{current_function});
158 return error.DuplicateId;158 return error.DuplicateId;
...@@ -170,7 +170,7 @@ const ModuleInfo = struct {...@@ -170,7 +170,7 @@ const ModuleInfo = struct {
170 .first_callee = first_callee,170 .first_callee = first_callee,
171 .return_type = fn_type.return_type,171 .return_type = fn_type.return_type,
172 .param_types = fn_type.param_types,172 .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),
174 };174 };
175 maybe_current_function = null;175 maybe_current_function = null;
176 calls.clearRetainingCapacity();176 calls.clearRetainingCapacity();
...@@ -181,7 +181,7 @@ const ModuleInfo = struct {...@@ -181,7 +181,7 @@ const ModuleInfo = struct {
181 for (result_id_offsets.items) |off| {181 for (result_id_offsets.items) |off| {
182 const result_id: ResultId = @enumFromInt(inst.operands[off]);182 const result_id: ResultId = @enumFromInt(inst.operands[off]);
183 if (invocation_globals.contains(result_id)) {183 if (invocation_globals.contains(result_id)) {
184 try function_invocation_globals.put(result_id, {});184 try function_invocation_globals.put(arena, result_id, {});
185 }185 }
186 }186 }
187 }187 }
...@@ -191,11 +191,11 @@ const ModuleInfo = struct {...@@ -191,11 +191,11 @@ const ModuleInfo = struct {
191 return error.InvalidPhysicalFormat;191 return error.InvalidPhysicalFormat;
192 }192 }
193193
194 return ModuleInfo{194 return .{
195 .functions = functions.unmanaged,195 .functions = functions,
196 .entry_points = entry_points.unmanaged,196 .entry_points = entry_points,
197 .callee_store = callee_store.items,197 .callee_store = callee_store.items,
198 .invocation_globals = invocation_globals.unmanaged,198 .invocation_globals = invocation_globals,
199 };199 };
200 }200 }
201201
...@@ -583,7 +583,8 @@ const ModuleBuilder = struct {...@@ -583,7 +583,8 @@ const ModuleBuilder = struct {
583 }583 }
584584
585 fn emitNewEntryPoints(self: *ModuleBuilder, info: ModuleInfo) !void {585 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
588 for (info.entry_points.keys(), 0..) |func, entry_point_index| {589 for (info.entry_points.keys(), 0..) |func, entry_point_index| {
589 const fn_info = info.functions.get(func).?;590 const fn_info = info.functions.get(func).?;
...@@ -593,7 +594,7 @@ const ModuleBuilder = struct {...@@ -593,7 +594,7 @@ const ModuleBuilder = struct {
593 .param_types = fn_info.param_types,594 .param_types = fn_info.param_types,
594 }).?;595 }).?;
595596
596 try self.section.emit(self.arena, .OpFunction, .{597 try self.section.emit(arena, .OpFunction, .{
597 .id_result_type = fn_info.return_type,598 .id_result_type = fn_info.return_type,
598 .id_result = ep_id,599 .id_result = ep_id,
599 .function_control = .{}, // TODO: Copy the attributes from the original function maybe?600 .function_control = .{}, // TODO: Copy the attributes from the original function maybe?
...@@ -604,13 +605,13 @@ const ModuleBuilder = struct {...@@ -604,13 +605,13 @@ const ModuleBuilder = struct {
604 const params_id_base: u32 = @intFromEnum(self.allocIds(@intCast(fn_info.param_types.len)));605 const params_id_base: u32 = @intFromEnum(self.allocIds(@intCast(fn_info.param_types.len)));
605 for (fn_info.param_types, 0..) |param_type, i| {606 for (fn_info.param_types, 0..) |param_type, i| {
606 const id: ResultId = @enumFromInt(params_id_base + @as(u32, @intCast(i)));607 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, .{
608 .id_result_type = param_type,609 .id_result_type = param_type,
609 .id_result = id,610 .id_result = id,
610 });611 });
611 }612 }
612613
613 try self.section.emit(self.arena, .OpLabel, .{614 try self.section.emit(arena, .OpLabel, .{
614 .id_result = self.allocId(),615 .id_result = self.allocId(),
615 });616 });
616617
...@@ -619,10 +620,10 @@ const ModuleBuilder = struct {...@@ -619,10 +620,10 @@ const ModuleBuilder = struct {
619 // Just quickly construct that set here.620 // Just quickly construct that set here.
620 all_function_invocation_globals.clearRetainingCapacity();621 all_function_invocation_globals.clearRetainingCapacity();
621 for (fn_info.invocation_globals.keys()) |global| {622 for (fn_info.invocation_globals.keys()) |global| {
622 try all_function_invocation_globals.put(global, {});623 try all_function_invocation_globals.put(arena, global, {});
623 const global_info = info.invocation_globals.get(global).?;624 const global_info = info.invocation_globals.get(global).?;
624 for (global_info.dependencies.keys()) |dependency| {625 for (global_info.dependencies.keys()) |dependency| {
625 try all_function_invocation_globals.put(dependency, {});626 try all_function_invocation_globals.put(arena, dependency, {});
626 }627 }
627 }628 }
628629
...@@ -632,7 +633,7 @@ const ModuleBuilder = struct {...@@ -632,7 +633,7 @@ const ModuleBuilder = struct {
632 const global_info = info.invocation_globals.get(global).?;633 const global_info = info.invocation_globals.get(global).?;
633634
634 const id: ResultId = @enumFromInt(global_id_base + @as(u32, @intCast(i)));635 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, .{
636 .id_result_type = global_info.ty,637 .id_result_type = global_info.ty,
637 .id_result = id,638 .id_result = id,
638 .storage_class = .function,639 .storage_class = .function,
...@@ -649,7 +650,7 @@ const ModuleBuilder = struct {...@@ -649,7 +650,7 @@ const ModuleBuilder = struct {
649 assert(initializer_info.param_types.len == 0);650 assert(initializer_info.param_types.len == 0);
650651
651 try self.callWithGlobalsAndLinearParams(652 try self.callWithGlobalsAndLinearParams(
652 all_function_invocation_globals,653 &all_function_invocation_globals,
653 global_info.initializer,654 global_info.initializer,
654 initializer_info,655 initializer_info,
655 global_id_base,656 global_id_base,
...@@ -659,21 +660,21 @@ const ModuleBuilder = struct {...@@ -659,21 +660,21 @@ const ModuleBuilder = struct {
659660
660 // Call the main kernel entry661 // Call the main kernel entry
661 try self.callWithGlobalsAndLinearParams(662 try self.callWithGlobalsAndLinearParams(
662 all_function_invocation_globals,663 &all_function_invocation_globals,
663 func,664 func,
664 fn_info,665 fn_info,
665 global_id_base,666 global_id_base,
666 params_id_base,667 params_id_base,
667 );668 );
668669
669 try self.section.emit(self.arena, .OpReturn, {});670 try self.section.emit(arena, .OpReturn, {});
670 try self.section.emit(self.arena, .OpFunctionEnd, {});671 try self.section.emit(arena, .OpFunctionEnd, {});
671 }672 }
672 }673 }
673674
674 fn callWithGlobalsAndLinearParams(675 fn callWithGlobalsAndLinearParams(
675 self: *ModuleBuilder,676 self: *ModuleBuilder,
676 all_globals: std.AutoArrayHashMap(ResultId, void),677 all_globals: *const std.array_hash_map.Auto(ResultId, void),
677 func: ResultId,678 func: ResultId,
678 callee_info: ModuleInfo.Fn,679 callee_info: ModuleInfo.Fn,
679 global_id_base: u32,680 global_id_base: u32,
src/link/Wasm.zig+3-3
...@@ -3088,11 +3088,11 @@ fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void {...@@ -3088,11 +3088,11 @@ fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void {
3088 // In this case we must force link all embedded object files within the archive3088 // In this case we must force link all embedded object files within the archive
3089 // We loop over all symbols, and then group them by offset as the offset3089 // We loop over all symbols, and then group them by offset as the offset
3090 // notates where the object file starts.3090 // notates where the object file starts.
3091 var offsets = std.AutoArrayHashMap(u32, void).init(gpa);3091 var offsets: std.array_hash_map.Auto(u32, void) = .empty;
3092 defer offsets.deinit();3092 defer offsets.deinit(gpa);
3093 for (archive.toc.values()) |symbol_offsets| {3093 for (archive.toc.values()) |symbol_offsets| {
3094 for (symbol_offsets.items) |sym_offset| {3094 for (symbol_offsets.items) |sym_offset| {
3095 try offsets.put(sym_offset, {});3095 try offsets.put(gpa, sym_offset, {});
3096 }3096 }
3097 }3097 }
30983098
tools/gen_spirv_spec.zig+11-11
...@@ -44,7 +44,7 @@ const StringPairContext = struct {...@@ -44,7 +44,7 @@ const StringPairContext = struct {
44 }44 }
45};45};
4646
47const OperandKindMap = std.ArrayHashMap(StringPair, OperandKind, StringPairContext, true);47const OperandKindMap = std.array_hash_map.Custom(StringPair, OperandKind, StringPairContext, true);
4848
49/// Khronos made it so that these names are not defined explicitly, so49/// Khronos made it so that these names are not defined explicitly, so
50/// we need to hardcode it (like they did).50/// we need to hardcode it (like they did).
...@@ -295,9 +295,9 @@ fn render(...@@ -295,9 +295,9 @@ fn render(
295 );295 );
296296
297 // Merge the operand kinds from all extensions together.297 // Merge the operand kinds from all extensions together.
298 var all_operand_kinds = OperandKindMap.init(arena);298 var all_operand_kinds: OperandKindMap = .empty;
299 for (registry.operand_kinds) |kind| {299 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);
301 }301 }
302 for (extensions) |ext| {302 for (extensions) |ext| {
303 // Note: extensions may define the same operand kind, with different303 // Note: extensions may define the same operand kind, with different
...@@ -305,11 +305,11 @@ fn render(...@@ -305,11 +305,11 @@ fn render(
305 // using the name of the extension. This is similar to what305 // using the name of the extension. This is similar to what
306 // the official headers do.306 // 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);
309 for (ext.spec.operand_kinds) |kind| {309 for (ext.spec.operand_kinds) |kind| {
310 var new_kind = kind;310 var new_kind = kind;
311 new_kind.kind = try std.mem.join(arena, ".", &.{ ext.name, kind.kind });311 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);
313 }313 }
314 }314 }
315315
...@@ -411,11 +411,11 @@ fn renderInstructionsCase(...@@ -411,11 +411,11 @@ fn renderInstructionsCase(
411}411}
412412
413fn renderClass(arena: Allocator, writer: *std.Io.Writer, instructions: []const Instruction) !void {413fn 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
416 for (instructions) |inst| {416 for (instructions) |inst| {
417 if (std.mem.eql(u8, inst.class.?, "@exclude")) continue;417 if (std.mem.eql(u8, inst.class.?, "@exclude")) continue;
418 try class_map.put(inst.class.?, {});418 try class_map.put(arena, inst.class.?, {});
419 }419 }
420420
421 try writer.writeAll("pub const Class = enum {\n");421 try writer.writeAll("pub const Class = enum {\n");
...@@ -538,8 +538,8 @@ fn renderOpcodes(...@@ -538,8 +538,8 @@ fn renderOpcodes(
538 instructions: []const Instruction,538 instructions: []const Instruction,
539 extended_structs: ExtendedStructSet,539 extended_structs: ExtendedStructSet,
540) !void {540) !void {
541 var inst_map = std.AutoArrayHashMap(u32, usize).init(arena);541 var inst_map: std.array_hash_map.Auto(u32, usize) = .empty;
542 try inst_map.ensureTotalCapacity(instructions.len);542 try inst_map.ensureTotalCapacity(arena, instructions.len);
543543
544 var aliases = std.array_list.Managed(struct { inst: usize, alias: usize }).init(arena);544 var aliases = std.array_list.Managed(struct { inst: usize, alias: usize }).init(arena);
545 try aliases.ensureTotalCapacity(instructions.len);545 try aliases.ensureTotalCapacity(instructions.len);
...@@ -653,8 +653,8 @@ fn renderValueEnum(...@@ -653,8 +653,8 @@ fn renderValueEnum(
653) !void {653) !void {
654 const enumerants = enumeration.enumerants orelse return error.InvalidRegistry;654 const enumerants = enumeration.enumerants orelse return error.InvalidRegistry;
655655
656 var enum_map = std.AutoArrayHashMap(u32, usize).init(arena);656 var enum_map: std.array_hash_map.Auto(u32, usize) = .empty;
657 try enum_map.ensureTotalCapacity(enumerants.len);657 try enum_map.ensureTotalCapacity(arena, enumerants.len);
658658
659 var aliases = std.array_list.Managed(struct { enumerant: usize, alias: usize }).init(arena);659 var aliases = std.array_list.Managed(struct { enumerant: usize, alias: usize }).init(arena);
660 try aliases.ensureTotalCapacity(enumerants.len);660 try aliases.ensureTotalCapacity(enumerants.len);
tools/gen_stubs.zig+10-14
...@@ -274,8 +274,8 @@ const MultiSym = struct {...@@ -274,8 +274,8 @@ const MultiSym = struct {
274274
275const Parse = struct {275const Parse = struct {
276 arena: mem.Allocator,276 arena: mem.Allocator,
277 sym_table: *std.StringArrayHashMap(MultiSym),277 sym_table: *std.array_hash_map.String(MultiSym),
278 sections: *std.StringArrayHashMap(void),278 sections: *std.array_hash_map.String(void),
279 elf_bytes: []align(@alignOf(elf.Elf64_Ehdr)) u8,279 elf_bytes: []align(@alignOf(elf.Elf64_Ehdr)) u8,
280 header: elf.Header,280 header: elf.Header,
281 arch: Arch,281 arch: Arch,
...@@ -289,13 +289,11 @@ pub fn main(init: std.process.Init) !void {...@@ -289,13 +289,11 @@ pub fn main(init: std.process.Init) !void {
289289
290 var build_all_dir = try Io.Dir.cwd().openDir(io, build_all_path, .{});290 var build_all_dir = try Io.Dir.cwd().openDir(io, build_all_path, .{});
291291
292 var sym_table = std.StringArrayHashMap(MultiSym).init(arena);292 var sym_table: std.array_hash_map.String(MultiSym) = .empty;
293 var sections = std.StringArrayHashMap(void).init(arena);293 var sections: std.array_hash_map.String(void) = .empty;
294294
295 for (arches) |arch| {295 for (arches) |arch| {
296 const libc_so_path = try std.fmt.allocPrint(arena, "{s}/lib/libc.so", .{296 const libc_so_path = try std.fmt.allocPrint(arena, "{t}/lib/libc.so", .{arch});
297 @tagName(arch),
298 });
299297
300 // Read the ELF header.298 // Read the ELF header.
301 const elf_bytes = build_all_dir.readFileAllocOptions(299 const elf_bytes = build_all_dir.readFileAllocOptions(
...@@ -306,9 +304,7 @@ pub fn main(init: std.process.Init) !void {...@@ -306,9 +304,7 @@ pub fn main(init: std.process.Init) !void {
306 .of(elf.Elf64_Ehdr),304 .of(elf.Elf64_Ehdr),
307 null,305 null,
308 ) catch |err| {306 ) catch |err| {
309 std.debug.panic("unable to read '{s}/{s}': {s}", .{307 std.debug.panic("unable to read '{s}/{s}': {t}", .{ build_all_path, libc_so_path, err });
310 build_all_path, libc_so_path, @errorName(err),
311 });
312 };308 };
313 var stream: std.Io.Reader = .fixed(elf_bytes);309 var stream: std.Io.Reader = .fixed(elf_bytes);
314 const header = try elf.Header.read(&stream);310 const header = try elf.Header.read(&stream);
...@@ -359,8 +355,8 @@ pub fn main(init: std.process.Init) !void {...@@ -359,8 +355,8 @@ pub fn main(init: std.process.Init) !void {
359355
360 // Sort the symbols for deterministic output and cleaner vcs diffs.356 // Sort the symbols for deterministic output and cleaner vcs diffs.
361 const SymTableSort = struct {357 const SymTableSort = struct {
362 sections: *const std.StringArrayHashMap(void),358 sections: *const std.array_hash_map.String(void),
363 sym_table: *const std.StringArrayHashMap(MultiSym),359 sym_table: *const std.array_hash_map.String(MultiSym),
364360
365 /// Sort first by section name, then by symbol name361 /// Sort first by section name, then by symbol name
366 pub fn lessThan(ctx: @This(), index_a: usize, index_b: usize) bool {362 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...@@ -580,7 +576,7 @@ fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: std.builtin.End
580 if (mem.eql(u8, sh_name, ".dynsym")) {576 if (mem.eql(u8, sh_name, ".dynsym")) {
581 dynsym_index = @as(u16, @intCast(i));577 dynsym_index = @as(u16, @intCast(i));
582 }578 }
583 const gop = try parse.sections.getOrPut(sh_name);579 const gop = try parse.sections.getOrPut(arena, sh_name);
584 section_index_map[i] = @as(u16, @intCast(gop.index));580 section_index_map[i] = @as(u16, @intCast(gop.index));
585 }581 }
586 if (dynsym_index == 0) @panic("did not find the .dynsym section");582 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...@@ -653,7 +649,7 @@ fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: std.builtin.End
653 },649 },
654 }650 }
655651
656 const gop = try parse.sym_table.getOrPut(name);652 const gop = try parse.sym_table.getOrPut(arena, name);
657 if (gop.found_existing) {653 if (gop.found_existing) {
658 if (gop.value_ptr.section != section_index_map[this_section]) {654 if (gop.value_ptr.section != section_index_map[this_section]) {
659 const sh_name = mem.sliceTo(shstrtab[s(shdrs[this_section].sh_name)..], 0);655 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 {...@@ -130,7 +130,7 @@ const Contents = struct {
130};130};
131131
132const HashToContents = std.StringHashMap(Contents);132const HashToContents = std.StringHashMap(Contents);
133const TargetToHash = std.StringArrayHashMap([]const u8);133const TargetToHash = std.array_hash_map.String([]const u8);
134const PathTable = std.StringHashMap(*TargetToHash);134const PathTable = std.StringHashMap(*TargetToHash);
135135
136const LibCVendor = enum {136const LibCVendor = enum {
...@@ -317,7 +317,7 @@ pub fn main(init: std.process.Init) !void {...@@ -317,7 +317,7 @@ pub fn main(init: std.process.Init) !void {
317 const path_gop = try path_table.getOrPut(rel_path);317 const path_gop = try path_table.getOrPut(rel_path);
318 const target_to_hash = if (path_gop.found_existing) path_gop.value_ptr.* else blk: {318 const target_to_hash = if (path_gop.found_existing) path_gop.value_ptr.* else blk: {
319 const ptr = try arena.create(TargetToHash);319 const ptr = try arena.create(TargetToHash);
320 ptr.* = TargetToHash.init(arena);320 ptr.* = .empty;
321 path_gop.value_ptr.* = ptr;321 path_gop.value_ptr.* = ptr;
322 break :blk ptr;322 break :blk ptr;
323 };323 };
...@@ -327,14 +327,14 @@ pub fn main(init: std.process.Init) !void {...@@ -327,14 +327,14 @@ pub fn main(init: std.process.Init) !void {
327 // such cases, we manually patch the affected header after processing, so it's fine that327 // such cases, we manually patch the affected header after processing, so it's fine that
328 // only one header wins here.328 // only one header wins here.
329 if (libc_target.dest != null) {329 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);
331 if (hash_gop.found_existing) std.debug.print("overwrote: {s} {s} {s}\n", .{331 if (hash_gop.found_existing) std.debug.print("overwrote: {s} {s} {s}\n", .{
332 libc_dir,332 libc_dir,
333 rel_path,333 rel_path,
334 dest_target,334 dest_target,
335 }) else hash_gop.value_ptr.* = hash;335 }) else hash_gop.value_ptr.* = hash;
336 } else {336 } else {
337 try target_to_hash.putNoClobber(dest_target, hash);337 try target_to_hash.putNoClobber(arena, dest_target, hash);
338 }338 }
339 },339 },
340 else => std.debug.print("warning: weird file: {s}\n", .{full_path}),340 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 {...@@ -138,7 +138,7 @@ const Contents = struct {
138};138};
139139
140const HashToContents = std.StringHashMap(Contents);140const 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);
142const PathTable = std.StringHashMap(*TargetToHash);142const PathTable = std.StringHashMap(*TargetToHash);
143143
144pub fn main(init: std.process.Init) !void {144pub fn main(init: std.process.Init) !void {
...@@ -239,11 +239,11 @@ pub fn main(init: std.process.Init) !void {...@@ -239,11 +239,11 @@ pub fn main(init: std.process.Init) !void {
239 const path_gop = try path_table.getOrPut(rel_path);239 const path_gop = try path_table.getOrPut(rel_path);
240 const target_to_hash = if (path_gop.found_existing) path_gop.value_ptr.* else blk: {240 const target_to_hash = if (path_gop.found_existing) path_gop.value_ptr.* else blk: {
241 const ptr = try arena.create(TargetToHash);241 const ptr = try arena.create(TargetToHash);
242 ptr.* = TargetToHash.init(arena);242 ptr.* = .empty;
243 path_gop.value_ptr.* = ptr;243 path_gop.value_ptr.* = ptr;
244 break :blk ptr;244 break :blk ptr;
245 };245 };
246 try target_to_hash.putNoClobber(dest_target, hash);246 try target_to_hash.putNoClobber(arena, dest_target, hash);
247 },247 },
248 else => std.debug.print("warning: weird file: {s}\n", .{full_path}),248 else => std.debug.print("warning: weird file: {s}\n", .{full_path}),
249 }249 }