What does "error: expected type '*T', found '*const T" mean? (Where T is some type)

I’m fairly new to Zig so I might be missing something obvious.
But in any case, I have the following error but I’m not sure what to make of it:

~/src/main.zig:82:39: error: expected type '*mem.Allocator', found '*const mem.Allocator'
        var conv = try Converter.init(&arena.allocator(), std.io.getStdOut().writer(), bufSize);
                                      ^~~~~~~~~~~~~~~~~~
~/src/main.zig:82:39: note: cast discards const qualifier
referenced by:
    comptime_0: /usr/local/Cellar/zig/0.10.1/lib/zig/std/start.zig:59:50
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

And the code that generates it:

// in main.zig
const std = @import("std");
const Converter = @import("./converter.zig").Converter;

pub fn main() !void {
  var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
  defer arena.deinit();

  var conv = try Converter.init(&arena.allocator(), std.io.getStdOut().writer(), bufSize);
  // other operations
}

And in converter.zig:

const std = @import("std");

pub const Converter = struct {
    const BufferedWriter = std.io.BufferedWriter(4096, std.fs.File.Writer);

    allocator: *std.mem.Allocator,
    csvBuf: []u8,
    hdrBuf: []u8,
    rowBuf: []u8,
    keys: [][]const u8,
    out: BufferedWriter,

    const Self = @This();

    // Initialize the converter.
    pub fn init(allocator: *std.mem.Allocator, writer: anytype, rowBufSize: u32) !Self {
        var s = Converter{
            .allocator = allocator,
            .out = std.io.bufferedWriter(writer),
            .csvBuf = try allocator.alloc(u8, rowBufSize),
            .hdrBuf = try allocator.alloc(u8, rowBufSize),
            .rowBuf = try allocator.alloc(u8, rowBufSize),
            .keys = undefined,
        };

        return s;
    }

// other methods like `deinit()` etc

What I’d like to understand the point where this const comes into play.

Welcome to the forum!

You’re returning the allocator directly from its construction with &arena.allocator() here:

var conv = try Converter.init(&arena.allocator(), std.io.getStdOut().writer(), bufSize);

Variables are immutable unless defined otherwise.

It will work if you instead do this:

var allocator = arena.allocator();
var conv = try Converter.init(&allocator, std.io.getStdOut().writer(), bufSize);

Which first defines it as a mutable variable and then passes a reference to that mutable variable into Converter.init

This error just means it expected a mutable reference but received an immutable one

1 Like

Aha!! Makes sense. This was such an oversight from me. Thank you :slight_smile:

2 Likes

No problem at all!

If you run into anything else feel free to ask away :slightly_smiling_face:

1 Like

Note that passing the allocator by pointer is not the way to do things anymore (since Allocgate by leecannon · Pull Request #10055 · ziglang/zig · GitHub which changed allocator into a function [instead of a field that you’d take the pointer of]). Your init function should therefore just take

allocator: std.mem.Allocator

and same for the allocator field of the Converter struct.

1 Like

Interesting. Thanks for letting me know. I’ll read up more on that and change my code accordingly :smiley: