authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-12 05:59:28-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-12 05:59:28-07:00
log3c2a43fdcc2d9aeafafe7ef37c7b805e18fac351
tree99050b8c99b38756448f321c145b926d0efff95c
parentabc9530a88d24350481d9264edcde300f293929a

Revert "std: check types of pointers passed to allocator functions"

This reverts commit abc9530a88d24350481d9264edcde300f293929a. This patch implies that the idiomatic Zig way of handling anytype parameter is to write a bunch of boilerplate instead of directly accessing type information and relying on the compiler to be useful. I don't want it to be this way. It is the compiler's job to make useful error messages when the wrong field of a type info result is accessed, and it is the zig programmer's job to understand what it means when a compile error points at the field access of `@typeInfo` (along with the relevant callsites). One thing that might be useful would be having the compiler be aware of module boundaries and highlighting the boundaries of them. The first reference note after crossing a module boundary is likely the most interesting one.

2 files changed, 8 insertions(+), 35 deletions(-)

lib/std/heap/general_purpose_allocator.zig+2-6
......@@ -397,9 +397,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
397397 const prev = bucket.prev;
398398 if (config.never_unmap) {
399399 // free page that was intentionally leaked by never_unmap
400 const array_ptr = bucket.page[0..page_size];
401 comptime assert(@TypeOf(array_ptr) == *align(page_size) [page_size]u8);
402 self.backing_allocator.free(@as([]align(page_size) u8, array_ptr));
400 self.backing_allocator.free(bucket.page[0..page_size]);
403401 }
404402 // alloc_cursor was set to slot count when bucket added to empty_buckets
405403 self.freeBucket(bucket, @divExact(page_size, bucket.alloc_cursor));
......@@ -816,9 +814,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
816814 self.buckets[bucket_index] = bucket.prev;
817815 }
818816 if (!config.never_unmap) {
819 const array_ptr = bucket.page[0..page_size];
820 comptime assert(@TypeOf(array_ptr) == *align(page_size) [page_size]u8);
821 self.backing_allocator.free(@as([]align(page_size) u8, array_ptr));
817 self.backing_allocator.free(bucket.page[0..page_size]);
822818 }
823819 if (!config.retain_metadata) {
824820 self.freeBucket(bucket, size_class);
lib/std/mem/Allocator.zig+6-29
......@@ -109,7 +109,7 @@ pub fn create(self: Allocator, comptime T: type) Error!*T {
109109/// `ptr` should be the return value of `create`, or otherwise
110110/// have the same address and alignment property.
111111pub fn destroy(self: Allocator, ptr: anytype) void {
112 const info = ensureSlice(@TypeOf(ptr), "destroy", .One);
112 const info = @typeInfo(@TypeOf(ptr)).Pointer;
113113 const T = info.child;
114114 if (@sizeOf(T) == 0) return;
115115 const non_const_ptr = @intToPtr([*]u8, @ptrToInt(ptr));
......@@ -224,7 +224,7 @@ pub fn allocAdvancedWithRetAddr(
224224/// the pointer, however the allocator implementation may refuse the resize
225225/// request by returning `false`.
226226pub fn resize(self: Allocator, old_mem: anytype, new_n: usize) bool {
227 const Slice = ensureSlice(@TypeOf(old_mem), "resize", .Slice);
227 const Slice = @typeInfo(@TypeOf(old_mem)).Pointer;
228228 const T = Slice.child;
229229 if (new_n == 0) {
230230 self.free(old_mem);
......@@ -245,7 +245,7 @@ pub fn resize(self: Allocator, old_mem: anytype, new_n: usize) bool {
245245/// can be larger, smaller, or the same size as the old memory allocation.
246246/// If `new_n` is 0, this is the same as `free` and it always succeeds.
247247pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) t: {
248 const Slice = ensureSlice(@TypeOf(old_mem), "realloc", .Slice);
248 const Slice = @typeInfo(@TypeOf(old_mem)).Pointer;
249249 break :t Error![]align(Slice.alignment) Slice.child;
250250} {
251251 return self.reallocAdvanced(old_mem, new_n, @returnAddress());
......@@ -257,10 +257,10 @@ pub fn reallocAdvanced(
257257 new_n: usize,
258258 return_address: usize,
259259) t: {
260 const Slice = ensureSlice(@TypeOf(old_mem), "reallocAdvanced", .Slice);
260 const Slice = @typeInfo(@TypeOf(old_mem)).Pointer;
261261 break :t Error![]align(Slice.alignment) Slice.child;
262262} {
263 const Slice = ensureSlice(@TypeOf(old_mem), "reallocAdvanced", .Slice);
263 const Slice = @typeInfo(@TypeOf(old_mem)).Pointer;
264264 const T = Slice.child;
265265 if (old_mem.len == 0) {
266266 return self.allocAdvancedWithRetAddr(T, Slice.alignment, new_n, return_address);
......@@ -293,7 +293,7 @@ pub fn reallocAdvanced(
293293/// Free an array allocated with `alloc`. To free a single item,
294294/// see `destroy`.
295295pub fn free(self: Allocator, memory: anytype) void {
296 const Slice = ensureSlice(@TypeOf(memory), "free", .Slice);
296 const Slice = @typeInfo(@TypeOf(memory)).Pointer;
297297 const bytes = mem.sliceAsBytes(memory);
298298 const bytes_len = bytes.len + if (Slice.sentinel != null) @sizeOf(Slice.child) else 0;
299299 if (bytes_len == 0) return;
......@@ -318,29 +318,6 @@ pub fn dupeZ(allocator: Allocator, comptime T: type, m: []const T) ![:0]T {
318318 return new_buf[0..m.len :0];
319319}
320320
321inline fn ensureSlice(
322 comptime Type: type,
323 comptime function_name: []const u8,
324 comptime expected_size: std.builtin.Type.Pointer.Size,
325) std.builtin.Type.Pointer {
326 const expectation = switch (expected_size) {
327 .One => "a single item pointer",
328 .Slice => "a slice",
329 else => unreachable,
330 };
331 const type_info = @typeInfo(Type);
332
333 if (type_info == .Pointer) {
334 const pointer = type_info.Pointer;
335
336 if (pointer.size == expected_size) {
337 return pointer;
338 }
339 }
340
341 @compileError(std.fmt.comptimePrint("{s} expects {s} but received a value of type `{s}`", .{ function_name, expectation, @typeName(Type) }));
342}
343
344321/// TODO replace callsites with `@log2` after this proposal is implemented:
345322/// https://github.com/ziglang/zig/issues/13642
346323inline fn log2a(x: anytype) switch (@typeInfo(@TypeOf(x))) {