From 1e5d24a009ffef49f0888b3d6ea46aec8a82d40b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 5 Aug 2026 14:48:54 -0700 Subject: [PATCH] std: extract mem.Allocator.SliceType to meta.Slice --- lib/std/mem/Allocator.zig | 34 ++++++++-------------------------- lib/std/meta.zig | 34 +++++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 31 deletions(-) diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig index e442427169f56898da818f11e3587ebe4d348dc2..12d96f6030c030a11f1fd81419b6f10168b7cfa3 100644 --- a/lib/std/mem/Allocator.zig +++ b/lib/std/mem/Allocator.zig @@ -8,6 +8,7 @@ const assert = std.debug.assert; const math = std.math; const mem = std.mem; const Alignment = std.mem.Alignment; +const Slice = std.meta.Slice; pub const Error = error{OutOfMemory}; pub const Log2Align = math.Log2Int(usize); @@ -305,25 +306,6 @@ pub fn allocBytesAligned( return @alignCast(byte_ptr); } -fn SliceType(comptime Pointer: type) type { - const info = @typeInfo(Pointer).pointer; - switch (info.size) { - .slice => return Pointer, - .one => { - const child_info = @typeInfo(info.child); - comptime assert(child_info == .array); - const sentinel_ptr: ?*const child_info.array.child = @ptrCast(@alignCast(child_info.array.sentinel_ptr)); - return @Pointer( - .slice, - info.attrs, - child_info.array.child, - if (sentinel_ptr) |ptr| ptr.* else null, - ); - }, - else => unreachable, - } -} - /// Request to modify the size of an allocation. /// /// It is guaranteed to not move the pointer, however the allocator @@ -336,7 +318,7 @@ fn SliceType(comptime Pointer: type) type { pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { const slice_info = @typeInfo(@TypeOf(allocation)).pointer; if (slice_info.size != .slice) { - const slice: SliceType(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T + const slice: Slice(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T return resize(self, slice, new_len); } comptime assert(slice_info.size == .slice); @@ -377,10 +359,10 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { /// `new_len` may be zero, in which case the allocation is freed. /// /// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`. -pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?SliceType(@TypeOf(allocation)) { +pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?Slice(@TypeOf(allocation)) { const slice_info = @typeInfo(@TypeOf(allocation)).pointer; if (slice_info.size != .slice) { - const slice: SliceType(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T + const slice: Slice(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T return remap(self, slice, new_len); } comptime assert(slice_info.size == .slice); @@ -426,7 +408,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?SliceType(@T /// do the realloc more efficiently than the caller /// * `resize` which returns `false` when the `Allocator` implementation cannot /// change the size without relocating the allocation. -pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!SliceType(@TypeOf(old_mem)) { +pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!Slice(@TypeOf(old_mem)) { return self.reallocAdvanced(old_mem, new_n, @returnAddress()); } @@ -435,10 +417,10 @@ pub fn reallocAdvanced( old_mem: anytype, new_n: usize, return_address: usize, -) Error!SliceType(@TypeOf(old_mem)) { +) Error!Slice(@TypeOf(old_mem)) { const slice_info = @typeInfo(@TypeOf(old_mem)).pointer; if (slice_info.size != .slice) { - const slice: SliceType(@TypeOf(old_mem)) = old_mem; // coerce *[len]T to []T + const slice: Slice(@TypeOf(old_mem)) = old_mem; // coerce *[len]T to []T return reallocAdvanced(self, slice, new_n, return_address); } comptime assert(slice_info.size == .slice); @@ -477,7 +459,7 @@ pub fn reallocAdvanced( pub fn free(self: Allocator, memory: anytype) void { const slice_info = @typeInfo(@TypeOf(memory)).pointer; if (slice_info.size != .slice) { - const slice: SliceType(@TypeOf(memory)) = memory; // coerce *[len]T to []T + const slice: Slice(@TypeOf(memory)) = memory; // coerce *[len]T to []T return free(self, slice); } comptime assert(slice_info.size == .slice); diff --git a/lib/std/meta.zig b/lib/std/meta.zig index cfeb6a758524a4e0e5a3f9e6dcac57fd029123c6..76f0ae867f66dd158e30521bbd2c1e7e4ef53f9d 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -1,10 +1,9 @@ const builtin = @import("builtin"); + const std = @import("std.zig"); -const debug = std.debug; +const assert = std.debug.assert; const mem = std.mem; -const math = std.math; const testing = std.testing; -const root = @import("root"); pub const TrailerFlags = @import("meta/trailer_flags.zig").TrailerFlags; @@ -821,8 +820,8 @@ pub fn isError(error_union: anytype) bool { } test isError { - try std.testing.expect(isError(math.divTrunc(u8, 5, 0))); - try std.testing.expect(!isError(math.divTrunc(u8, 5, 5))); + try std.testing.expect(isError(std.math.divTrunc(u8, 5, 0))); + try std.testing.expect(!isError(std.math.divTrunc(u8, 5, 5))); } /// Returns true if a type has a namespace and the namespace contains `name`; @@ -1070,3 +1069,28 @@ test hasUniqueRepresentation { try testing.expect(hasUniqueRepresentation(StructWithComptimeFields)); } + +/// Given a pointer type, type-erases the array length if present, returning an +/// equivalent pointer type that is always a slice. +pub fn Slice(comptime Pointer: type) type { + const info = @typeInfo(Pointer).pointer; + switch (info.size) { + .slice => return Pointer, + .one => { + const child_info = @typeInfo(info.child); + comptime assert(child_info == .array); + const sentinel_ptr: ?*const child_info.array.child = @ptrCast(@alignCast(child_info.array.sentinel_ptr)); + return @Pointer( + .slice, + info.attrs, + child_info.array.child, + if (sentinel_ptr) |ptr| ptr.* else null, + ); + }, + else => unreachable, + } +} + +test Slice { + try testing.expectEqual([]i32, Slice(*[10]i32)); +} -- 2.54.0