authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-08-05 14:48:54-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-08-05 15:08:51-07:00
log1e5d24a009ffef49f0888b3d6ea46aec8a82d40b
treea6e16c36365387b062c72e12919b5d04f7af28ad
parentc9533046ca37a053f487f4002a999a29a96de517

std: extract mem.Allocator.SliceType to meta.Slice


2 files changed, 37 insertions(+), 31 deletions(-)

lib/std/mem/Allocator.zig+8-26
...@@ -8,6 +8,7 @@ const assert = std.debug.assert;...@@ -8,6 +8,7 @@ const assert = std.debug.assert;
8const math = std.math;8const math = std.math;
9const mem = std.mem;9const mem = std.mem;
10const Alignment = std.mem.Alignment;10const Alignment = std.mem.Alignment;
11const Slice = std.meta.Slice;
1112
12pub const Error = error{OutOfMemory};13pub const Error = error{OutOfMemory};
13pub const Log2Align = math.Log2Int(usize);14pub const Log2Align = math.Log2Int(usize);
...@@ -305,25 +306,6 @@ pub fn allocBytesAligned(...@@ -305,25 +306,6 @@ pub fn allocBytesAligned(
305 return @alignCast(byte_ptr);306 return @alignCast(byte_ptr);
306}307}
307308
308fn SliceType(comptime Pointer: type) type {
309 const info = @typeInfo(Pointer).pointer;
310 switch (info.size) {
311 .slice => return Pointer,
312 .one => {
313 const child_info = @typeInfo(info.child);
314 comptime assert(child_info == .array);
315 const sentinel_ptr: ?*const child_info.array.child = @ptrCast(@alignCast(child_info.array.sentinel_ptr));
316 return @Pointer(
317 .slice,
318 info.attrs,
319 child_info.array.child,
320 if (sentinel_ptr) |ptr| ptr.* else null,
321 );
322 },
323 else => unreachable,
324 }
325}
326
327/// Request to modify the size of an allocation.309/// Request to modify the size of an allocation.
328///310///
329/// It is guaranteed to not move the pointer, however the allocator311/// It is guaranteed to not move the pointer, however the allocator
...@@ -336,7 +318,7 @@ fn SliceType(comptime Pointer: type) type {...@@ -336,7 +318,7 @@ fn SliceType(comptime Pointer: type) type {
336pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {318pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
337 const slice_info = @typeInfo(@TypeOf(allocation)).pointer;319 const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
338 if (slice_info.size != .slice) {320 if (slice_info.size != .slice) {
339 const slice: SliceType(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T321 const slice: Slice(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T
340 return resize(self, slice, new_len);322 return resize(self, slice, new_len);
341 }323 }
342 comptime assert(slice_info.size == .slice);324 comptime assert(slice_info.size == .slice);
...@@ -377,10 +359,10 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {...@@ -377,10 +359,10 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
377/// `new_len` may be zero, in which case the allocation is freed.359/// `new_len` may be zero, in which case the allocation is freed.
378///360///
379/// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`.361/// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`.
380pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?SliceType(@TypeOf(allocation)) {362pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?Slice(@TypeOf(allocation)) {
381 const slice_info = @typeInfo(@TypeOf(allocation)).pointer;363 const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
382 if (slice_info.size != .slice) {364 if (slice_info.size != .slice) {
383 const slice: SliceType(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T365 const slice: Slice(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T
384 return remap(self, slice, new_len);366 return remap(self, slice, new_len);
385 }367 }
386 comptime assert(slice_info.size == .slice);368 comptime assert(slice_info.size == .slice);
...@@ -426,7 +408,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?SliceType(@T...@@ -426,7 +408,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?SliceType(@T
426/// do the realloc more efficiently than the caller408/// do the realloc more efficiently than the caller
427/// * `resize` which returns `false` when the `Allocator` implementation cannot409/// * `resize` which returns `false` when the `Allocator` implementation cannot
428/// change the size without relocating the allocation.410/// change the size without relocating the allocation.
429pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!SliceType(@TypeOf(old_mem)) {411pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!Slice(@TypeOf(old_mem)) {
430 return self.reallocAdvanced(old_mem, new_n, @returnAddress());412 return self.reallocAdvanced(old_mem, new_n, @returnAddress());
431}413}
432414
...@@ -435,10 +417,10 @@ pub fn reallocAdvanced(...@@ -435,10 +417,10 @@ pub fn reallocAdvanced(
435 old_mem: anytype,417 old_mem: anytype,
436 new_n: usize,418 new_n: usize,
437 return_address: usize,419 return_address: usize,
438) Error!SliceType(@TypeOf(old_mem)) {420) Error!Slice(@TypeOf(old_mem)) {
439 const slice_info = @typeInfo(@TypeOf(old_mem)).pointer;421 const slice_info = @typeInfo(@TypeOf(old_mem)).pointer;
440 if (slice_info.size != .slice) {422 if (slice_info.size != .slice) {
441 const slice: SliceType(@TypeOf(old_mem)) = old_mem; // coerce *[len]T to []T423 const slice: Slice(@TypeOf(old_mem)) = old_mem; // coerce *[len]T to []T
442 return reallocAdvanced(self, slice, new_n, return_address);424 return reallocAdvanced(self, slice, new_n, return_address);
443 }425 }
444 comptime assert(slice_info.size == .slice);426 comptime assert(slice_info.size == .slice);
...@@ -477,7 +459,7 @@ pub fn reallocAdvanced(...@@ -477,7 +459,7 @@ pub fn reallocAdvanced(
477pub fn free(self: Allocator, memory: anytype) void {459pub fn free(self: Allocator, memory: anytype) void {
478 const slice_info = @typeInfo(@TypeOf(memory)).pointer;460 const slice_info = @typeInfo(@TypeOf(memory)).pointer;
479 if (slice_info.size != .slice) {461 if (slice_info.size != .slice) {
480 const slice: SliceType(@TypeOf(memory)) = memory; // coerce *[len]T to []T462 const slice: Slice(@TypeOf(memory)) = memory; // coerce *[len]T to []T
481 return free(self, slice);463 return free(self, slice);
482 }464 }
483 comptime assert(slice_info.size == .slice);465 comptime assert(slice_info.size == .slice);
lib/std/meta.zig+29-5
...@@ -1,10 +1,9 @@...@@ -1,10 +1,9 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2
2const std = @import("std.zig");3const std = @import("std.zig");
3const debug = std.debug;4const assert = std.debug.assert;
4const mem = std.mem;5const mem = std.mem;
5const math = std.math;
6const testing = std.testing;6const testing = std.testing;
7const root = @import("root");
87
9pub const TrailerFlags = @import("meta/trailer_flags.zig").TrailerFlags;8pub const TrailerFlags = @import("meta/trailer_flags.zig").TrailerFlags;
109
...@@ -821,8 +820,8 @@ pub fn isError(error_union: anytype) bool {...@@ -821,8 +820,8 @@ pub fn isError(error_union: anytype) bool {
821}820}
822821
823test isError {822test isError {
824 try std.testing.expect(isError(math.divTrunc(u8, 5, 0)));823 try std.testing.expect(isError(std.math.divTrunc(u8, 5, 0)));
825 try std.testing.expect(!isError(math.divTrunc(u8, 5, 5)));824 try std.testing.expect(!isError(std.math.divTrunc(u8, 5, 5)));
826}825}
827826
828/// Returns true if a type has a namespace and the namespace contains `name`;827/// Returns true if a type has a namespace and the namespace contains `name`;
...@@ -1070,3 +1069,28 @@ test hasUniqueRepresentation {...@@ -1070,3 +1069,28 @@ test hasUniqueRepresentation {
10701069
1071 try testing.expect(hasUniqueRepresentation(StructWithComptimeFields));1070 try testing.expect(hasUniqueRepresentation(StructWithComptimeFields));
1072}1071}
1072
1073/// Given a pointer type, type-erases the array length if present, returning an
1074/// equivalent pointer type that is always a slice.
1075pub fn Slice(comptime Pointer: type) type {
1076 const info = @typeInfo(Pointer).pointer;
1077 switch (info.size) {
1078 .slice => return Pointer,
1079 .one => {
1080 const child_info = @typeInfo(info.child);
1081 comptime assert(child_info == .array);
1082 const sentinel_ptr: ?*const child_info.array.child = @ptrCast(@alignCast(child_info.array.sentinel_ptr));
1083 return @Pointer(
1084 .slice,
1085 info.attrs,
1086 child_info.array.child,
1087 if (sentinel_ptr) |ptr| ptr.* else null,
1088 );
1089 },
1090 else => unreachable,
1091 }
1092}
1093
1094test Slice {
1095 try testing.expectEqual([]i32, Slice(*[10]i32));
1096}