#error: expected type ‘*T’, found ‘*const T’ when passing allocator from struct to ArrayList

1 messages · Page 1 of 1 (latest)

rich pier
#

I have the following code (part of it) for Bencode BitTorrent decoder. I looked through other questions and learned that function arguments are immutable, hence the *const. How to fix this code?

pub const Bencoder = struct {
    arena_allocator: std.heap.ArenaAllocator,

    pub fn init(arena_child_allocator: std.mem.Allocator) @This() {
        return .{ .arena_allocator = std.heap.ArenaAllocator.init(arena_child_allocator) };
    }

    pub fn deinit(self: @This()) void {
        log.debug("Freeing memory from arena allocator for Bencoder", .{});
        self.arena_allocator.deinit();
    }

    ...

I want to have an arena allocator to be able to free all memory at once when decoding is done. Passing child allocator is done in the init() function. Below is the code when I pass allocator to ArrayList:

var list = std.ArrayList(Value).init(self.arena_allocator.allocator());

Test code:

test "should decode integers" {
    const b = Bencoder.init(std.testing.allocator);
    defer b.deinit();

    const fourty_two = b.decode("i42e") catch unreachable;
    const minus_fourty_two = b.decode("i-42e") catch unreachable;
    const zero = b.decode("i0e") catch unreachable;

    try std.testing.expect(fourty_two.value.integer == 42);
    try std.testing.expect(fourty_two.read == 4);
    try std.testing.expect(minus_fourty_two.value.integer == -42);
    try std.testing.expect(minus_fourty_two.read == 5);
    try std.testing.expect(zero.value.integer == 0);
    try std.testing.expect(zero.read == 3);
}

And the error I am getting:

src\encoding\bencode.zig:77:74: error: expected type '*heap.arena_allocator.ArenaAllocator', found '*const heap.arena_allocator.ArenaAllocator'
                var list = std.ArrayList(Value).init(self.arena_allocator.allocator());
                                                     ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
src\encoding\bencode.zig:77:74: note: cast discards const qualifier
C:\Users\Johnny\scoop\persist\zigup\zig\0.14.0-dev.224+95d9292a7\files\lib\std\heap\arena_allocator.zig:26:28: note: parameter type declared here
    pub fn allocator(self: *ArenaAllocator) Allocator {
                           ^~~~~~~~~~~~~~~
referenced by:
    test.should decode integers: src\encoding\bencode.zig:133:32

Process finished with exit code 1
#

error: expected type ‘*T’, found ‘*const T when passing allocator from struct to ArrayList

#

error: expected type ‘*T’, found ‘*const T‘ when passing allocator from struct to ArrayList

#

error: expected type ‘*T’, found ‘*const T’ when passing allocator from struct to ArrayList

teal wagon
#

if you need to mutate a field in self, do self: *@This() instead of self: @This()

honest gazelle
#

b is declared const so pointers to it are const as well.

rich pier
#

@honest gazelle When I change to var I get the same error

teal wagon
#

arena_allocator.allocator() expects arena_allocator to be mutable (it takes it as a *ArenaAllocator) but since self is immutable, it’s arena_allocator field is also immutable

rich pier
#

@teal wagon And I get this error with *@This:

src\encoding\bencode.zig:82:82: error: expected type '*encoding.bencode.Bencoder', found 'mem.Allocator'
                    const decoded_val = try decode(self.arena_allocator.allocator(), encoded_value[idx..]);
                                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
C:\Users\Johnny\scoop\persist\zigup\zig\0.14.0-dev.224+95d9292a7\files\lib\std\mem\Allocator.zig:1:1: note: struct declared here
//! The standard memory allocation interface.
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src\encoding\bencode.zig:31:25: note: parameter type declared here
    pub fn decode(self: *@This(), encoded_value: []const u8) !DecodedValue {
teal wagon
#

I mean yeah, youre trying to pass an allocator as an argument to a function that wants a Bencoder

honest gazelle
rich pier
#

@teal wagon When I use *@This() I lon longer can use b.decode()

    const b = Bencoder.init(std.testing.allocator);
    defer b.deinit();
    const fourty_two = b.decode("i42e") catch unreachable;
teal wagon
#

yeah because b is immutable and *This() has to be mutable

rich pier
#

Aaa, b is @This not *@This()

teal wagon
#

just do var b = …; instead

honest gazelle
#

oohhh look at that - I wasn't wrong after all!

teal wagon
#

b.foo() is syntax sugar so it will automatically pass b by reference for you, it doesnt need to already be a pointer

rich pier
#

Progress, now getting:

src\encoding\bencode.zig:23:66: error: type '*encoding.bencode.Bencoder' does not support struct initialization syntax
        return .{ .arena_allocator = std.heap.ArenaAllocator.init(arena_child_allocator) };
teal wagon
#

why did you make init return a pointer, that doesnt make any sense

#

make sure you understand stuff before you change it everywhere
*@This() is a completely different type than @This() you cant use them interchangeably

rich pier
#

I know what the bug was now. I had recursive calls inside decoding function, that was calling decode(...) instead of self.decode(...) facepalm

#

So the correct signature is: pub fn decode(self: *@This(), encoded_value: []const u8) !DecodedValue {...}