#Allocators

1 messages · Page 1 of 1 (latest)

timid spruce
#

I'm trying to implement a dynamic array in Zig.
As a way of instantiating it, I have:

    fn newWithAllocator(comptime T: type, allocator: Allocator) !Self {
        const ptr = try allocator.create(T);
        return Self{ .allocator = allocator, .ptr = ptr, .len = 0, .cap = 0 };
    }

When I try to use it with the testing allocator like so:

test "basic functionality" {
    const a = testing.allocator;
    const vector = JoyVector.newWithAllocator(u8, a);
    std.debug.print("", .{vector});
}
#

I get:
I get:

zig test src/root.zig
/nix/store/x2s18vm0lxahz7bvpprflm8k3s4zwz94-zig-0.13.0/lib/zig/std/Thread.zig:1050:30: error: unable to evaluate comptime expression
        return tls_thread_id orelse {
               ~~~~~~~~~~~~~~^~~~~~
/nix/store/x2s18vm0lxahz7bvpprflm8k3s4zwz94-zig-0.13.0/lib/zig/std/Thread.zig:277:29: note: called from here
    return Impl.getCurrentId();
           ~~~~~~~~~~~~~~~~~^~
/nix/store/x2s18vm0lxahz7bvpprflm8k3s4zwz94-zig-0.13.0/lib/zig/std/Thread/Mutex.zig:80:47: note: called from here
        const current_id = Thread.getCurrentId();
                           ~~~~~~~~~~~~~~~~~~~^~
/nix/store/x2s18vm0lxahz7bvpprflm8k3s4zwz94-zig-0.13.0/lib/zig/std/Thread/Mutex.zig:44:19: note: called from here
    self.impl.lock();
    ~~~~~~~~~~~~~~^~
/nix/store/x2s18vm0lxahz7bvpprflm8k3s4zwz94-zig-0.13.0/lib/zig/std/heap/general_purpose_allocator.zig:971:28: note: called from here
            self.mutex.lock();
            ~~~~~~~~~~~~~~~^~
/nix/store/x2s18vm0lxahz7bvpprflm8k3s4zwz94-zig-0.13.0/lib/zig/std/mem/Allocator.zig:86:29: note: called from here
    return self.vtable.alloc(self.ptr, len, ptr_align, ret_addr);
           ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/nix/store/x2s18vm0lxahz7bvpprflm8k3s4zwz94-zig-0.13.0/lib/zig/std/mem/Allocator.zig:225:35: note: called from here
    const byte_ptr = self.rawAlloc(byte_count, log2a(alignment), return_address) orelse return Error.OutOfMemory;
                     ...

                        ~~~~~~~~~~~~~~~~^~~
src/root.zig:77:46: note: called from here
    const vector = JoyVector.newWithAllocator(u8, a);
vestal pike
#

can you provide the field definitions of your JoyVector type?

timid spruce
#

Will do

tulip ember
#

also curious if you can try zig 0.14 since some of these errors were improved (most of them now say why certain code is running at comptime, because that's not always intuitive)

timid spruce
#
    const Self = @This();
    allocator: Allocator = undefined,
    ptr: *type = undefined,
    len: usize,
    cap: usize,

timid spruce
tulip ember
#

@halcyon osprey how install zig 0.14 on nixos

timid spruce
tulip ember
#

so it makes the entire struct comptime

halcyon osprey
timid spruce
#

*won't be defined

vestal pike
# timid spruce ```zig const Self = @This(); allocator: Allocator = undefined, ptr: ...

yeah alright this is indeed the problem.
the ptr field is of type *type, so, "pointer to a single (mutable) type" - this type is comptime-only and so it forces the computation of JoyVector.newWithAllocator to happen entirely at compile-time (by virtue of the return type being comptime-only). the inner allocation function does not work at compile time and so it fails. see @tulip ember's message for a solution

timid spruce
tulip ember
#

should this be a type function?

vestal pike
timid spruce
#
const JoyVector = struct {
    const Self = @This();
    allocator: Allocator = undefined,
    ptr: *T = undefined, //just modified
    len: usize,
    cap: usize,

    fn new(
        comptime T: type,
    ) !Self {
        const ptr = try alloc.create(T);
        return Self{ .allocator = alloc, .ptr = ptr, .len = 0, .cap = 0 };
    }

    fn newWithAllocator(comptime T: type, allocator: Allocator) !Self {
        const ptr = try allocator.create(T);
        return Self{ .allocator = allocator, .ptr = ptr, .len = 0, .cap = 0 };
    }

    fn newFromSlice(comptime T: type, slice: []T) !Self {
        const len = slice.len;
        const cap = len;
        const ptr = try alloc.alloc(T, len);
        const rptr = ptr.ptr;
        std.mem.copyForwards(T, rptr, slice);
        return Self{
            .allocator = alloc,
            .ptr = rptr,
            .len = len,
            .cap = cap,
        };
    }

    fn newFromSliceWithAllocator(comptime T: type, allocator: Allocator, slice: []T) !Self {
        const len = slice.len;
        const ptr = try allocator.alloc(T, len);
        const rptr = ptr.ptr;
        std.mem.copyForwards(T, rptr, slice);
        return Self{
            .allocator = allocator,
            .ptr = rptr,
            .len = len,
            .cap = len,
        };
    }
};
halcyon osprey
vestal pike
halcyon osprey
#

Ctrl f zig overlay in here

vestal pike
#

I suggest you have a read of this part of the language reference

timid spruce
#

So I have to define the struct in the functio?

vestal pike
#

correct

timid spruce
#

I see, but in the stdlib, ArrayListUnaligned is not defined in ArrayList

#

*Aligned

vestal pike
#

ArrayList wraps ArrayListAligned, which guarantees a certain alignment for the first stored item. ArrayList is there for the common case where you want the alignment of the elements be their natural alignment

timid spruce
#

Is there no way I can define the struct externally, so that the defining function isn't long and ugly asf

timid spruce
vestal pike
#

the usual way to go about defining generic types is to actually write out their methods all in the big wrapping function - it might be a bit ugly and indent-y, but that's how it is

timid spruce
#

Thank you very much

timid spruce
vestal pike
timid spruce
vestal pike