authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-03-25 13:45:10+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-03-25 15:23:08+01:00
log7d8a556ba92474d78b465b30c8d5df64e9775d93
tree497f7266c1a24ed35df05cd3ac7f327228d59aef
parent1aca3dd6e07a9285d9455a527f3ee676f15afb1b
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

Merge pull request #23220 from samy-00007/bytesAsSlice-fix

Minor fix for `Allocator.remap` and `mem.bytesAsSlice` for zero-sized types

3 files changed, 51 insertions(+), 1 deletions(-)

lib/std/json/static_test.zig+16
...@@ -925,3 +925,19 @@ test "parse at comptime" {...@@ -925,3 +925,19 @@ test "parse at comptime" {
925 };925 };
926 comptime testing.expectEqual(@as(u64, 9999), config.uptime) catch unreachable;926 comptime testing.expectEqual(@as(u64, 9999), config.uptime) catch unreachable;
927}927}
928
929test "parse with zero-bit field" {
930 const str =
931 \\{
932 \\ "a": ["a", "a"],
933 \\ "b": "a"
934 \\}
935 ;
936 const ZeroSizedEnum = enum { a };
937 try testing.expectEqual(0, @sizeOf(ZeroSizedEnum));
938
939 const Inner = struct { a: []const ZeroSizedEnum, b: ZeroSizedEnum };
940 const expected: Inner = .{ .a = &.{ .a, .a }, .b = .a };
941
942 try testAllParseFunctions(Inner, expected, str);
943}
lib/std/mem.zig+27-1
...@@ -228,6 +228,18 @@ test "Allocator.resize" {...@@ -228,6 +228,18 @@ test "Allocator.resize" {
228 }228 }
229}229}
230230
231test "Allocator alloc and remap with zero-bit type" {
232 var values = try testing.allocator.alloc(void, 10);
233 defer testing.allocator.free(values);
234
235 try testing.expectEqual(10, values.len);
236 const remaped = testing.allocator.remap(values, 200);
237 try testing.expect(remaped != null);
238
239 values = remaped.?;
240 try testing.expectEqual(200, values.len);
241}
242
231/// Copy all of source into dest at position 0.243/// Copy all of source into dest at position 0.
232/// dest.len must be >= source.len.244/// dest.len must be >= source.len.
233/// If the slices overlap, dest.ptr must be <= src.ptr.245/// If the slices overlap, dest.ptr must be <= src.ptr.
...@@ -4207,10 +4219,11 @@ fn BytesAsSliceReturnType(comptime T: type, comptime bytesType: type) type {...@@ -4207,10 +4219,11 @@ fn BytesAsSliceReturnType(comptime T: type, comptime bytesType: type) type {
42074219
4208/// Given a slice of bytes, returns a slice of the specified type4220/// Given a slice of bytes, returns a slice of the specified type
4209/// backed by those bytes, preserving pointer attributes.4221/// backed by those bytes, preserving pointer attributes.
4222/// If `T` is zero-bytes sized, the returned slice has a len of zero.
4210pub fn bytesAsSlice(comptime T: type, bytes: anytype) BytesAsSliceReturnType(T, @TypeOf(bytes)) {4223pub fn bytesAsSlice(comptime T: type, bytes: anytype) BytesAsSliceReturnType(T, @TypeOf(bytes)) {
4211 // let's not give an undefined pointer to @ptrCast4224 // let's not give an undefined pointer to @ptrCast
4212 // it may be equal to zero and fail a null check4225 // it may be equal to zero and fail a null check
4213 if (bytes.len == 0) {4226 if (bytes.len == 0 or @sizeOf(T) == 0) {
4214 return &[0]T{};4227 return &[0]T{};
4215 }4228 }
42164229
...@@ -4288,6 +4301,19 @@ test "bytesAsSlice preserves pointer attributes" {...@@ -4288,6 +4301,19 @@ test "bytesAsSlice preserves pointer attributes" {
4288 try testing.expectEqual(in.alignment, out.alignment);4301 try testing.expectEqual(in.alignment, out.alignment);
4289}4302}
42904303
4304test "bytesAsSlice with zero-bit element type" {
4305 {
4306 const bytes = [_]u8{};
4307 const slice = bytesAsSlice(void, &bytes);
4308 try testing.expectEqual(0, slice.len);
4309 }
4310 {
4311 const bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 };
4312 const slice = bytesAsSlice(u0, &bytes);
4313 try testing.expectEqual(0, slice.len);
4314 }
4315}
4316
4291fn SliceAsBytesReturnType(comptime Slice: type) type {4317fn SliceAsBytesReturnType(comptime Slice: type) type {
4292 return CopyPtrAttrs(Slice, .slice, u8);4318 return CopyPtrAttrs(Slice, .slice, u8);
4293}4319}
lib/std/mem/Allocator.zig+8
...@@ -312,12 +312,15 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {...@@ -312,12 +312,15 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
312/// unless `new_len` is also 0, in which case `allocation` is returned.312/// unless `new_len` is also 0, in which case `allocation` is returned.
313///313///
314/// `new_len` may be zero, in which case the allocation is freed.314/// `new_len` may be zero, in which case the allocation is freed.
315///
316/// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`.
315pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: {317pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: {
316 const Slice = @typeInfo(@TypeOf(allocation)).pointer;318 const Slice = @typeInfo(@TypeOf(allocation)).pointer;
317 break :t ?[]align(Slice.alignment) Slice.child;319 break :t ?[]align(Slice.alignment) Slice.child;
318} {320} {
319 const Slice = @typeInfo(@TypeOf(allocation)).pointer;321 const Slice = @typeInfo(@TypeOf(allocation)).pointer;
320 const T = Slice.child;322 const T = Slice.child;
323
321 const alignment = Slice.alignment;324 const alignment = Slice.alignment;
322 if (new_len == 0) {325 if (new_len == 0) {
323 self.free(allocation);326 self.free(allocation);
...@@ -326,6 +329,11 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: {...@@ -326,6 +329,11 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: {
326 if (allocation.len == 0) {329 if (allocation.len == 0) {
327 return null;330 return null;
328 }331 }
332 if (@sizeOf(T) == 0) {
333 var new_memory = allocation;
334 new_memory.len = new_len;
335 return new_memory;
336 }
329 const old_memory = mem.sliceAsBytes(allocation);337 const old_memory = mem.sliceAsBytes(allocation);
330 // I would like to use saturating multiplication here, but LLVM cannot lower it338 // I would like to use saturating multiplication here, but LLVM cannot lower it
331 // on WebAssembly: https://github.com/ziglang/zig/issues/9660339 // on WebAssembly: https://github.com/ziglang/zig/issues/9660