From c03b733f0999418b234067cac51eac0e4412dfe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Sun, 27 Feb 2022 22:24:00 +0200 Subject: [PATCH] std.HashMap: return explicit errors (#11000) All errors from std.HashMap are allocation errors. Mark them as such. This is helpful when one wants to return explicit errors where HashMap is used. --- lib/std/hash_map.zig | 66 ++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/lib/std/hash_map.zig b/lib/std/hash_map.zig index 74d8a9e7c9..66d67bf08d 100644 --- a/lib/std/hash_map.zig +++ b/lib/std/hash_map.zig @@ -473,7 +473,7 @@ pub fn HashMap( /// Otherwise, puts a new item with undefined value, and /// the `Entry` pointers point to it. Caller should then initialize /// the value (but not the key). - pub fn getOrPut(self: *Self, key: K) !GetOrPutResult { + pub fn getOrPut(self: *Self, key: K) Allocator.Error!GetOrPutResult { return self.unmanaged.getOrPutContext(self.allocator, key, self.ctx); } @@ -483,7 +483,7 @@ pub fn HashMap( /// Otherwise, puts a new item with undefined key and value, and /// the `Entry` pointers point to it. Caller must then initialize /// the key and value. - pub fn getOrPutAdapted(self: *Self, key: anytype, ctx: anytype) !GetOrPutResult { + pub fn getOrPutAdapted(self: *Self, key: anytype, ctx: anytype) Allocator.Error!GetOrPutResult { return self.unmanaged.getOrPutContextAdapted(self.allocator, key, ctx, self.ctx); } @@ -509,7 +509,7 @@ pub fn HashMap( return self.unmanaged.getOrPutAssumeCapacityAdapted(self.allocator, key, ctx); } - pub fn getOrPutValue(self: *Self, key: K, value: V) !Entry { + pub fn getOrPutValue(self: *Self, key: K, value: V) Allocator.Error!Entry { return self.unmanaged.getOrPutValueContext(self.allocator, key, value, self.ctx); } @@ -517,14 +517,14 @@ pub fn HashMap( /// Increases capacity, guaranteeing that insertions up until the /// `expected_count` will not cause an allocation, and therefore cannot fail. - pub fn ensureTotalCapacity(self: *Self, expected_count: Size) !void { + pub fn ensureTotalCapacity(self: *Self, expected_count: Size) Allocator.Error!void { return self.unmanaged.ensureTotalCapacityContext(self.allocator, expected_count, self.ctx); } /// Increases capacity, guaranteeing that insertions up until /// `additional_count` **more** items will not cause an allocation, and /// therefore cannot fail. - pub fn ensureUnusedCapacity(self: *Self, additional_count: Size) !void { + pub fn ensureUnusedCapacity(self: *Self, additional_count: Size) Allocator.Error!void { return self.unmanaged.ensureUnusedCapacityContext(self.allocator, additional_count, self.ctx); } @@ -536,13 +536,13 @@ pub fn HashMap( /// Clobbers any existing data. To detect if a put would clobber /// existing data, see `getOrPut`. - pub fn put(self: *Self, key: K, value: V) !void { + pub fn put(self: *Self, key: K, value: V) Allocator.Error!void { return self.unmanaged.putContext(self.allocator, key, value, self.ctx); } /// Inserts a key-value pair into the hash map, asserting that no previous /// entry with the same key is already present - pub fn putNoClobber(self: *Self, key: K, value: V) !void { + pub fn putNoClobber(self: *Self, key: K, value: V) Allocator.Error!void { return self.unmanaged.putNoClobberContext(self.allocator, key, value, self.ctx); } @@ -561,7 +561,7 @@ pub fn HashMap( } /// Inserts a new `Entry` into the hash map, returning the previous one, if any. - pub fn fetchPut(self: *Self, key: K, value: V) !?KV { + pub fn fetchPut(self: *Self, key: K, value: V) Allocator.Error!?KV { return self.unmanaged.fetchPutContext(self.allocator, key, value, self.ctx); } @@ -647,19 +647,19 @@ pub fn HashMap( } /// Creates a copy of this map, using the same allocator - pub fn clone(self: Self) !Self { + pub fn clone(self: Self) Allocator.Error!Self { var other = try self.unmanaged.cloneContext(self.allocator, self.ctx); return other.promoteContext(self.allocator, self.ctx); } /// Creates a copy of this map, using a specified allocator - pub fn cloneWithAllocator(self: Self, new_allocator: Allocator) !Self { + pub fn cloneWithAllocator(self: Self, new_allocator: Allocator) Allocator.Error!Self { var other = try self.unmanaged.cloneContext(new_allocator, self.ctx); return other.promoteContext(new_allocator, self.ctx); } /// Creates a copy of this map, using a specified context - pub fn cloneWithContext(self: Self, new_ctx: anytype) !HashMap(K, V, @TypeOf(new_ctx), max_load_percentage) { + pub fn cloneWithContext(self: Self, new_ctx: anytype) Allocator.Error!HashMap(K, V, @TypeOf(new_ctx), max_load_percentage) { var other = try self.unmanaged.cloneContext(self.allocator, new_ctx); return other.promoteContext(self.allocator, new_ctx); } @@ -669,7 +669,7 @@ pub fn HashMap( self: Self, new_allocator: Allocator, new_ctx: anytype, - ) !HashMap(K, V, @TypeOf(new_ctx), max_load_percentage) { + ) Allocator.Error!HashMap(K, V, @TypeOf(new_ctx), max_load_percentage) { var other = try self.unmanaged.cloneContext(new_allocator, new_ctx); return other.promoteContext(new_allocator, new_ctx); } @@ -896,20 +896,20 @@ pub fn HashMapUnmanaged( pub const ensureCapacity = @compileError("deprecated; call `ensureUnusedCapacity` or `ensureTotalCapacity`"); - pub fn ensureTotalCapacity(self: *Self, allocator: Allocator, new_size: Size) !void { + pub fn ensureTotalCapacity(self: *Self, allocator: Allocator, new_size: Size) Allocator.Error!void { if (@sizeOf(Context) != 0) @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call ensureTotalCapacityContext instead."); return ensureTotalCapacityContext(self, allocator, new_size, undefined); } - pub fn ensureTotalCapacityContext(self: *Self, allocator: Allocator, new_size: Size, ctx: Context) !void { + pub fn ensureTotalCapacityContext(self: *Self, allocator: Allocator, new_size: Size, ctx: Context) Allocator.Error!void { if (new_size > self.size) try self.growIfNeeded(allocator, new_size - self.size, ctx); } - pub fn ensureUnusedCapacity(self: *Self, allocator: Allocator, additional_size: Size) !void { + pub fn ensureUnusedCapacity(self: *Self, allocator: Allocator, additional_size: Size) Allocator.Error!void { return ensureUnusedCapacityContext(self, allocator, additional_size, undefined); } - pub fn ensureUnusedCapacityContext(self: *Self, allocator: Allocator, additional_size: Size, ctx: Context) !void { + pub fn ensureUnusedCapacityContext(self: *Self, allocator: Allocator, additional_size: Size, ctx: Context) Allocator.Error!void { return ensureTotalCapacityContext(self, allocator, self.count() + additional_size, ctx); } @@ -986,12 +986,12 @@ pub fn HashMapUnmanaged( } /// Insert an entry in the map. Assumes it is not already present. - pub fn putNoClobber(self: *Self, allocator: Allocator, key: K, value: V) !void { + pub fn putNoClobber(self: *Self, allocator: Allocator, key: K, value: V) Allocator.Error!void { if (@sizeOf(Context) != 0) @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call putNoClobberContext instead."); return self.putNoClobberContext(allocator, key, value, undefined); } - pub fn putNoClobberContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) !void { + pub fn putNoClobberContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) Allocator.Error!void { assert(!self.containsContext(key, ctx)); try self.growIfNeeded(allocator, 1, ctx); @@ -1043,12 +1043,12 @@ pub fn HashMapUnmanaged( } /// Inserts a new `Entry` into the hash map, returning the previous one, if any. - pub fn fetchPut(self: *Self, allocator: Allocator, key: K, value: V) !?KV { + pub fn fetchPut(self: *Self, allocator: Allocator, key: K, value: V) Allocator.Error!?KV { if (@sizeOf(Context) != 0) @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call fetchPutContext instead."); return self.fetchPutContext(allocator, key, value, undefined); } - pub fn fetchPutContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) !?KV { + pub fn fetchPutContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) Allocator.Error!?KV { const gop = try self.getOrPutContext(allocator, key, ctx); var result: ?KV = null; if (gop.found_existing) { @@ -1182,12 +1182,12 @@ pub fn HashMapUnmanaged( } /// Insert an entry if the associated key is not already present, otherwise update preexisting value. - pub fn put(self: *Self, allocator: Allocator, key: K, value: V) !void { + pub fn put(self: *Self, allocator: Allocator, key: K, value: V) Allocator.Error!void { if (@sizeOf(Context) != 0) @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call putContext instead."); return self.putContext(allocator, key, value, undefined); } - pub fn putContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) !void { + pub fn putContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) Allocator.Error!void { const result = try self.getOrPutContext(allocator, key, ctx); result.value_ptr.* = value; } @@ -1256,24 +1256,24 @@ pub fn HashMapUnmanaged( return null; } - pub fn getOrPut(self: *Self, allocator: Allocator, key: K) !GetOrPutResult { + pub fn getOrPut(self: *Self, allocator: Allocator, key: K) Allocator.Error!GetOrPutResult { if (@sizeOf(Context) != 0) @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getOrPutContext instead."); return self.getOrPutContext(allocator, key, undefined); } - pub fn getOrPutContext(self: *Self, allocator: Allocator, key: K, ctx: Context) !GetOrPutResult { + pub fn getOrPutContext(self: *Self, allocator: Allocator, key: K, ctx: Context) Allocator.Error!GetOrPutResult { const gop = try self.getOrPutContextAdapted(allocator, key, ctx, ctx); if (!gop.found_existing) { gop.key_ptr.* = key; } return gop; } - pub fn getOrPutAdapted(self: *Self, allocator: Allocator, key: anytype, key_ctx: anytype) !GetOrPutResult { + pub fn getOrPutAdapted(self: *Self, allocator: Allocator, key: anytype, key_ctx: anytype) Allocator.Error!GetOrPutResult { if (@sizeOf(Context) != 0) @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getOrPutContextAdapted instead."); return self.getOrPutContextAdapted(allocator, key, key_ctx, undefined); } - pub fn getOrPutContextAdapted(self: *Self, allocator: Allocator, key: anytype, key_ctx: anytype, ctx: Context) !GetOrPutResult { + pub fn getOrPutContextAdapted(self: *Self, allocator: Allocator, key: anytype, key_ctx: anytype, ctx: Context) Allocator.Error!GetOrPutResult { self.growIfNeeded(allocator, 1, ctx) catch |err| { // If allocation fails, try to do the lookup anyway. // If we find an existing item, we can return it. @@ -1367,12 +1367,12 @@ pub fn HashMapUnmanaged( }; } - pub fn getOrPutValue(self: *Self, allocator: Allocator, key: K, value: V) !Entry { + pub fn getOrPutValue(self: *Self, allocator: Allocator, key: K, value: V) Allocator.Error!Entry { if (@sizeOf(Context) != 0) @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getOrPutValueContext instead."); return self.getOrPutValueContext(allocator, key, value, undefined); } - pub fn getOrPutValueContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) !Entry { + pub fn getOrPutValueContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) Allocator.Error!Entry { const res = try self.getOrPutAdapted(allocator, key, ctx); if (!res.found_existing) { res.key_ptr.* = key; @@ -1450,18 +1450,18 @@ pub fn HashMapUnmanaged( return @truncate(Size, max_load - self.available); } - fn growIfNeeded(self: *Self, allocator: Allocator, new_count: Size, ctx: Context) !void { + fn growIfNeeded(self: *Self, allocator: Allocator, new_count: Size, ctx: Context) Allocator.Error!void { if (new_count > self.available) { try self.grow(allocator, capacityForSize(self.load() + new_count), ctx); } } - pub fn clone(self: Self, allocator: Allocator) !Self { + pub fn clone(self: Self, allocator: Allocator) Allocator.Error!Self { if (@sizeOf(Context) != 0) @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call cloneContext instead."); return self.cloneContext(allocator, @as(Context, undefined)); } - pub fn cloneContext(self: Self, allocator: Allocator, new_ctx: anytype) !HashMapUnmanaged(K, V, @TypeOf(new_ctx), max_load_percentage) { + pub fn cloneContext(self: Self, allocator: Allocator, new_ctx: anytype) Allocator.Error!HashMapUnmanaged(K, V, @TypeOf(new_ctx), max_load_percentage) { var other = HashMapUnmanaged(K, V, @TypeOf(new_ctx), max_load_percentage){}; if (self.size == 0) return other; @@ -1486,7 +1486,7 @@ pub fn HashMapUnmanaged( return other; } - fn grow(self: *Self, allocator: Allocator, new_capacity: Size, ctx: Context) !void { + fn grow(self: *Self, allocator: Allocator, new_capacity: Size, ctx: Context) Allocator.Error!void { @setCold(true); const new_cap = std.math.max(new_capacity, minimal_capacity); assert(new_cap > self.capacity()); @@ -1517,7 +1517,7 @@ pub fn HashMapUnmanaged( std.mem.swap(Self, self, &map); } - fn allocate(self: *Self, allocator: Allocator, new_capacity: Size) !void { + fn allocate(self: *Self, allocator: Allocator, new_capacity: Size) Allocator.Error!void { const header_align = @alignOf(Header); const key_align = if (@sizeOf(K) == 0) 1 else @alignOf(K); const val_align = if (@sizeOf(V) == 0) 1 else @alignOf(V);