Commit 3c2a43fdcc

Andrew Kelley <andrew@ziglang.org>
2023-02-12 13:59:28
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.
1 parent abc9530
Changed files (2)
lib/std/heap/general_purpose_allocator.zig
@@ -397,9 +397,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
                         const prev = bucket.prev;
                         if (config.never_unmap) {
                             // free page that was intentionally leaked by never_unmap
-                            const array_ptr = bucket.page[0..page_size];
-                            comptime assert(@TypeOf(array_ptr) == *align(page_size) [page_size]u8);
-                            self.backing_allocator.free(@as([]align(page_size) u8, array_ptr));
+                            self.backing_allocator.free(bucket.page[0..page_size]);
                         }
                         // alloc_cursor was set to slot count when bucket added to empty_buckets
                         self.freeBucket(bucket, @divExact(page_size, bucket.alloc_cursor));
@@ -816,9 +814,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
                     self.buckets[bucket_index] = bucket.prev;
                 }
                 if (!config.never_unmap) {
-                    const array_ptr = bucket.page[0..page_size];
-                    comptime assert(@TypeOf(array_ptr) == *align(page_size) [page_size]u8);
-                    self.backing_allocator.free(@as([]align(page_size) u8, array_ptr));
+                    self.backing_allocator.free(bucket.page[0..page_size]);
                 }
                 if (!config.retain_metadata) {
                     self.freeBucket(bucket, size_class);
lib/std/mem/Allocator.zig
@@ -109,7 +109,7 @@ pub fn create(self: Allocator, comptime T: type) Error!*T {
 /// `ptr` should be the return value of `create`, or otherwise
 /// have the same address and alignment property.
 pub fn destroy(self: Allocator, ptr: anytype) void {
-    const info = ensureSlice(@TypeOf(ptr), "destroy", .One);
+    const info = @typeInfo(@TypeOf(ptr)).Pointer;
     const T = info.child;
     if (@sizeOf(T) == 0) return;
     const non_const_ptr = @intToPtr([*]u8, @ptrToInt(ptr));
@@ -224,7 +224,7 @@ pub fn allocAdvancedWithRetAddr(
 /// the pointer, however the allocator implementation may refuse the resize
 /// request by returning `false`.
 pub fn resize(self: Allocator, old_mem: anytype, new_n: usize) bool {
-    const Slice = ensureSlice(@TypeOf(old_mem), "resize", .Slice);
+    const Slice = @typeInfo(@TypeOf(old_mem)).Pointer;
     const T = Slice.child;
     if (new_n == 0) {
         self.free(old_mem);
@@ -245,7 +245,7 @@ pub fn resize(self: Allocator, old_mem: anytype, new_n: usize) bool {
 /// can be larger, smaller, or the same size as the old memory allocation.
 /// If `new_n` is 0, this is the same as `free` and it always succeeds.
 pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) t: {
-    const Slice = ensureSlice(@TypeOf(old_mem), "realloc", .Slice);
+    const Slice = @typeInfo(@TypeOf(old_mem)).Pointer;
     break :t Error![]align(Slice.alignment) Slice.child;
 } {
     return self.reallocAdvanced(old_mem, new_n, @returnAddress());
@@ -257,10 +257,10 @@ pub fn reallocAdvanced(
     new_n: usize,
     return_address: usize,
 ) t: {
-    const Slice = ensureSlice(@TypeOf(old_mem), "reallocAdvanced", .Slice);
+    const Slice = @typeInfo(@TypeOf(old_mem)).Pointer;
     break :t Error![]align(Slice.alignment) Slice.child;
 } {
-    const Slice = ensureSlice(@TypeOf(old_mem), "reallocAdvanced", .Slice);
+    const Slice = @typeInfo(@TypeOf(old_mem)).Pointer;
     const T = Slice.child;
     if (old_mem.len == 0) {
         return self.allocAdvancedWithRetAddr(T, Slice.alignment, new_n, return_address);
@@ -293,7 +293,7 @@ pub fn reallocAdvanced(
 /// Free an array allocated with `alloc`. To free a single item,
 /// see `destroy`.
 pub fn free(self: Allocator, memory: anytype) void {
-    const Slice = ensureSlice(@TypeOf(memory), "free", .Slice);
+    const Slice = @typeInfo(@TypeOf(memory)).Pointer;
     const bytes = mem.sliceAsBytes(memory);
     const bytes_len = bytes.len + if (Slice.sentinel != null) @sizeOf(Slice.child) else 0;
     if (bytes_len == 0) return;
@@ -318,29 +318,6 @@ pub fn dupeZ(allocator: Allocator, comptime T: type, m: []const T) ![:0]T {
     return new_buf[0..m.len :0];
 }
 
-inline fn ensureSlice(
-    comptime Type: type,
-    comptime function_name: []const u8,
-    comptime expected_size: std.builtin.Type.Pointer.Size,
-) std.builtin.Type.Pointer {
-    const expectation = switch (expected_size) {
-        .One => "a single item pointer",
-        .Slice => "a slice",
-        else => unreachable,
-    };
-    const type_info = @typeInfo(Type);
-
-    if (type_info == .Pointer) {
-        const pointer = type_info.Pointer;
-
-        if (pointer.size == expected_size) {
-            return pointer;
-        }
-    }
-
-    @compileError(std.fmt.comptimePrint("{s} expects {s} but received a value of type `{s}`", .{ function_name, expectation, @typeName(Type) }));
-}
-
 /// TODO replace callsites with `@log2` after this proposal is implemented:
 /// https://github.com/ziglang/zig/issues/13642
 inline fn log2a(x: anytype) switch (@typeInfo(@TypeOf(x))) {