Skip to content
zit Artifact [08734442b3]
Login

Artifact [08734442b3]

Artifact 08734442b3b3f3192578c62abc156cd347d1d3d6bf25655d2b66d100bd592027:


//! An allocator that never grows or shrinks a block in place, so every
//! growth is a fresh allocation an allocation-failure walk can count.
//!
//! Since Zig 0.17, `Allocator.print` and list growth first try an in-place
//! remap, and whether that succeeds depends on heap state left by earlier
//! runs and on the platform. `std.testing.checkAllAllocationFailures` needs
//! the same allocation count on every run, so the walks that trip on this
//! wrap `std.testing.allocator` in one of these.
const std = @import("std");

const NoGrowAllocator = @This();

inner: std.mem.Allocator,

pub fn init(inner: std.mem.Allocator) NoGrowAllocator {
    return .{ .inner = inner };
}

pub fn allocator(self: *NoGrowAllocator) std.mem.Allocator {
    return .{ .ptr = self, .vtable = &.{ .alloc = alloc, .resize = resize, .remap = remap, .free = free } };
}

fn alloc(ctx: *anyopaque, len: usize, alignment: std.mem.Alignment, ret_addr: usize) ?[*]u8 {
    const self: *NoGrowAllocator = @ptrCast(@alignCast(ctx));
    return self.inner.rawAlloc(len, alignment, ret_addr);
}

fn resize(_: *anyopaque, _: []u8, _: std.mem.Alignment, _: usize, _: usize) bool {
    return false;
}

fn remap(_: *anyopaque, _: []u8, _: std.mem.Alignment, _: usize, _: usize) ?[*]u8 {
    return null;
}

fn free(ctx: *anyopaque, memory: []u8, alignment: std.mem.Alignment, ret_addr: usize) void {
    const self: *NoGrowAllocator = @ptrCast(@alignCast(ctx));
    self.inner.rawFree(memory, alignment, ret_addr);
}

test "every growth is a fresh allocation" {
    var no_grow = NoGrowAllocator.init(std.testing.allocator);
    const gpa = no_grow.allocator();
    var list: std.ArrayList(u8) = .empty;
    defer list.deinit(gpa);
    try list.appendSlice(gpa, "abc");
    const before = list.items.ptr;
    try list.ensureTotalCapacity(gpa, 4096);
    try std.testing.expect(list.items.ptr != before);
    try std.testing.expectEqualStrings("abc", list.items);
}