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

This reverts commit abc9530a88.

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.
This commit is contained in:
Andrew Kelley
2023-02-12 05:59:28 -07:00
parent abc9530a88
commit 3c2a43fdcc
2 changed files with 8 additions and 35 deletions

View File

@@ -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);

View File

@@ -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))) {